]> git.proxmox.com Git - mirror_frr.git/blob - ripngd/ripng_zebra.c
*: reindent
[mirror_frr.git] / ripngd / ripng_zebra.c
1 /*
2 * RIPngd and zebra interface.
3 * Copyright (C) 1998, 1999 Kunihiro Ishiguro
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 */
22
23 #include <zebra.h>
24
25 #include "command.h"
26 #include "prefix.h"
27 #include "table.h"
28 #include "stream.h"
29 #include "memory.h"
30 #include "routemap.h"
31 #include "zclient.h"
32 #include "log.h"
33
34 #include "ripngd/ripngd.h"
35 #include "ripngd/ripng_debug.h"
36
37 /* All information about zebra. */
38 struct zclient *zclient = NULL;
39
40 /* Send ECMP routes to zebra. */
41 static void ripng_zebra_ipv6_send(struct route_node *rp, u_char cmd)
42 {
43 static struct in6_addr **nexthops = NULL;
44 static ifindex_t *ifindexes = NULL;
45 static unsigned int nexthops_len = 0;
46
47 struct list *list = (struct list *)rp->info;
48 struct zapi_ipv6 api;
49 struct listnode *listnode = NULL;
50 struct ripng_info *rinfo = NULL;
51 int count = 0;
52
53 if (vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG],
54 VRF_DEFAULT)) {
55 api.vrf_id = VRF_DEFAULT;
56 api.type = ZEBRA_ROUTE_RIPNG;
57 api.instance = 0;
58 api.flags = 0;
59 api.message = 0;
60 api.safi = SAFI_UNICAST;
61
62 if (nexthops_len < listcount(list)) {
63 nexthops_len = listcount(list);
64 nexthops = XREALLOC(
65 MTYPE_TMP, nexthops,
66 nexthops_len * sizeof(struct in6_addr *));
67 ifindexes =
68 XREALLOC(MTYPE_TMP, ifindexes,
69 nexthops_len * sizeof(unsigned int));
70 }
71
72 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
73 SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
74 for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
75 nexthops[count] = &rinfo->nexthop;
76 ifindexes[count] = rinfo->ifindex;
77 count++;
78 if (cmd == ZEBRA_IPV6_ROUTE_ADD)
79 SET_FLAG(rinfo->flags, RIPNG_RTF_FIB);
80 else
81 UNSET_FLAG(rinfo->flags, RIPNG_RTF_FIB);
82 }
83
84 api.nexthop = nexthops;
85 api.nexthop_num = count;
86 api.ifindex = ifindexes;
87 api.ifindex_num = count;
88
89 rinfo = listgetdata(listhead(list));
90
91 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
92 api.metric = rinfo->metric;
93
94 if (rinfo->tag) {
95 SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
96 api.tag = rinfo->tag;
97 }
98
99 zapi_ipv6_route(cmd, zclient, (struct prefix_ipv6 *)&rp->p,
100 NULL, &api);
101
102 if (IS_RIPNG_DEBUG_ZEBRA) {
103 if (ripng->ecmp)
104 zlog_debug("%s: %s/%d nexthops %d",
105 (cmd == ZEBRA_IPV6_ROUTE_ADD)
106 ? "Install into zebra"
107 : "Delete from zebra",
108 inet6_ntoa(rp->p.u.prefix6),
109 rp->p.prefixlen, count);
110 else
111 zlog_debug("%s: %s/%d",
112 (cmd == ZEBRA_IPV6_ROUTE_ADD)
113 ? "Install into zebra"
114 : "Delete from zebra",
115 inet6_ntoa(rp->p.u.prefix6),
116 rp->p.prefixlen);
117 }
118 }
119 }
120
121 /* Add/update ECMP routes to zebra. */
122 void ripng_zebra_ipv6_add(struct route_node *rp)
123 {
124 ripng_zebra_ipv6_send(rp, ZEBRA_IPV6_ROUTE_ADD);
125 }
126
127 /* Delete ECMP routes from zebra. */
128 void ripng_zebra_ipv6_delete(struct route_node *rp)
129 {
130 ripng_zebra_ipv6_send(rp, ZEBRA_IPV6_ROUTE_DELETE);
131 }
132
133 /* Zebra route add and delete treatment. */
134 static int ripng_zebra_read_ipv6(int command, struct zclient *zclient,
135 zebra_size_t length, vrf_id_t vrf_id)
136 {
137 struct stream *s;
138 struct zapi_ipv6 api;
139 unsigned long ifindex;
140 struct in6_addr nexthop;
141 struct prefix_ipv6 p, src_p;
142
143 s = zclient->ibuf;
144 ifindex = 0;
145 memset(&nexthop, 0, sizeof(struct in6_addr));
146
147 /* Type, flags, message. */
148 api.type = stream_getc(s);
149 api.instance = stream_getw(s);
150 api.flags = stream_getl(s);
151 api.message = stream_getc(s);
152
153 /* IPv6 prefix. */
154 memset(&p, 0, sizeof(struct prefix_ipv6));
155 p.family = AF_INET6;
156 p.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc(s));
157 stream_get(&p.prefix, s, PSIZE(p.prefixlen));
158
159 memset(&src_p, 0, sizeof(struct prefix_ipv6));
160 src_p.family = AF_INET6;
161 if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) {
162 src_p.prefixlen = stream_getc(s);
163 stream_get(&src_p.prefix, s, PSIZE(src_p.prefixlen));
164 }
165
166 if (src_p.prefixlen)
167 /* we completely ignore srcdest routes for now. */
168 return 0;
169
170 /* Nexthop, ifindex, distance, metric. */
171 if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
172 api.nexthop_num = stream_getc(s);
173 stream_get(&nexthop, s, 16);
174 }
175 if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
176 api.ifindex_num = stream_getc(s);
177 ifindex = stream_getl(s);
178 }
179 if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
180 api.distance = stream_getc(s);
181 else
182 api.distance = 0;
183 if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
184 api.metric = stream_getl(s);
185 else
186 api.metric = 0;
187
188 if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG))
189 api.tag = stream_getl(s);
190 else
191 api.tag = 0;
192
193 if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD)
194 ripng_redistribute_add(api.type, RIPNG_ROUTE_REDISTRIBUTE, &p,
195 ifindex, &nexthop, api.tag);
196 else
197 ripng_redistribute_delete(api.type, RIPNG_ROUTE_REDISTRIBUTE,
198 &p, ifindex);
199
200 return 0;
201 }
202
203 void ripng_zclient_reset(void)
204 {
205 zclient_reset(zclient);
206 }
207
208 static int ripng_redistribute_unset(int type)
209 {
210
211 if (!vrf_bitmap_check(zclient->redist[AFI_IP6][type], VRF_DEFAULT))
212 return CMD_SUCCESS;
213
214 vrf_bitmap_set(zclient->redist[AFI_IP6][type], VRF_DEFAULT);
215
216 if (zclient->sock > 0)
217 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
218 AFI_IP6, type, 0, VRF_DEFAULT);
219
220 ripng_redistribute_withdraw(type);
221
222 return CMD_SUCCESS;
223 }
224
225 int ripng_redistribute_check(int type)
226 {
227 return vrf_bitmap_check(zclient->redist[AFI_IP6][type], VRF_DEFAULT);
228 }
229
230 static void ripng_redistribute_metric_set(int type, int metric)
231 {
232 ripng->route_map[type].metric_config = 1;
233 ripng->route_map[type].metric = metric;
234 }
235
236 static int ripng_redistribute_metric_unset(int type)
237 {
238 ripng->route_map[type].metric_config = 0;
239 ripng->route_map[type].metric = 0;
240 return 0;
241 }
242
243 static void ripng_redistribute_routemap_set(int type, const char *name)
244 {
245 if (ripng->route_map[type].name)
246 free(ripng->route_map[type].name);
247
248 ripng->route_map[type].name = strdup(name);
249 ripng->route_map[type].map = route_map_lookup_by_name(name);
250 }
251
252 static void ripng_redistribute_routemap_unset(int type)
253 {
254 if (ripng->route_map[type].name)
255 free(ripng->route_map[type].name);
256
257 ripng->route_map[type].name = NULL;
258 ripng->route_map[type].map = NULL;
259 }
260
261 /* Redistribution types */
262 static struct {
263 int type;
264 int str_min_len;
265 const char *str;
266 } redist_type[] = {{ZEBRA_ROUTE_KERNEL, 1, "kernel"},
267 {ZEBRA_ROUTE_CONNECT, 1, "connected"},
268 {ZEBRA_ROUTE_STATIC, 1, "static"},
269 {ZEBRA_ROUTE_OSPF6, 1, "ospf6"},
270 {ZEBRA_ROUTE_BGP, 2, "bgp"},
271 {ZEBRA_ROUTE_VNC, 1, "vnc"},
272 {0, 0, NULL}};
273
274 void ripng_redistribute_clean()
275 {
276 int i;
277
278 for (i = 0; redist_type[i].str; i++) {
279 if (vrf_bitmap_check(
280 zclient->redist[AFI_IP6][redist_type[i].type],
281 VRF_DEFAULT)) {
282 if (zclient->sock > 0)
283 zebra_redistribute_send(
284 ZEBRA_REDISTRIBUTE_DELETE, zclient,
285 AFI_IP6, redist_type[i].type, 0,
286 VRF_DEFAULT);
287
288 vrf_bitmap_unset(
289 zclient->redist[AFI_IP6][redist_type[i].type],
290 VRF_DEFAULT);
291
292 /* Remove the routes from RIPng table. */
293 ripng_redistribute_withdraw(redist_type[i].type);
294 }
295 }
296 }
297
298 DEFUN (ripng_redistribute_ripng,
299 ripng_redistribute_ripng_cmd,
300 "redistribute ripng",
301 "Redistribute information from another routing protocol\n"
302 "RIPng route\n")
303 {
304 vrf_bitmap_set(zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG],
305 VRF_DEFAULT);
306 return CMD_SUCCESS;
307 }
308
309 DEFUN (no_ripng_redistribute_ripng,
310 no_ripng_redistribute_ripng_cmd,
311 "no redistribute ripng",
312 NO_STR
313 "Redistribute information from another routing protocol\n"
314 "RIPng route\n")
315 {
316 vrf_bitmap_unset(zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG],
317 VRF_DEFAULT);
318 return CMD_SUCCESS;
319 }
320
321 DEFUN (ripng_redistribute_type,
322 ripng_redistribute_type_cmd,
323 "redistribute " FRR_REDIST_STR_RIPNGD,
324 "Redistribute\n"
325 FRR_REDIST_HELP_STR_RIPNGD)
326 {
327 int type;
328
329 char *proto = argv[argc - 1]->text;
330 type = proto_redistnum(AFI_IP6, proto);
331
332 if (type < 0) {
333 vty_out(vty, "Invalid type %s%s", proto, VTY_NEWLINE);
334 return CMD_WARNING;
335 }
336
337 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0,
338 VRF_DEFAULT);
339 return CMD_SUCCESS;
340 }
341
342 DEFUN (no_ripng_redistribute_type,
343 no_ripng_redistribute_type_cmd,
344 "no redistribute " FRR_REDIST_STR_RIPNGD " [metric (0-16)] [route-map WORD]",
345 NO_STR
346 "Redistribute\n"
347 FRR_REDIST_HELP_STR_RIPNGD
348 "Metric\n"
349 "Metric value\n"
350 "Route map reference\n"
351 "Pointer to route-map entries\n")
352 {
353 int type;
354
355 char *proto = argv[2]->text;
356 type = proto_redistnum(AFI_IP6, proto);
357
358 if (type < 0) {
359 vty_out(vty, "Invalid type %s%s", proto, VTY_NEWLINE);
360 return CMD_WARNING;
361 }
362
363 ripng_redistribute_metric_unset(type);
364 ripng_redistribute_routemap_unset(type);
365 return ripng_redistribute_unset(type);
366 }
367
368
369 DEFUN (ripng_redistribute_type_metric,
370 ripng_redistribute_type_metric_cmd,
371 "redistribute " FRR_REDIST_STR_RIPNGD " metric (0-16)",
372 "Redistribute\n"
373 FRR_REDIST_HELP_STR_RIPNGD
374 "Metric\n"
375 "Metric value\n")
376 {
377 int idx_protocol = 1;
378 int idx_number = 3;
379 int type;
380 int metric;
381
382 metric = atoi(argv[idx_number]->arg);
383 type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
384
385 if (type < 0) {
386 vty_out(vty, "Invalid type %s%s", argv[idx_protocol]->text,
387 VTY_NEWLINE);
388 return CMD_WARNING;
389 }
390
391 ripng_redistribute_metric_set(type, metric);
392 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0,
393 VRF_DEFAULT);
394 return CMD_SUCCESS;
395 }
396
397 DEFUN (ripng_redistribute_type_routemap,
398 ripng_redistribute_type_routemap_cmd,
399 "redistribute " FRR_REDIST_STR_RIPNGD " route-map WORD",
400 "Redistribute\n"
401 FRR_REDIST_HELP_STR_RIPNGD
402 "Route map reference\n"
403 "Pointer to route-map entries\n")
404 {
405 int idx_protocol = 1;
406 int idx_word = 3;
407 int type;
408
409 type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
410
411 if (type < 0) {
412 vty_out(vty, "Invalid type %s%s", argv[idx_protocol]->text,
413 VTY_NEWLINE);
414 return CMD_WARNING;
415 }
416
417 ripng_redistribute_routemap_set(type, argv[idx_word]->text);
418 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0,
419 VRF_DEFAULT);
420 return CMD_SUCCESS;
421 }
422
423 DEFUN (ripng_redistribute_type_metric_routemap,
424 ripng_redistribute_type_metric_routemap_cmd,
425 "redistribute " FRR_REDIST_STR_RIPNGD " metric (0-16) route-map WORD",
426 "Redistribute\n"
427 FRR_REDIST_HELP_STR_RIPNGD
428 "Metric\n"
429 "Metric value\n"
430 "Route map reference\n"
431 "Pointer to route-map entries\n")
432 {
433 int idx_protocol = 1;
434 int idx_number = 3;
435 int idx_word = 5;
436 int type;
437 int metric;
438
439 type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
440 metric = atoi(argv[idx_number]->arg);
441
442 if (type < 0) {
443 vty_out(vty, "Invalid type %s%s", argv[idx_protocol]->text,
444 VTY_NEWLINE);
445 return CMD_WARNING;
446 }
447
448 ripng_redistribute_metric_set(type, metric);
449 ripng_redistribute_routemap_set(type, argv[idx_word]->text);
450 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0,
451 VRF_DEFAULT);
452 return CMD_SUCCESS;
453 }
454
455 void ripng_redistribute_write(struct vty *vty, int config_mode)
456 {
457 int i;
458
459 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
460 if (i != zclient->redist_default
461 && vrf_bitmap_check(zclient->redist[AFI_IP6][i],
462 VRF_DEFAULT)) {
463 if (config_mode) {
464 if (ripng->route_map[i].metric_config) {
465 if (ripng->route_map[i].name)
466 vty_out(vty,
467 " redistribute %s metric %d route-map %s%s",
468 zebra_route_string(i),
469 ripng->route_map[i]
470 .metric,
471 ripng->route_map[i]
472 .name,
473 VTY_NEWLINE);
474 else
475 vty_out(vty,
476 " redistribute %s metric %d%s",
477 zebra_route_string(i),
478 ripng->route_map[i]
479 .metric,
480 VTY_NEWLINE);
481 } else {
482 if (ripng->route_map[i].name)
483 vty_out(vty,
484 " redistribute %s route-map %s%s",
485 zebra_route_string(i),
486 ripng->route_map[i]
487 .name,
488 VTY_NEWLINE);
489 else
490 vty_out(vty,
491 " redistribute %s%s",
492 zebra_route_string(i),
493 VTY_NEWLINE);
494 }
495 } else
496 vty_out(vty, " %s", zebra_route_string(i));
497 }
498 }
499
500 /* RIPng configuration write function. */
501 static int zebra_config_write(struct vty *vty)
502 {
503 if (!zclient->enable) {
504 vty_out(vty, "no router zebra%s", VTY_NEWLINE);
505 return 1;
506 } else if (!vrf_bitmap_check(
507 zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG],
508 VRF_DEFAULT)) {
509 vty_out(vty, "router zebra%s", VTY_NEWLINE);
510 vty_out(vty, " no redistribute ripng%s", VTY_NEWLINE);
511 return 1;
512 }
513 return 0;
514 }
515
516 /* Zebra node structure. */
517 static struct cmd_node zebra_node = {
518 ZEBRA_NODE, "%s(config-router)# ",
519 };
520
521 static void ripng_zebra_connected(struct zclient *zclient)
522 {
523 zclient_send_reg_requests(zclient, VRF_DEFAULT);
524 }
525
526 /* Initialize zebra structure and it's commands. */
527 void zebra_init(struct thread_master *master)
528 {
529 /* Allocate zebra structure. */
530 zclient = zclient_new(master);
531 zclient_init(zclient, ZEBRA_ROUTE_RIPNG, 0);
532
533 zclient->zebra_connected = ripng_zebra_connected;
534 zclient->interface_up = ripng_interface_up;
535 zclient->interface_down = ripng_interface_down;
536 zclient->interface_add = ripng_interface_add;
537 zclient->interface_delete = ripng_interface_delete;
538 zclient->interface_address_add = ripng_interface_address_add;
539 zclient->interface_address_delete = ripng_interface_address_delete;
540 zclient->redistribute_route_ipv6_add = ripng_zebra_read_ipv6;
541 zclient->redistribute_route_ipv6_del = ripng_zebra_read_ipv6;
542
543 /* Install zebra node. */
544 install_node(&zebra_node, zebra_config_write);
545
546 /* Install command element for zebra node. */
547 install_default(ZEBRA_NODE);
548 install_element(ZEBRA_NODE, &ripng_redistribute_ripng_cmd);
549 install_element(ZEBRA_NODE, &no_ripng_redistribute_ripng_cmd);
550
551 /* Install command elements to ripng node */
552 install_element(RIPNG_NODE, &ripng_redistribute_type_cmd);
553 install_element(RIPNG_NODE, &ripng_redistribute_type_routemap_cmd);
554 install_element(RIPNG_NODE, &ripng_redistribute_type_metric_cmd);
555 install_element(RIPNG_NODE,
556 &ripng_redistribute_type_metric_routemap_cmd);
557 install_element(RIPNG_NODE, &no_ripng_redistribute_type_cmd);
558 }