]> git.proxmox.com Git - mirror_frr.git/blob - ripd/rip_zebra.c
Merge pull request #1031 from opensourcerouting/small-bits
[mirror_frr.git] / ripd / rip_zebra.c
1 /* RIPd and zebra interface.
2 * Copyright (C) 1997, 1999 Kunihiro Ishiguro <kunihiro@zebra.org>
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 "command.h"
24 #include "prefix.h"
25 #include "table.h"
26 #include "stream.h"
27 #include "memory.h"
28 #include "routemap.h"
29 #include "zclient.h"
30 #include "log.h"
31 #include "vrf.h"
32 #include "ripd/ripd.h"
33 #include "ripd/rip_debug.h"
34 #include "ripd/rip_interface.h"
35
36 /* All information about zebra. */
37 struct zclient *zclient = NULL;
38
39 /* Send ECMP routes to zebra. */
40 static void rip_zebra_ipv4_send(struct route_node *rp, u_char cmd)
41 {
42 struct list *list = (struct list *)rp->info;
43 struct zapi_route api;
44 struct zapi_nexthop *api_nh;
45 struct listnode *listnode = NULL;
46 struct rip_info *rinfo = NULL;
47 int count = 0;
48
49 memset(&api, 0, sizeof(api));
50 api.vrf_id = VRF_DEFAULT;
51 api.type = ZEBRA_ROUTE_RIP;
52 api.safi = SAFI_UNICAST;
53
54 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
55 for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
56 api_nh = &api.nexthops[count];
57 api_nh->gate.ipv4 = rinfo->nexthop;
58 api_nh->type = NEXTHOP_TYPE_IPV4;
59 if (cmd == ZEBRA_ROUTE_ADD)
60 SET_FLAG(rinfo->flags, RIP_RTF_FIB);
61 else
62 UNSET_FLAG(rinfo->flags, RIP_RTF_FIB);
63 count++;
64 }
65
66 api.prefix = rp->p;
67 api.nexthop_num = count;
68
69 rinfo = listgetdata(listhead(list));
70
71 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
72 api.metric = rinfo->metric;
73
74 if (rinfo->distance && rinfo->distance != ZEBRA_RIP_DISTANCE_DEFAULT) {
75 SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
76 api.distance = rinfo->distance;
77 }
78
79 if (rinfo->tag) {
80 SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
81 api.tag = rinfo->tag;
82 }
83
84 zclient_route_send(cmd, zclient, &api);
85
86 if (IS_RIP_DEBUG_ZEBRA) {
87 if (rip->ecmp)
88 zlog_debug("%s: %s/%d nexthops %d",
89 (cmd == ZEBRA_ROUTE_ADD)
90 ? "Install into zebra"
91 : "Delete from zebra",
92 inet_ntoa(rp->p.u.prefix4), rp->p.prefixlen,
93 count);
94 else
95 zlog_debug("%s: %s/%d",
96 (cmd == ZEBRA_ROUTE_ADD)
97 ? "Install into zebra"
98 : "Delete from zebra",
99 inet_ntoa(rp->p.u.prefix4), rp->p.prefixlen);
100 }
101
102 rip_global_route_changes++;
103 }
104
105 /* Add/update ECMP routes to zebra. */
106 void rip_zebra_ipv4_add(struct route_node *rp)
107 {
108 rip_zebra_ipv4_send(rp, ZEBRA_ROUTE_ADD);
109 }
110
111 /* Delete ECMP routes from zebra. */
112 void rip_zebra_ipv4_delete(struct route_node *rp)
113 {
114 rip_zebra_ipv4_send(rp, ZEBRA_ROUTE_DELETE);
115 }
116
117 /* Zebra route add and delete treatment. */
118 static int rip_zebra_read_route(int command, struct zclient *zclient,
119 zebra_size_t length, vrf_id_t vrf_id)
120 {
121 struct zapi_route api;
122 struct in_addr nexthop;
123 unsigned long ifindex;
124
125 if (!rip)
126 return 0;
127
128 if (zapi_route_decode(zclient->ibuf, &api) < 0)
129 return -1;
130
131 nexthop = api.nexthops[0].gate.ipv4;
132 ifindex = api.nexthops[0].ifindex;
133
134 /* Then fetch IPv4 prefixes. */
135 if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
136 rip_redistribute_add(api.type, RIP_ROUTE_REDISTRIBUTE,
137 (struct prefix_ipv4 *)&api.prefix, ifindex,
138 &nexthop, api.metric, api.distance,
139 api.tag);
140 else if (command == ZEBRA_REDISTRIBUTE_ROUTE_DEL)
141 rip_redistribute_delete(api.type, RIP_ROUTE_REDISTRIBUTE,
142 (struct prefix_ipv4 *)&api.prefix,
143 ifindex);
144
145 return 0;
146 }
147
148 void rip_zclient_reset(void)
149 {
150 zclient_reset(zclient);
151 }
152
153 /* RIP route-map set for redistribution */
154 static void rip_routemap_set(int type, const char *name)
155 {
156 if (rip->route_map[type].name)
157 free(rip->route_map[type].name);
158
159 rip->route_map[type].name = strdup(name);
160 rip->route_map[type].map = route_map_lookup_by_name(name);
161 }
162
163 static void rip_redistribute_metric_set(int type, unsigned int metric)
164 {
165 rip->route_map[type].metric_config = 1;
166 rip->route_map[type].metric = metric;
167 }
168
169 static int rip_metric_unset(int type, unsigned int metric)
170 {
171 #define DONT_CARE_METRIC_RIP 17
172 if (metric != DONT_CARE_METRIC_RIP
173 && rip->route_map[type].metric != metric)
174 return 1;
175 rip->route_map[type].metric_config = 0;
176 rip->route_map[type].metric = 0;
177 return 0;
178 }
179
180 /* RIP route-map unset for redistribution */
181 static int rip_routemap_unset(int type, const char *name)
182 {
183 if (!rip->route_map[type].name
184 || (name != NULL && strcmp(rip->route_map[type].name, name)))
185 return 1;
186
187 free(rip->route_map[type].name);
188 rip->route_map[type].name = NULL;
189 rip->route_map[type].map = NULL;
190
191 return 0;
192 }
193
194 /* Redistribution types */
195 static struct {
196 int type;
197 int str_min_len;
198 const char *str;
199 } redist_type[] = {{ZEBRA_ROUTE_KERNEL, 1, "kernel"},
200 {ZEBRA_ROUTE_CONNECT, 1, "connected"},
201 {ZEBRA_ROUTE_STATIC, 1, "static"},
202 {ZEBRA_ROUTE_OSPF, 1, "ospf"},
203 {ZEBRA_ROUTE_BGP, 2, "bgp"},
204 {ZEBRA_ROUTE_VNC, 1, "vnc"},
205 {0, 0, NULL}};
206
207 static int rip_redistribute_unset(int type)
208 {
209 if (!vrf_bitmap_check(zclient->redist[AFI_IP][type], VRF_DEFAULT))
210 return CMD_SUCCESS;
211
212 vrf_bitmap_unset(zclient->redist[AFI_IP][type], VRF_DEFAULT);
213
214 if (zclient->sock > 0)
215 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
216 AFI_IP, type, 0, VRF_DEFAULT);
217
218 /* Remove the routes from RIP table. */
219 rip_redistribute_withdraw(type);
220
221 return CMD_SUCCESS;
222 }
223
224 int rip_redistribute_check(int type)
225 {
226 return vrf_bitmap_check(zclient->redist[AFI_IP][type], VRF_DEFAULT);
227 }
228
229 void rip_redistribute_clean(void)
230 {
231 int i;
232
233 for (i = 0; redist_type[i].str; i++) {
234 if (vrf_bitmap_check(
235 zclient->redist[AFI_IP][redist_type[i].type],
236 VRF_DEFAULT)) {
237 if (zclient->sock > 0)
238 zebra_redistribute_send(
239 ZEBRA_REDISTRIBUTE_DELETE, zclient,
240 AFI_IP, redist_type[i].type, 0,
241 VRF_DEFAULT);
242
243 vrf_bitmap_unset(
244 zclient->redist[AFI_IP][redist_type[i].type],
245 VRF_DEFAULT);
246
247 /* Remove the routes from RIP table. */
248 rip_redistribute_withdraw(redist_type[i].type);
249 }
250 }
251 }
252
253 DEFUN (rip_redistribute_type,
254 rip_redistribute_type_cmd,
255 "redistribute " FRR_REDIST_STR_RIPD,
256 REDIST_STR
257 FRR_REDIST_HELP_STR_RIPD)
258 {
259 int i;
260
261 for (i = 0; redist_type[i].str; i++) {
262 if (strncmp(redist_type[i].str, argv[1]->arg,
263 redist_type[i].str_min_len)
264 == 0) {
265 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient,
266 AFI_IP, redist_type[i].type, 0,
267 VRF_DEFAULT);
268 return CMD_SUCCESS;
269 }
270 }
271
272 vty_out(vty, "Invalid type %s\n", argv[1]->arg);
273
274 return CMD_WARNING_CONFIG_FAILED;
275 }
276
277 DEFUN (no_rip_redistribute_type,
278 no_rip_redistribute_type_cmd,
279 "no redistribute " FRR_REDIST_STR_RIPD,
280 NO_STR
281 REDIST_STR
282 FRR_REDIST_HELP_STR_RIPD)
283 {
284 int i;
285
286 for (i = 0; redist_type[i].str; i++) {
287 if (strncmp(redist_type[i].str, argv[2]->arg,
288 redist_type[i].str_min_len)
289 == 0) {
290 rip_metric_unset(redist_type[i].type,
291 DONT_CARE_METRIC_RIP);
292 rip_routemap_unset(redist_type[i].type, NULL);
293 rip_redistribute_unset(redist_type[i].type);
294 return CMD_SUCCESS;
295 }
296 }
297
298 vty_out(vty, "Invalid type %s\n", argv[2]->arg);
299
300 return CMD_WARNING_CONFIG_FAILED;
301 }
302
303 DEFUN (rip_redistribute_type_routemap,
304 rip_redistribute_type_routemap_cmd,
305 "redistribute " FRR_REDIST_STR_RIPD " route-map WORD",
306 REDIST_STR
307 FRR_REDIST_HELP_STR_RIPD
308 "Route map reference\n"
309 "Pointer to route-map entries\n")
310 {
311 int idx_protocol = 1;
312 int idx_word = 3;
313 int i;
314
315 for (i = 0; redist_type[i].str; i++) {
316 if (strmatch(redist_type[i].str, argv[idx_protocol]->text)) {
317 rip_routemap_set(redist_type[i].type,
318 argv[idx_word]->arg);
319 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient,
320 AFI_IP, redist_type[i].type, 0,
321 VRF_DEFAULT);
322 return CMD_SUCCESS;
323 }
324 }
325
326 vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text);
327
328 return CMD_WARNING_CONFIG_FAILED;
329 }
330
331 DEFUN (no_rip_redistribute_type_routemap,
332 no_rip_redistribute_type_routemap_cmd,
333 "no redistribute " FRR_REDIST_STR_RIPD " route-map WORD",
334 NO_STR
335 REDIST_STR
336 FRR_REDIST_HELP_STR_RIPD
337 "Route map reference\n"
338 "Pointer to route-map entries\n")
339 {
340 int idx_protocol = 2;
341 int idx_word = 4;
342 int i;
343
344 for (i = 0; redist_type[i].str; i++) {
345 if (strmatch(redist_type[i].str, argv[idx_protocol]->text)) {
346 if (rip_routemap_unset(redist_type[i].type,
347 argv[idx_word]->arg))
348 return CMD_WARNING_CONFIG_FAILED;
349 rip_redistribute_unset(redist_type[i].type);
350 return CMD_SUCCESS;
351 }
352 }
353
354 vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text);
355
356 return CMD_WARNING_CONFIG_FAILED;
357 }
358
359 DEFUN (rip_redistribute_type_metric,
360 rip_redistribute_type_metric_cmd,
361 "redistribute " FRR_REDIST_STR_RIPD " metric (0-16)",
362 REDIST_STR
363 FRR_REDIST_HELP_STR_RIPD
364 "Metric\n"
365 "Metric value\n")
366 {
367 int idx_protocol = 1;
368 int idx_number = 3;
369 int i;
370 int metric;
371
372 metric = atoi(argv[idx_number]->arg);
373
374 for (i = 0; redist_type[i].str; i++) {
375 if (strmatch(redist_type[i].str, argv[idx_protocol]->text)) {
376 rip_redistribute_metric_set(redist_type[i].type,
377 metric);
378 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient,
379 AFI_IP, redist_type[i].type, 0,
380 VRF_DEFAULT);
381 return CMD_SUCCESS;
382 }
383 }
384
385 vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text);
386
387 return CMD_WARNING_CONFIG_FAILED;
388 }
389
390 DEFUN (no_rip_redistribute_type_metric,
391 no_rip_redistribute_type_metric_cmd,
392 "no redistribute " FRR_REDIST_STR_RIPD " metric (0-16)",
393 NO_STR
394 REDIST_STR
395 FRR_REDIST_HELP_STR_RIPD
396 "Metric\n"
397 "Metric value\n")
398 {
399 int idx_protocol = 2;
400 int idx_number = 4;
401 int i;
402
403 for (i = 0; redist_type[i].str; i++) {
404 if (strmatch(redist_type[i].str, argv[idx_protocol]->text)) {
405 if (rip_metric_unset(redist_type[i].type,
406 atoi(argv[idx_number]->arg)))
407 return CMD_WARNING_CONFIG_FAILED;
408 rip_redistribute_unset(redist_type[i].type);
409 return CMD_SUCCESS;
410 }
411 }
412
413 vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text);
414
415 return CMD_WARNING_CONFIG_FAILED;
416 }
417
418 DEFUN (rip_redistribute_type_metric_routemap,
419 rip_redistribute_type_metric_routemap_cmd,
420 "redistribute " FRR_REDIST_STR_RIPD " metric (0-16) route-map WORD",
421 REDIST_STR
422 FRR_REDIST_HELP_STR_RIPD
423 "Metric\n"
424 "Metric value\n"
425 "Route map reference\n"
426 "Pointer to route-map entries\n")
427 {
428 int idx_protocol = 1;
429 int idx_number = 3;
430 int idx_word = 5;
431 int i;
432 int metric;
433
434 metric = atoi(argv[idx_number]->arg);
435
436 for (i = 0; redist_type[i].str; i++) {
437 if (strmatch(redist_type[i].str, argv[idx_protocol]->text)) {
438 rip_redistribute_metric_set(redist_type[i].type,
439 metric);
440 rip_routemap_set(redist_type[i].type,
441 argv[idx_word]->arg);
442 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient,
443 AFI_IP, redist_type[i].type, 0,
444 VRF_DEFAULT);
445 return CMD_SUCCESS;
446 }
447 }
448
449 vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text);
450
451 return CMD_WARNING_CONFIG_FAILED;
452 }
453
454
455 DEFUN (no_rip_redistribute_type_metric_routemap,
456 no_rip_redistribute_type_metric_routemap_cmd,
457 "no redistribute " FRR_REDIST_STR_RIPD " metric (0-16) route-map WORD",
458 NO_STR
459 REDIST_STR
460 FRR_REDIST_HELP_STR_RIPD
461 "Metric\n"
462 "Metric value\n"
463 "Route map reference\n"
464 "Pointer to route-map entries\n")
465 {
466 int idx_protocol = 2;
467 int idx_number = 4;
468 int idx_word = 6;
469 int i;
470
471 for (i = 0; redist_type[i].str; i++) {
472 if (strmatch(redist_type[i].str, argv[idx_protocol]->text)) {
473 if (rip_metric_unset(redist_type[i].type,
474 atoi(argv[idx_number]->arg)))
475 return CMD_WARNING_CONFIG_FAILED;
476 if (rip_routemap_unset(redist_type[i].type,
477 argv[idx_word]->arg)) {
478 rip_redistribute_metric_set(
479 redist_type[i].type,
480 atoi(argv[idx_number]->arg));
481 return CMD_WARNING_CONFIG_FAILED;
482 }
483 rip_redistribute_unset(redist_type[i].type);
484 return CMD_SUCCESS;
485 }
486 }
487
488 vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text);
489
490 return CMD_WARNING_CONFIG_FAILED;
491 }
492
493 /* Default information originate. */
494
495 DEFUN (rip_default_information_originate,
496 rip_default_information_originate_cmd,
497 "default-information originate",
498 "Control distribution of default route\n"
499 "Distribute a default route\n")
500 {
501 struct prefix_ipv4 p;
502
503 if (!rip->default_information) {
504 memset(&p, 0, sizeof(struct prefix_ipv4));
505 p.family = AF_INET;
506
507 rip->default_information = 1;
508
509 rip_redistribute_add(ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p, 0,
510 NULL, 0, 0, 0);
511 }
512
513 return CMD_SUCCESS;
514 }
515
516 DEFUN (no_rip_default_information_originate,
517 no_rip_default_information_originate_cmd,
518 "no default-information originate",
519 NO_STR
520 "Control distribution of default route\n"
521 "Distribute a default route\n")
522 {
523 struct prefix_ipv4 p;
524
525 if (rip->default_information) {
526 memset(&p, 0, sizeof(struct prefix_ipv4));
527 p.family = AF_INET;
528
529 rip->default_information = 0;
530
531 rip_redistribute_delete(ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p,
532 0);
533 }
534
535 return CMD_SUCCESS;
536 }
537
538 int config_write_rip_redistribute(struct vty *vty, int config_mode)
539 {
540 int i;
541
542 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
543 if (i == zclient->redist_default
544 || !vrf_bitmap_check(zclient->redist[AFI_IP][i],
545 VRF_DEFAULT))
546 continue;
547
548 if (!config_mode) {
549 vty_out(vty, " %s", zebra_route_string(i));
550 continue;
551 }
552
553 if (rip->route_map[i].metric_config) {
554 if (rip->route_map[i].name)
555 vty_out(vty,
556 " redistribute %s metric %d route-map %s\n",
557 zebra_route_string(i),
558 rip->route_map[i].metric,
559 rip->route_map[i].name);
560 else
561 vty_out(vty, " redistribute %s metric %d\n",
562 zebra_route_string(i),
563 rip->route_map[i].metric);
564 } else {
565 if (rip->route_map[i].name)
566 vty_out(vty, " redistribute %s route-map %s\n",
567 zebra_route_string(i),
568 rip->route_map[i].name);
569 else
570 vty_out(vty, " redistribute %s\n",
571 zebra_route_string(i));
572 }
573 }
574
575 return 0;
576 }
577
578 static void rip_zebra_connected(struct zclient *zclient)
579 {
580 zclient_send_reg_requests(zclient, VRF_DEFAULT);
581 }
582
583 void rip_zclient_init(struct thread_master *master)
584 {
585 /* Set default value to the zebra client structure. */
586 zclient = zclient_new(master);
587 zclient_init(zclient, ZEBRA_ROUTE_RIP, 0);
588 zclient->zebra_connected = rip_zebra_connected;
589 zclient->interface_add = rip_interface_add;
590 zclient->interface_delete = rip_interface_delete;
591 zclient->interface_address_add = rip_interface_address_add;
592 zclient->interface_address_delete = rip_interface_address_delete;
593 zclient->interface_up = rip_interface_up;
594 zclient->interface_down = rip_interface_down;
595 zclient->redistribute_route_add = rip_zebra_read_route;
596 zclient->redistribute_route_del = rip_zebra_read_route;
597
598 /* Install command elements to rip node. */
599 install_element(RIP_NODE, &rip_redistribute_type_cmd);
600 install_element(RIP_NODE, &rip_redistribute_type_routemap_cmd);
601 install_element(RIP_NODE, &rip_redistribute_type_metric_cmd);
602 install_element(RIP_NODE, &rip_redistribute_type_metric_routemap_cmd);
603 install_element(RIP_NODE, &no_rip_redistribute_type_cmd);
604 install_element(RIP_NODE, &no_rip_redistribute_type_routemap_cmd);
605 install_element(RIP_NODE, &no_rip_redistribute_type_metric_cmd);
606 install_element(RIP_NODE,
607 &no_rip_redistribute_type_metric_routemap_cmd);
608 install_element(RIP_NODE, &rip_default_information_originate_cmd);
609 install_element(RIP_NODE, &no_rip_default_information_originate_cmd);
610 }
611
612 void rip_zclient_stop(void)
613 {
614 zclient_stop(zclient);
615 zclient_free(zclient);
616 }