Line data Source code
1 : /*
2 : * Copyright (C) 2003 Yasuhiro Ohara
3 : *
4 : * This file is part of GNU Zebra.
5 : *
6 : * GNU Zebra is free software; you can redistribute it and/or modify it
7 : * under the terms of the GNU General Public License as published by the
8 : * Free Software Foundation; either version 2, or (at your option) any
9 : * later version.
10 : *
11 : * GNU Zebra is distributed in the hope that it will be useful, but
12 : * WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : * General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU General Public License along
17 : * with this program; see the file COPYING; if not, write to the Free Software
18 : * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 : */
20 :
21 : #include <zebra.h>
22 :
23 : #include "log.h"
24 : #include "vty.h"
25 : #include "command.h"
26 : #include "prefix.h"
27 : #include "stream.h"
28 : #include "zclient.h"
29 : #include "memory.h"
30 : #include "route_opaque.h"
31 : #include "lib/bfd.h"
32 : #include "lib_errors.h"
33 :
34 : #include "ospf6_proto.h"
35 : #include "ospf6_top.h"
36 : #include "ospf6_interface.h"
37 : #include "ospf6_route.h"
38 : #include "ospf6_lsa.h"
39 : #include "ospf6_lsdb.h"
40 : #include "ospf6_asbr.h"
41 : #include "ospf6_nssa.h"
42 : #include "ospf6_zebra.h"
43 : #include "ospf6d.h"
44 : #include "ospf6_area.h"
45 : #include "ospf6_gr.h"
46 : #include "lib/json.h"
47 :
48 48 : DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_DISTANCE, "OSPF6 distance");
49 :
50 : unsigned char conf_debug_ospf6_zebra = 0;
51 :
52 : /* information about zebra. */
53 : struct zclient *zclient = NULL;
54 :
55 16 : void ospf6_zebra_vrf_register(struct ospf6 *ospf6)
56 : {
57 16 : if (!zclient || zclient->sock < 0 || !ospf6)
58 : return;
59 :
60 16 : if (ospf6->vrf_id != VRF_UNKNOWN) {
61 16 : if (IS_OSPF6_DEBUG_ZEBRA(RECV)) {
62 0 : zlog_debug("%s: Register VRF %s id %u", __func__,
63 : ospf6_vrf_id_to_name(ospf6->vrf_id),
64 : ospf6->vrf_id);
65 : }
66 16 : zclient_send_reg_requests(zclient, ospf6->vrf_id);
67 : }
68 : }
69 :
70 16 : void ospf6_zebra_vrf_deregister(struct ospf6 *ospf6)
71 : {
72 16 : if (!zclient || zclient->sock < 0 || !ospf6)
73 : return;
74 :
75 16 : if (ospf6->vrf_id != VRF_DEFAULT && ospf6->vrf_id != VRF_UNKNOWN) {
76 0 : if (IS_OSPF6_DEBUG_ZEBRA(RECV)) {
77 0 : zlog_debug("%s: De-Register VRF %s id %u to Zebra.",
78 : __func__,
79 : ospf6_vrf_id_to_name(ospf6->vrf_id),
80 : ospf6->vrf_id);
81 : }
82 : /* Deregister for router-id, interfaces,
83 : * redistributed routes. */
84 0 : zclient_send_dereg_requests(zclient, ospf6->vrf_id);
85 : }
86 : }
87 :
88 : /* Router-id update message from zebra. */
89 32 : static int ospf6_router_id_update_zebra(ZAPI_CALLBACK_ARGS)
90 : {
91 32 : struct prefix router_id;
92 32 : struct ospf6 *o;
93 :
94 32 : zebra_router_id_update_read(zclient->ibuf, &router_id);
95 :
96 32 : if (IS_OSPF6_DEBUG_ZEBRA(RECV))
97 0 : zlog_debug("Zebra router-id update %pI4 vrf %s id %u",
98 : &router_id.u.prefix4, ospf6_vrf_id_to_name(vrf_id),
99 : vrf_id);
100 :
101 32 : o = ospf6_lookup_by_vrf_id(vrf_id);
102 32 : if (o == NULL)
103 : return 0;
104 :
105 32 : o->router_id_zebra = router_id.u.prefix4.s_addr;
106 :
107 32 : ospf6_router_id_update(o, false);
108 :
109 32 : return 0;
110 : }
111 :
112 : /* redistribute function */
113 5 : void ospf6_zebra_redistribute(int type, vrf_id_t vrf_id)
114 : {
115 5 : if (vrf_bitmap_check(zclient->redist[AFI_IP6][type], vrf_id))
116 : return;
117 5 : vrf_bitmap_set(zclient->redist[AFI_IP6][type], vrf_id);
118 :
119 5 : if (zclient->sock > 0)
120 5 : zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient,
121 : AFI_IP6, type, 0, vrf_id);
122 : }
123 :
124 5 : void ospf6_zebra_no_redistribute(int type, vrf_id_t vrf_id)
125 : {
126 5 : if (!vrf_bitmap_check(zclient->redist[AFI_IP6][type], vrf_id))
127 : return;
128 5 : vrf_bitmap_unset(zclient->redist[AFI_IP6][type], vrf_id);
129 5 : if (zclient->sock > 0)
130 5 : zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
131 : AFI_IP6, type, 0, vrf_id);
132 : }
133 :
134 0 : void ospf6_zebra_import_default_route(struct ospf6 *ospf6, bool unreg)
135 : {
136 0 : struct prefix prefix = {};
137 0 : int command;
138 :
139 0 : if (zclient->sock < 0) {
140 0 : if (IS_OSPF6_DEBUG_ZEBRA(SEND))
141 0 : zlog_debug(" Not connected to Zebra");
142 0 : return;
143 : }
144 :
145 0 : prefix.family = AF_INET6;
146 0 : prefix.prefixlen = 0;
147 :
148 0 : if (unreg)
149 : command = ZEBRA_NEXTHOP_UNREGISTER;
150 : else
151 0 : command = ZEBRA_NEXTHOP_REGISTER;
152 :
153 0 : if (IS_OSPF6_DEBUG_ZEBRA(SEND))
154 0 : zlog_debug("%s: sending cmd %s for %pFX (vrf %u)", __func__,
155 : zserv_command_string(command), &prefix,
156 : ospf6->vrf_id);
157 :
158 0 : if (zclient_send_rnh(zclient, command, &prefix, SAFI_UNICAST, false,
159 : true, ospf6->vrf_id)
160 : == ZCLIENT_SEND_FAILURE)
161 0 : flog_err(EC_LIB_ZAPI_SOCKET, "%s: zclient_send_rnh() failed",
162 : __func__);
163 : }
164 :
165 0 : static int ospf6_zebra_import_check_update(ZAPI_CALLBACK_ARGS)
166 : {
167 0 : struct ospf6 *ospf6;
168 0 : struct zapi_route nhr;
169 0 : struct prefix matched;
170 :
171 0 : ospf6 = ospf6_lookup_by_vrf_id(vrf_id);
172 0 : if (ospf6 == NULL || !IS_OSPF6_ASBR(ospf6))
173 : return 0;
174 :
175 0 : if (!zapi_nexthop_update_decode(zclient->ibuf, &matched, &nhr)) {
176 0 : zlog_err("%s[%u]: Failure to decode route", __func__,
177 : ospf6->vrf_id);
178 0 : return -1;
179 : }
180 :
181 0 : if (matched.family != AF_INET6 || matched.prefixlen != 0 ||
182 0 : nhr.type == ZEBRA_ROUTE_OSPF6)
183 : return 0;
184 :
185 0 : ospf6->nssa_default_import_check.status = !!nhr.nexthop_num;
186 0 : ospf6_abr_nssa_type_7_defaults(ospf6);
187 :
188 0 : return 0;
189 : }
190 :
191 267 : static int ospf6_zebra_if_address_update_add(ZAPI_CALLBACK_ARGS)
192 : {
193 267 : struct connected *c;
194 :
195 267 : c = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD,
196 : zclient->ibuf, vrf_id);
197 267 : if (c == NULL)
198 : return 0;
199 :
200 267 : if (IS_OSPF6_DEBUG_ZEBRA(RECV))
201 0 : zlog_debug("Zebra Interface address add: %s %5s %pFX",
202 : c->ifp->name, prefix_family_str(c->address),
203 : c->address);
204 :
205 267 : if (c->address->family == AF_INET6) {
206 123 : ospf6_interface_state_update(c->ifp);
207 123 : ospf6_interface_connected_route_update(c->ifp);
208 : }
209 : return 0;
210 : }
211 :
212 19 : static int ospf6_zebra_if_address_update_delete(ZAPI_CALLBACK_ARGS)
213 : {
214 19 : struct connected *c;
215 :
216 19 : c = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE,
217 : zclient->ibuf, vrf_id);
218 19 : if (c == NULL)
219 : return 0;
220 :
221 19 : if (IS_OSPF6_DEBUG_ZEBRA(RECV))
222 0 : zlog_debug("Zebra Interface address delete: %s %5s %pFX",
223 : c->ifp->name, prefix_family_str(c->address),
224 : c->address);
225 :
226 19 : if (c->address->family == AF_INET6) {
227 9 : ospf6_interface_connected_route_update(c->ifp);
228 9 : ospf6_interface_state_update(c->ifp);
229 : }
230 :
231 19 : connected_free(&c);
232 :
233 19 : return 0;
234 : }
235 :
236 0 : static int ospf6_zebra_gr_update(struct ospf6 *ospf6, int command,
237 : uint32_t stale_time)
238 : {
239 0 : struct zapi_cap api;
240 :
241 0 : if (!zclient || zclient->sock < 0 || !ospf6)
242 : return 1;
243 :
244 0 : memset(&api, 0, sizeof(api));
245 0 : api.cap = command;
246 0 : api.stale_removal_time = stale_time;
247 0 : api.vrf_id = ospf6->vrf_id;
248 :
249 0 : (void)zclient_capabilities_send(ZEBRA_CLIENT_CAPABILITIES, zclient,
250 : &api);
251 :
252 0 : return 0;
253 : }
254 :
255 0 : int ospf6_zebra_gr_enable(struct ospf6 *ospf6, uint32_t stale_time)
256 : {
257 0 : return ospf6_zebra_gr_update(ospf6, ZEBRA_CLIENT_GR_CAPABILITIES,
258 : stale_time);
259 : }
260 :
261 0 : int ospf6_zebra_gr_disable(struct ospf6 *ospf6)
262 : {
263 0 : return ospf6_zebra_gr_update(ospf6, ZEBRA_CLIENT_GR_DISABLE, 0);
264 : }
265 :
266 76 : static int ospf6_zebra_read_route(ZAPI_CALLBACK_ARGS)
267 : {
268 76 : struct zapi_route api;
269 76 : unsigned long ifindex;
270 76 : struct in6_addr *nexthop;
271 76 : struct ospf6 *ospf6;
272 76 : struct prefix_ipv6 p;
273 :
274 76 : ospf6 = ospf6_lookup_by_vrf_id(vrf_id);
275 :
276 76 : if (ospf6 == NULL)
277 : return 0;
278 :
279 76 : if (zapi_route_decode(zclient->ibuf, &api) < 0)
280 : return -1;
281 :
282 : /* we completely ignore srcdest routes for now. */
283 76 : if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
284 : return 0;
285 :
286 76 : if (IN6_IS_ADDR_LINKLOCAL(&api.prefix.u.prefix6))
287 : return 0;
288 :
289 76 : ifindex = api.nexthops[0].ifindex;
290 76 : nexthop = &api.nexthops[0].gate.ipv6;
291 :
292 76 : if (IS_OSPF6_DEBUG_ZEBRA(RECV))
293 0 : zlog_debug(
294 : "Zebra Receive route %s: %s %pFX nexthop %pI6 ifindex %ld tag %" ROUTE_TAG_PRI,
295 : (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD ? "add"
296 : : "delete"),
297 : zebra_route_string(api.type), &api.prefix, nexthop,
298 : ifindex, api.tag);
299 :
300 76 : memcpy(&p, &api.prefix, sizeof(p));
301 76 : if (is_default_prefix6(&p))
302 0 : api.type = DEFAULT_ROUTE;
303 :
304 76 : if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
305 60 : ospf6_asbr_redistribute_add(api.type, ifindex, &api.prefix,
306 60 : api.nexthop_num, nexthop, api.tag,
307 : ospf6);
308 : else
309 16 : ospf6_asbr_redistribute_remove(api.type, ifindex, &api.prefix,
310 : ospf6);
311 :
312 : return 0;
313 : }
314 :
315 0 : DEFUN(show_zebra,
316 : show_ospf6_zebra_cmd,
317 : "show ipv6 ospf6 zebra [json]",
318 : SHOW_STR
319 : IPV6_STR
320 : OSPF6_STR
321 : ZEBRA_STR
322 : JSON_STR)
323 : {
324 0 : int i;
325 0 : bool uj = use_json(argc, argv);
326 0 : json_object *json;
327 0 : json_object *json_zebra;
328 0 : json_object *json_array;
329 :
330 0 : if (zclient == NULL) {
331 0 : vty_out(vty, "Not connected to zebra\n");
332 0 : return CMD_SUCCESS;
333 : }
334 :
335 0 : if (uj) {
336 0 : json = json_object_new_object();
337 0 : json_zebra = json_object_new_object();
338 0 : json_array = json_object_new_array();
339 :
340 0 : json_object_int_add(json_zebra, "fail", zclient->fail);
341 0 : json_object_int_add(
342 : json_zebra, "redistributeDefault",
343 0 : vrf_bitmap_check(zclient->default_information[AFI_IP6],
344 : VRF_DEFAULT));
345 0 : for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
346 0 : if (vrf_bitmap_check(zclient->redist[AFI_IP6][i],
347 : VRF_DEFAULT))
348 0 : json_object_array_add(
349 : json_array,
350 : json_object_new_string(
351 : zebra_route_string(i)));
352 : }
353 0 : json_object_object_add(json_zebra, "redistribute", json_array);
354 0 : json_object_object_add(json, "zebraInformation", json_zebra);
355 :
356 0 : vty_json(vty, json);
357 : } else {
358 0 : vty_out(vty, "Zebra Information\n");
359 0 : vty_out(vty, " fail: %d\n", zclient->fail);
360 0 : vty_out(vty, " redistribute default: %d\n",
361 0 : vrf_bitmap_check(zclient->default_information[AFI_IP6],
362 : VRF_DEFAULT));
363 0 : vty_out(vty, " redistribute:");
364 0 : for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
365 0 : if (vrf_bitmap_check(zclient->redist[AFI_IP6][i],
366 : VRF_DEFAULT))
367 0 : vty_out(vty, " %s", zebra_route_string(i));
368 : }
369 0 : vty_out(vty, "\n");
370 : }
371 : return CMD_SUCCESS;
372 : }
373 :
374 0 : static void ospf6_zebra_append_opaque_attr(struct ospf6_route *request,
375 : struct zapi_route *api)
376 : {
377 0 : struct ospf_zebra_opaque ospf_opaque = {};
378 :
379 : /* OSPF path type */
380 0 : snprintf(ospf_opaque.path_type, sizeof(ospf_opaque.path_type), "%s",
381 0 : OSPF6_PATH_TYPE_NAME(request->path.type));
382 :
383 0 : switch (request->path.type) {
384 0 : case OSPF6_PATH_TYPE_INTRA:
385 : case OSPF6_PATH_TYPE_INTER:
386 : /* OSPF area ID */
387 0 : (void)inet_ntop(AF_INET, &request->path.area_id,
388 : ospf_opaque.area_id,
389 : sizeof(ospf_opaque.area_id));
390 0 : break;
391 0 : case OSPF6_PATH_TYPE_EXTERNAL1:
392 : case OSPF6_PATH_TYPE_EXTERNAL2:
393 : /* OSPF route tag */
394 0 : snprintf(ospf_opaque.tag, sizeof(ospf_opaque.tag), "%u",
395 : request->path.tag);
396 0 : break;
397 : default:
398 : break;
399 : }
400 :
401 0 : SET_FLAG(api->message, ZAPI_MESSAGE_OPAQUE);
402 0 : api->opaque.length = sizeof(struct ospf_zebra_opaque);
403 0 : memcpy(api->opaque.data, &ospf_opaque, api->opaque.length);
404 0 : }
405 :
406 : #define ADD 0
407 : #define REM 1
408 369 : static void ospf6_zebra_route_update(int type, struct ospf6_route *request,
409 : struct ospf6 *ospf6)
410 : {
411 369 : struct zapi_route api;
412 369 : int nhcount;
413 369 : int ret = 0;
414 369 : struct prefix *dest;
415 :
416 369 : if (IS_OSPF6_DEBUG_ZEBRA(SEND))
417 0 : zlog_debug("Zebra Send %s route: %pFX",
418 : (type == REM ? "remove" : "add"), &request->prefix);
419 :
420 369 : if (zclient->sock < 0) {
421 0 : if (IS_OSPF6_DEBUG_ZEBRA(SEND))
422 0 : zlog_debug(" Not connected to Zebra");
423 0 : return;
424 : }
425 :
426 369 : if (request->path.origin.adv_router == ospf6->router_id
427 121 : && (request->path.type == OSPF6_PATH_TYPE_EXTERNAL1
428 121 : || request->path.type == OSPF6_PATH_TYPE_EXTERNAL2)) {
429 0 : if (IS_OSPF6_DEBUG_ZEBRA(SEND))
430 0 : zlog_debug(" Ignore self-originated external route");
431 0 : return;
432 : }
433 :
434 : /* If removing is the best path and if there's another path,
435 : * treat this request as add the secondary path - if there are
436 : * nexthops.
437 : */
438 446 : if (type == REM && ospf6_route_is_best(request) && request->next &&
439 100 : ospf6_route_is_same(request, request->next) &&
440 23 : ospf6_route_num_nexthops(request->next) > 0) {
441 23 : if (IS_OSPF6_DEBUG_ZEBRA(SEND))
442 0 : zlog_debug(
443 : " Best-path removal resulted Secondary addition");
444 23 : type = ADD;
445 23 : request = request->next;
446 : }
447 :
448 : /* Only the best path will be sent to zebra. */
449 369 : if (!ospf6_route_is_best(request)) {
450 : /* this is not preferred best route, ignore */
451 37 : if (IS_OSPF6_DEBUG_ZEBRA(SEND))
452 0 : zlog_debug(" Ignore non-best route");
453 37 : return;
454 : }
455 :
456 332 : nhcount = ospf6_route_num_nexthops(request);
457 332 : if (nhcount == 0) {
458 10 : if (type == ADD) {
459 5 : if (IS_OSPF6_DEBUG_ZEBRA(SEND))
460 0 : zlog_debug(" No nexthop, ignore");
461 5 : return;
462 5 : } else if (IS_OSPF6_DEBUG_ZEBRA(SEND))
463 0 : zlog_debug(" No nexthop, rem ok");
464 : }
465 :
466 327 : dest = &request->prefix;
467 :
468 327 : memset(&api, 0, sizeof(api));
469 327 : api.vrf_id = ospf6->vrf_id;
470 327 : api.type = ZEBRA_ROUTE_OSPF6;
471 327 : api.safi = SAFI_UNICAST;
472 327 : api.prefix = *dest;
473 :
474 327 : if (nhcount > ospf6->max_multipath) {
475 0 : if (IS_OSPF6_DEBUG_ZEBRA(SEND))
476 0 : zlog_debug(
477 : " Nexthop count is greater than configured maximum-path, hence ignore the extra nexthops");
478 : }
479 :
480 327 : api.nexthop_num = MIN(nhcount, ospf6->max_multipath);
481 327 : if (api.nexthop_num > 0) {
482 322 : SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
483 322 : ospf6_route_zebra_copy_nexthops(request, api.nexthops,
484 : api.nexthop_num, api.vrf_id);
485 : }
486 :
487 327 : SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
488 654 : api.metric = (request->path.metric_type == 2 ? request->path.u.cost_e2
489 327 : : request->path.cost);
490 327 : if (request->path.tag) {
491 0 : SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
492 0 : api.tag = request->path.tag;
493 : }
494 :
495 327 : SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
496 327 : api.distance = ospf6_distance_apply((struct prefix_ipv6 *)dest, request,
497 : ospf6);
498 :
499 327 : if (type == ADD
500 246 : && CHECK_FLAG(ospf6->config_flags, OSPF6_SEND_EXTRA_DATA_TO_ZEBRA))
501 0 : ospf6_zebra_append_opaque_attr(request, &api);
502 :
503 327 : if (type == REM)
504 81 : ret = zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
505 : else
506 246 : ret = zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
507 :
508 327 : if (ret == ZCLIENT_SEND_FAILURE)
509 0 : flog_err(EC_LIB_ZAPI_SOCKET,
510 : "zclient_route_send() %s failed: %s",
511 : (type == REM ? "delete" : "add"),
512 : safe_strerror(errno));
513 :
514 : return;
515 : }
516 :
517 259 : void ospf6_zebra_route_update_add(struct ospf6_route *request,
518 : struct ospf6 *ospf6)
519 : {
520 259 : if (ospf6->gr_info.restart_in_progress
521 259 : || ospf6->gr_info.prepare_in_progress) {
522 0 : if (IS_DEBUG_OSPF6_GR)
523 0 : zlog_debug(
524 : "Zebra: Graceful Restart in progress -- not installing %pFX",
525 : &request->prefix);
526 0 : return;
527 : }
528 :
529 259 : ospf6_zebra_route_update(ADD, request, ospf6);
530 : }
531 :
532 110 : void ospf6_zebra_route_update_remove(struct ospf6_route *request,
533 : struct ospf6 *ospf6)
534 : {
535 110 : if (ospf6->gr_info.restart_in_progress
536 110 : || ospf6->gr_info.prepare_in_progress) {
537 0 : if (IS_DEBUG_OSPF6_GR)
538 0 : zlog_debug(
539 : "Zebra: Graceful Restart in progress -- not uninstalling %pFX",
540 : &request->prefix);
541 0 : return;
542 : }
543 :
544 110 : ospf6_zebra_route_update(REM, request, ospf6);
545 : }
546 :
547 0 : void ospf6_zebra_add_discard(struct ospf6_route *request, struct ospf6 *ospf6)
548 : {
549 0 : struct zapi_route api;
550 0 : struct prefix *dest = &request->prefix;
551 :
552 0 : if (ospf6->gr_info.restart_in_progress
553 0 : || ospf6->gr_info.prepare_in_progress) {
554 0 : if (IS_DEBUG_OSPF6_GR)
555 0 : zlog_debug(
556 : "Zebra: Graceful Restart in progress -- not installing %pFX",
557 : &request->prefix);
558 0 : return;
559 : }
560 :
561 0 : if (!CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
562 0 : memset(&api, 0, sizeof(api));
563 0 : api.vrf_id = ospf6->vrf_id;
564 0 : api.type = ZEBRA_ROUTE_OSPF6;
565 0 : api.safi = SAFI_UNICAST;
566 0 : api.prefix = *dest;
567 0 : zapi_route_set_blackhole(&api, BLACKHOLE_NULL);
568 :
569 0 : zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
570 :
571 0 : if (IS_OSPF6_DEBUG_ZEBRA(SEND))
572 0 : zlog_debug("Zebra: Route add discard %pFX", dest);
573 :
574 0 : SET_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED);
575 : } else {
576 0 : if (IS_OSPF6_DEBUG_ZEBRA(SEND))
577 0 : zlog_debug(
578 : "Zebra: Blackhole route present already %pFX",
579 : dest);
580 : }
581 : }
582 :
583 0 : void ospf6_zebra_delete_discard(struct ospf6_route *request,
584 : struct ospf6 *ospf6)
585 : {
586 0 : struct zapi_route api;
587 0 : struct prefix *dest = &request->prefix;
588 :
589 0 : if (ospf6->gr_info.restart_in_progress
590 0 : || ospf6->gr_info.prepare_in_progress) {
591 0 : if (IS_DEBUG_OSPF6_GR)
592 0 : zlog_debug(
593 : "Zebra: Graceful Restart in progress -- not uninstalling %pFX",
594 : &request->prefix);
595 0 : return;
596 : }
597 :
598 0 : if (CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
599 0 : memset(&api, 0, sizeof(api));
600 0 : api.vrf_id = ospf6->vrf_id;
601 0 : api.type = ZEBRA_ROUTE_OSPF6;
602 0 : api.safi = SAFI_UNICAST;
603 0 : api.prefix = *dest;
604 0 : zapi_route_set_blackhole(&api, BLACKHOLE_NULL);
605 :
606 0 : zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
607 :
608 0 : if (IS_OSPF6_DEBUG_ZEBRA(SEND))
609 0 : zlog_debug("Zebra: Route delete discard %pFX", dest);
610 :
611 0 : UNSET_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED);
612 : } else {
613 0 : if (IS_OSPF6_DEBUG_ZEBRA(SEND))
614 0 : zlog_debug(
615 : "Zebra: Blackhole route already deleted %pFX",
616 : dest);
617 : }
618 : }
619 :
620 0 : static struct ospf6_distance *ospf6_distance_new(void)
621 : {
622 0 : return XCALLOC(MTYPE_OSPF6_DISTANCE, sizeof(struct ospf6_distance));
623 : }
624 :
625 0 : static void ospf6_distance_free(struct ospf6_distance *odistance)
626 : {
627 0 : XFREE(MTYPE_OSPF6_DISTANCE, odistance);
628 : }
629 :
630 0 : int ospf6_distance_set(struct vty *vty, struct ospf6 *o,
631 : const char *distance_str, const char *ip_str,
632 : const char *access_list_str)
633 : {
634 0 : int ret;
635 0 : struct prefix_ipv6 p;
636 0 : uint8_t distance;
637 0 : struct route_node *rn;
638 0 : struct ospf6_distance *odistance;
639 :
640 0 : ret = str2prefix_ipv6(ip_str, &p);
641 0 : if (ret == 0) {
642 0 : vty_out(vty, "Malformed prefix\n");
643 0 : return CMD_WARNING_CONFIG_FAILED;
644 : }
645 :
646 0 : distance = atoi(distance_str);
647 :
648 : /* Get OSPF6 distance node. */
649 0 : rn = route_node_get(o->distance_table, (struct prefix *)&p);
650 0 : if (rn->info) {
651 0 : odistance = rn->info;
652 0 : route_unlock_node(rn);
653 : } else {
654 0 : odistance = ospf6_distance_new();
655 0 : rn->info = odistance;
656 : }
657 :
658 : /* Set distance value. */
659 0 : odistance->distance = distance;
660 :
661 : /* Reset access-list configuration. */
662 0 : if (odistance->access_list) {
663 0 : free(odistance->access_list);
664 0 : odistance->access_list = NULL;
665 : }
666 0 : if (access_list_str)
667 0 : odistance->access_list = strdup(access_list_str);
668 :
669 : return CMD_SUCCESS;
670 : }
671 :
672 0 : int ospf6_distance_unset(struct vty *vty, struct ospf6 *o,
673 : const char *distance_str, const char *ip_str,
674 : const char *access_list_str)
675 : {
676 0 : int ret;
677 0 : struct prefix_ipv6 p;
678 0 : struct route_node *rn;
679 0 : struct ospf6_distance *odistance;
680 :
681 0 : ret = str2prefix_ipv6(ip_str, &p);
682 0 : if (ret == 0) {
683 0 : vty_out(vty, "Malformed prefix\n");
684 0 : return CMD_WARNING_CONFIG_FAILED;
685 : }
686 :
687 0 : rn = route_node_lookup(o->distance_table, (struct prefix *)&p);
688 0 : if (!rn) {
689 0 : vty_out(vty, "Cant't find specified prefix\n");
690 0 : return CMD_WARNING_CONFIG_FAILED;
691 : }
692 :
693 0 : odistance = rn->info;
694 :
695 0 : if (odistance->access_list)
696 0 : free(odistance->access_list);
697 0 : ospf6_distance_free(odistance);
698 :
699 0 : rn->info = NULL;
700 0 : route_unlock_node(rn);
701 0 : route_unlock_node(rn);
702 :
703 0 : return CMD_SUCCESS;
704 : }
705 :
706 16 : void ospf6_distance_reset(struct ospf6 *o)
707 : {
708 16 : struct route_node *rn;
709 16 : struct ospf6_distance *odistance;
710 :
711 16 : for (rn = route_top(o->distance_table); rn; rn = route_next(rn))
712 0 : if ((odistance = rn->info) != NULL) {
713 0 : if (odistance->access_list)
714 0 : free(odistance->access_list);
715 0 : ospf6_distance_free(odistance);
716 0 : rn->info = NULL;
717 0 : route_unlock_node(rn);
718 : }
719 16 : }
720 :
721 327 : uint8_t ospf6_distance_apply(struct prefix_ipv6 *p, struct ospf6_route * or,
722 : struct ospf6 *ospf6)
723 : {
724 327 : struct ospf6 *o;
725 :
726 327 : o = ospf6;
727 327 : if (o == NULL)
728 : return 0;
729 :
730 327 : if (o->distance_intra)
731 0 : if (or->path.type == OSPF6_PATH_TYPE_INTRA)
732 : return o->distance_intra;
733 :
734 327 : if (o->distance_inter)
735 0 : if (or->path.type == OSPF6_PATH_TYPE_INTER)
736 : return o->distance_inter;
737 :
738 327 : if (o->distance_external)
739 0 : if (or->path.type == OSPF6_PATH_TYPE_EXTERNAL1 ||
740 : or->path.type == OSPF6_PATH_TYPE_EXTERNAL2)
741 : return o->distance_external;
742 :
743 327 : if (o->distance_all)
744 : return o->distance_all;
745 :
746 : return 0;
747 : }
748 :
749 16 : static void ospf6_zebra_connected(struct zclient *zclient)
750 : {
751 : /* Send the client registration */
752 16 : bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, VRF_DEFAULT);
753 :
754 16 : zclient_send_reg_requests(zclient, VRF_DEFAULT);
755 16 : }
756 :
757 : static zclient_handler *const ospf6_handlers[] = {
758 : [ZEBRA_ROUTER_ID_UPDATE] = ospf6_router_id_update_zebra,
759 : [ZEBRA_INTERFACE_ADDRESS_ADD] = ospf6_zebra_if_address_update_add,
760 : [ZEBRA_INTERFACE_ADDRESS_DELETE] = ospf6_zebra_if_address_update_delete,
761 : [ZEBRA_REDISTRIBUTE_ROUTE_ADD] = ospf6_zebra_read_route,
762 : [ZEBRA_REDISTRIBUTE_ROUTE_DEL] = ospf6_zebra_read_route,
763 : [ZEBRA_NEXTHOP_UPDATE] = ospf6_zebra_import_check_update,
764 : };
765 :
766 16 : void ospf6_zebra_init(struct thread_master *master)
767 : {
768 : /* Allocate zebra structure. */
769 16 : zclient = zclient_new(master, &zclient_options_default, ospf6_handlers,
770 : array_size(ospf6_handlers));
771 16 : zclient_init(zclient, ZEBRA_ROUTE_OSPF6, 0, &ospf6d_privs);
772 16 : zclient->zebra_connected = ospf6_zebra_connected;
773 :
774 : /* Install command element for zebra node. */
775 16 : install_element(VIEW_NODE, &show_ospf6_zebra_cmd);
776 16 : }
777 :
778 : /* Debug */
779 :
780 0 : DEFUN (debug_ospf6_zebra_sendrecv,
781 : debug_ospf6_zebra_sendrecv_cmd,
782 : "debug ospf6 zebra [<send|recv>]",
783 : DEBUG_STR
784 : OSPF6_STR
785 : "Debug connection between zebra\n"
786 : "Debug Sending zebra\n"
787 : "Debug Receiving zebra\n"
788 : )
789 : {
790 0 : int idx_send_recv = 3;
791 0 : unsigned char level = 0;
792 :
793 0 : if (argc == 4) {
794 0 : if (strmatch(argv[idx_send_recv]->text, "send"))
795 : level = OSPF6_DEBUG_ZEBRA_SEND;
796 0 : else if (strmatch(argv[idx_send_recv]->text, "recv"))
797 0 : level = OSPF6_DEBUG_ZEBRA_RECV;
798 : } else
799 : level = OSPF6_DEBUG_ZEBRA_SEND | OSPF6_DEBUG_ZEBRA_RECV;
800 :
801 0 : OSPF6_DEBUG_ZEBRA_ON(level);
802 0 : return CMD_SUCCESS;
803 : }
804 :
805 0 : DEFUN (no_debug_ospf6_zebra_sendrecv,
806 : no_debug_ospf6_zebra_sendrecv_cmd,
807 : "no debug ospf6 zebra [<send|recv>]",
808 : NO_STR
809 : DEBUG_STR
810 : OSPF6_STR
811 : "Debug connection between zebra\n"
812 : "Debug Sending zebra\n"
813 : "Debug Receiving zebra\n"
814 : )
815 : {
816 0 : int idx_send_recv = 4;
817 0 : unsigned char level = 0;
818 :
819 0 : if (argc == 5) {
820 0 : if (strmatch(argv[idx_send_recv]->text, "send"))
821 : level = OSPF6_DEBUG_ZEBRA_SEND;
822 0 : else if (strmatch(argv[idx_send_recv]->text, "recv"))
823 0 : level = OSPF6_DEBUG_ZEBRA_RECV;
824 : } else
825 : level = OSPF6_DEBUG_ZEBRA_SEND | OSPF6_DEBUG_ZEBRA_RECV;
826 :
827 0 : OSPF6_DEBUG_ZEBRA_OFF(level);
828 0 : return CMD_SUCCESS;
829 : }
830 :
831 :
832 0 : int config_write_ospf6_debug_zebra(struct vty *vty)
833 : {
834 0 : if (IS_OSPF6_DEBUG_ZEBRA(SEND) && IS_OSPF6_DEBUG_ZEBRA(RECV))
835 0 : vty_out(vty, "debug ospf6 zebra\n");
836 : else {
837 0 : if (IS_OSPF6_DEBUG_ZEBRA(SEND))
838 0 : vty_out(vty, "debug ospf6 zebra send\n");
839 0 : if (IS_OSPF6_DEBUG_ZEBRA(RECV))
840 0 : vty_out(vty, "debug ospf6 zebra recv\n");
841 : }
842 0 : return 0;
843 : }
844 :
845 16 : void install_element_ospf6_debug_zebra(void)
846 : {
847 16 : install_element(ENABLE_NODE, &debug_ospf6_zebra_sendrecv_cmd);
848 16 : install_element(ENABLE_NODE, &no_debug_ospf6_zebra_sendrecv_cmd);
849 16 : install_element(CONFIG_NODE, &debug_ospf6_zebra_sendrecv_cmd);
850 16 : install_element(CONFIG_NODE, &no_debug_ospf6_zebra_sendrecv_cmd);
851 16 : }
|