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 "stream.h" 28#include "routemap.h" 29#include "zclient.h" 30#include "log.h" 31 32#include "ripngd/ripngd.h" 33 34/* All information about zebra. */ 35struct zclient *zclient = NULL; 36 37/* Callback prototypes for zebra client service. */ 38int ripng_interface_up (int, struct zclient *, zebra_size_t); 39int ripng_interface_down (int, struct zclient *, zebra_size_t); 40int ripng_interface_add (int, struct zclient *, zebra_size_t); 41int ripng_interface_delete (int, struct zclient *, zebra_size_t); 42int ripng_interface_address_add (int, struct zclient *, zebra_size_t); 43int ripng_interface_address_delete (int, struct zclient *, zebra_size_t); 44 45void 46ripng_zebra_ipv6_add (struct prefix_ipv6 *p, struct in6_addr *nexthop, 47 unsigned int ifindex, u_char metric) 48{ 49 struct zapi_ipv6 api; 50 51 if (zclient->redist[ZEBRA_ROUTE_RIPNG]) 52 { 53 api.type = ZEBRA_ROUTE_RIPNG; 54 api.flags = 0; 55 api.message = 0; 56 api.safi = SAFI_UNICAST; 57 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); 58 api.nexthop_num = 1; 59 api.nexthop = &nexthop; 60 SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX); 61 api.ifindex_num = 1; 62 api.ifindex = &ifindex; 63 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); 64 api.metric = metric; 65 66 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient, p, &api); 67 } 68} 69 70void 71ripng_zebra_ipv6_delete (struct prefix_ipv6 *p, struct in6_addr *nexthop, 72 unsigned int ifindex) 73{ 74 struct zapi_ipv6 api; 75 76 if (zclient->redist[ZEBRA_ROUTE_RIPNG]) 77 { 78 api.type = ZEBRA_ROUTE_RIPNG; 79 api.flags = 0; 80 api.message = 0; 81 api.safi = SAFI_UNICAST; 82 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); 83 api.nexthop_num = 1; 84 api.nexthop = &nexthop; 85 SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX); 86 api.ifindex_num = 1; 87 api.ifindex = &ifindex; 88 89 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, p, &api); 90 } 91} 92 93/* Zebra route add and delete treatment. */ 94static int 95ripng_zebra_read_ipv6 (int command, struct zclient *zclient, 96 zebra_size_t length) 97{ 98 struct stream *s; 99 struct zapi_ipv6 api; 100 unsigned long ifindex; 101 struct in6_addr nexthop; 102 struct prefix_ipv6 p; 103 104 s = zclient->ibuf; 105 ifindex = 0; 106 memset (&nexthop, 0, sizeof (struct in6_addr)); 107 108 /* Type, flags, message. */ 109 api.type = stream_getc (s); 110 api.flags = stream_getc (s); 111 api.message = stream_getc (s); 112 113 /* IPv6 prefix. */ 114 memset (&p, 0, sizeof (struct prefix_ipv6)); 115 p.family = AF_INET6; 116 p.prefixlen = stream_getc (s); 117 stream_get (&p.prefix, s, PSIZE (p.prefixlen)); 118 119 /* Nexthop, ifindex, distance, metric. */ 120 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) 121 { 122 api.nexthop_num = stream_getc (s); 123 stream_get (&nexthop, s, 16); 124 } 125 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) 126 { 127 api.ifindex_num = stream_getc (s); 128 ifindex = stream_getl (s); 129 } 130 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) 131 api.distance = stream_getc (s); 132 else 133 api.distance = 0; 134 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) 135 api.metric = stream_getl (s); 136 else 137 api.metric = 0; 138 139 if (command == ZEBRA_IPV6_ROUTE_ADD) 140 ripng_redistribute_add (api.type, RIPNG_ROUTE_REDISTRIBUTE, &p, ifindex, &nexthop); 141 else 142 ripng_redistribute_delete (api.type, RIPNG_ROUTE_REDISTRIBUTE, &p, ifindex); 143 144 return 0; 145} 146 147void 148ripng_zclient_reset (void) 149{ 150 zclient_reset (zclient); 151} 152 153static int 154ripng_redistribute_unset (int type) 155{ 156 if (! zclient->redist[type]) 157 return CMD_SUCCESS; 158 159 zclient->redist[type] = 0; 160 161 if (zclient->sock > 0) 162 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, type); 163 164 ripng_redistribute_withdraw (type); 165 166 return CMD_SUCCESS; 167} 168 169int 170ripng_redistribute_check (int type) 171{ 172 return (zclient->redist[type]); 173} 174 175static void 176ripng_redistribute_metric_set (int type, int metric) 177{ 178 ripng->route_map[type].metric_config = 1; 179 ripng->route_map[type].metric = metric; 180} 181 182static int 183ripng_redistribute_metric_unset (int type) 184{ 185 ripng->route_map[type].metric_config = 0; 186 ripng->route_map[type].metric = 0; 187 return 0; 188} 189 190static void 191ripng_redistribute_routemap_set (int type, const char *name) 192{ 193 if (ripng->route_map[type].name) 194 free (ripng->route_map[type].name); 195 196 ripng->route_map[type].name = strdup (name); 197 ripng->route_map[type].map = route_map_lookup_by_name (name); 198} 199 200static void 201ripng_redistribute_routemap_unset (int type) 202{ 203 if (ripng->route_map[type].name) 204 free (ripng->route_map[type].name); 205 206 ripng->route_map[type].name = NULL; 207 ripng->route_map[type].map = NULL; 208} 209 210/* Redistribution types */ 211static struct { 212 int type; 213 int str_min_len; 214 const char *str; 215} redist_type[] = { 216 {ZEBRA_ROUTE_KERNEL, 1, "kernel"}, 217 {ZEBRA_ROUTE_CONNECT, 1, "connected"}, 218 {ZEBRA_ROUTE_STATIC, 1, "static"}, 219 {ZEBRA_ROUTE_OSPF6, 1, "ospf6"}, 220 {ZEBRA_ROUTE_BGP, 2, "bgp"}, 221 {ZEBRA_ROUTE_BABEL, 2, "babel"}, 222 {0, 0, NULL} 223}; 224 225void 226ripng_redistribute_clean () 227{ 228 int i; 229 230 for (i = 0; redist_type[i].str; i++) 231 { 232 if (zclient->redist[redist_type[i].type]) 233 { 234 if (zclient->sock > 0) 235 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, 236 zclient, redist_type[i].type); 237 238 zclient->redist[redist_type[i].type] = 0; 239 240 /* Remove the routes from RIPng table. */ 241 ripng_redistribute_withdraw (redist_type[i].type); 242 } 243 } 244} 245 246DEFUN (router_zebra, 247 router_zebra_cmd, 248 "router zebra", 249 "Enable a routing process\n" 250 "Make connection to zebra daemon\n") 251{ 252 vty->node = ZEBRA_NODE; 253 zclient->enable = 1; 254 zclient_start (zclient); 255 return CMD_SUCCESS; 256} 257 258DEFUN (no_router_zebra, 259 no_router_zebra_cmd, 260 "no router zebra", 261 NO_STR 262 "Disable a routing process\n" 263 "Stop connection to zebra daemon\n") 264{ 265 zclient->enable = 0; 266 zclient_stop (zclient); 267 return CMD_SUCCESS; 268} 269 270DEFUN (ripng_redistribute_ripng, 271 ripng_redistribute_ripng_cmd, 272 "redistribute ripng", 273 "Redistribute information from another routing protocol\n" 274 "RIPng route\n") 275{ 276 zclient->redist[ZEBRA_ROUTE_RIPNG] = 1; 277 return CMD_SUCCESS; 278} 279 280DEFUN (no_ripng_redistribute_ripng, 281 no_ripng_redistribute_ripng_cmd, 282 "no redistribute ripng", 283 NO_STR 284 "Redistribute information from another routing protocol\n" 285 "RIPng route\n") 286{ 287 zclient->redist[ZEBRA_ROUTE_RIPNG] = 0; 288 return CMD_SUCCESS; 289} 290 291DEFUN (ripng_redistribute_type, 292 ripng_redistribute_type_cmd, 293 "redistribute " QUAGGA_REDIST_STR_RIPNGD, 294 "Redistribute\n" 295 QUAGGA_REDIST_HELP_STR_RIPNGD) 296{ 297 int type; 298 299 type = proto_redistnum(AFI_IP6, argv[0]); 300 301 if (type < 0) 302 { 303 vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE); 304 return CMD_WARNING; 305 } 306 307 zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, type); 308 return CMD_SUCCESS; 309} 310 311DEFUN (no_ripng_redistribute_type, 312 no_ripng_redistribute_type_cmd, 313 "no redistribute " QUAGGA_REDIST_STR_RIPNGD, 314 NO_STR 315 "Redistribute\n" 316 QUAGGA_REDIST_HELP_STR_RIPNGD) 317{ 318 int type; 319 320 type = proto_redistnum(AFI_IP6, argv[0]); 321 322 if (type < 0) 323 { 324 vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE); 325 return CMD_WARNING; 326 } 327 328 ripng_redistribute_metric_unset (type); 329 ripng_redistribute_routemap_unset (type); 330 return ripng_redistribute_unset (type); 331} 332 333 334DEFUN (ripng_redistribute_type_metric, 335 ripng_redistribute_type_metric_cmd, 336 "redistribute " QUAGGA_REDIST_STR_RIPNGD " metric <0-16>", 337 "Redistribute\n" 338 QUAGGA_REDIST_HELP_STR_RIPNGD 339 "Metric\n" 340 "Metric value\n") 341{ 342 int type; 343 int metric; 344 345 metric = atoi (argv[1]); 346 type = proto_redistnum(AFI_IP6, argv[0]); 347 348 if (type < 0) 349 { 350 vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE); 351 return CMD_WARNING; 352 } 353 354 ripng_redistribute_metric_set (type, metric); 355 zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, type); 356 return CMD_SUCCESS; 357} 358 359ALIAS (no_ripng_redistribute_type, 360 no_ripng_redistribute_type_metric_cmd, 361 "no redistribute " QUAGGA_REDIST_STR_RIPNGD " metric <0-16>", 362 NO_STR 363 "Redistribute\n" 364 QUAGGA_REDIST_HELP_STR_RIPNGD 365 "Metric\n" 366 "Metric value\n") 367 368DEFUN (ripng_redistribute_type_routemap, 369 ripng_redistribute_type_routemap_cmd, 370 "redistribute " QUAGGA_REDIST_STR_RIPNGD " route-map WORD", 371 "Redistribute\n" 372 QUAGGA_REDIST_HELP_STR_RIPNGD 373 "Route map reference\n" 374 "Pointer to route-map entries\n") 375{ 376 int type; 377 378 type = proto_redistnum(AFI_IP6, argv[0]); 379 380 if (type < 0) 381 { 382 vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE); 383 return CMD_WARNING; 384 } 385 386 ripng_redistribute_routemap_set (type, argv[1]); 387 zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, type); 388 return CMD_SUCCESS; 389} 390 391ALIAS (no_ripng_redistribute_type, 392 no_ripng_redistribute_type_routemap_cmd, 393 "no redistribute " QUAGGA_REDIST_STR_RIPNGD " route-map WORD", 394 NO_STR 395 "Redistribute\n" 396 QUAGGA_REDIST_HELP_STR_RIPNGD 397 "Route map reference\n" 398 "Pointer to route-map entries\n") 399 400DEFUN (ripng_redistribute_type_metric_routemap, 401 ripng_redistribute_type_metric_routemap_cmd, 402 "redistribute " QUAGGA_REDIST_STR_RIPNGD " metric <0-16> route-map WORD", 403 "Redistribute\n" 404 QUAGGA_REDIST_HELP_STR_RIPNGD 405 "Metric\n" 406 "Metric value\n" 407 "Route map reference\n" 408 "Pointer to route-map entries\n") 409{ 410 int type; 411 int metric; 412 413 type = proto_redistnum(AFI_IP6, argv[0]); 414 metric = atoi (argv[1]); 415 416 if (type < 0) 417 { 418 vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE); 419 return CMD_WARNING; 420 } 421 422 ripng_redistribute_metric_set (type, metric); 423 ripng_redistribute_routemap_set (type, argv[2]); 424 zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, type); 425 return CMD_SUCCESS; 426} 427 428ALIAS (no_ripng_redistribute_type, 429 no_ripng_redistribute_type_metric_routemap_cmd, 430 "no redistribute " QUAGGA_REDIST_STR_RIPNGD " metric <0-16> route-map WORD", 431 NO_STR 432 "Redistribute\n" 433 QUAGGA_REDIST_HELP_STR_RIPNGD 434 "Route map reference\n" 435 "Pointer to route-map entries\n") 436 437void 438ripng_redistribute_write (struct vty *vty, int config_mode) 439{ 440 int i; 441 442 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) 443 if (i != zclient->redist_default && zclient->redist[i]) 444 { 445 if (config_mode) 446 { 447 if (ripng->route_map[i].metric_config) 448 { 449 if (ripng->route_map[i].name) 450 vty_out (vty, " redistribute %s metric %d route-map %s%s", 451 zebra_route_string(i), ripng->route_map[i].metric, 452 ripng->route_map[i].name, VTY_NEWLINE); 453 else 454 vty_out (vty, " redistribute %s metric %d%s", 455 zebra_route_string(i), ripng->route_map[i].metric, 456 VTY_NEWLINE); 457 } 458 else 459 { 460 if (ripng->route_map[i].name) 461 vty_out (vty, " redistribute %s route-map %s%s", 462 zebra_route_string(i), ripng->route_map[i].name, 463 VTY_NEWLINE); 464 else 465 vty_out (vty, " redistribute %s%s", zebra_route_string(i), 466 VTY_NEWLINE); 467 } 468 } 469 else 470 vty_out (vty, " %s", zebra_route_string(i)); 471 } 472} 473 474/* RIPng configuration write function. */ 475static int 476zebra_config_write (struct vty *vty) 477{ 478 if (! zclient->enable) 479 { 480 vty_out (vty, "no router zebra%s", VTY_NEWLINE); 481 return 1; 482 } 483 else if (! zclient->redist[ZEBRA_ROUTE_RIPNG]) 484 { 485 vty_out (vty, "router zebra%s", VTY_NEWLINE); 486 vty_out (vty, " no redistribute ripng%s", VTY_NEWLINE); 487 return 1; 488 } 489 return 0; 490} 491 492/* Zebra node structure. */ 493static struct cmd_node zebra_node = 494{ 495 ZEBRA_NODE, 496 "%s(config-router)# ", 497}; 498 499/* Initialize zebra structure and it's commands. */ 500void 501zebra_init () 502{ 503 /* Allocate zebra structure. */ 504 zclient = zclient_new (); 505 zclient_init (zclient, ZEBRA_ROUTE_RIPNG); 506 507 zclient->interface_up = ripng_interface_up; 508 zclient->interface_down = ripng_interface_down; 509 zclient->interface_add = ripng_interface_add; 510 zclient->interface_delete = ripng_interface_delete; 511 zclient->interface_address_add = ripng_interface_address_add; 512 zclient->interface_address_delete = ripng_interface_address_delete; 513 zclient->ipv6_route_add = ripng_zebra_read_ipv6; 514 zclient->ipv6_route_delete = ripng_zebra_read_ipv6; 515 516 /* Install zebra node. */ 517 install_node (&zebra_node, zebra_config_write); 518 519 /* Install command element for zebra node. */ 520 install_element (CONFIG_NODE, &router_zebra_cmd); 521 install_element (CONFIG_NODE, &no_router_zebra_cmd); 522 install_default (ZEBRA_NODE); 523 install_element (ZEBRA_NODE, &ripng_redistribute_ripng_cmd); 524 install_element (ZEBRA_NODE, &no_ripng_redistribute_ripng_cmd); 525 526 /* Install command elements to ripng node */ 527 install_element (RIPNG_NODE, &ripng_redistribute_type_cmd); 528 install_element (RIPNG_NODE, &ripng_redistribute_type_routemap_cmd); 529 install_element (RIPNG_NODE, &ripng_redistribute_type_metric_cmd); 530 install_element (RIPNG_NODE, &ripng_redistribute_type_metric_routemap_cmd); 531 install_element (RIPNG_NODE, &no_ripng_redistribute_type_cmd); 532 install_element (RIPNG_NODE, &no_ripng_redistribute_type_routemap_cmd); 533 install_element (RIPNG_NODE, &no_ripng_redistribute_type_metric_cmd); 534 install_element (RIPNG_NODE, &no_ripng_redistribute_type_metric_routemap_cmd); 535} 536