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