blob: e68c2b70fa220fc5cca1fb09c73ec52f9a037f44 [file] [log] [blame]
Paul Jakma57345092011-12-25 17:52:09 +01001/*
2 * This file is free software: you may copy, redistribute and/or modify it
3 * under the terms of the GNU General Public License as published by the
4 * Free Software Foundation, either version 2 of the License, or (at your
5 * option) any later version.
6 *
7 * This file is distributed in the hope that it will be useful, but
8 * WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 *
15 * This file incorporates work covered by the following copyright and
16 * permission notice:
17 *
18Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
19
20Permission is hereby granted, free of charge, to any person obtaining a copy
21of this software and associated documentation files (the "Software"), to deal
22in the Software without restriction, including without limitation the rights
23to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
24copies of the Software, and to permit persons to whom the Software is
25furnished to do so, subject to the following conditions:
26
27The above copyright notice and this permission notice shall be included in
28all copies or substantial portions of the Software.
29
30THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
36THE SOFTWARE.
37*/
38
39/* quagga's includes */
40#include <zebra.h>
41#include "command.h"
42#include "zclient.h"
43#include "stream.h"
44
45/* babel's includes*/
46#include "babel_zebra.h"
47#include "babel_interface.h"
48#include "xroute.h"
Matthieu Boutierf1305cb2012-01-20 00:19:35 +010049#include "util.h"
Paul Jakma57345092011-12-25 17:52:09 +010050
51void babelz_zebra_init(void);
52
53
54/* we must use a pointer because of zclient.c's functions (new, free). */
55struct zclient *zclient;
56static int zebra_config_write (struct vty *vty);
57/* Redistribution types */
58static struct {
59 int type;
60 int str_min_len;
61 const char *str;
62} redist_type[] = {
63 {ZEBRA_ROUTE_KERNEL, 1, "kernel"},
64 {ZEBRA_ROUTE_CONNECT, 1, "connected"},
65 {ZEBRA_ROUTE_STATIC, 1, "static"},
66 {ZEBRA_ROUTE_OSPF6, 1, "ospf6"},
67 {ZEBRA_ROUTE_BGP, 1, "bgp"},
68 {0, 0, NULL}
69};
70
Matthieu Boutierf1305cb2012-01-20 00:19:35 +010071/* Debug types */
72static struct {
73 int type;
74 int str_min_len;
75 const char *str;
76} debug_type[] = {
77 {BABEL_DEBUG_COMMON, 1, "common"},
78 {BABEL_DEBUG_KERNEL, 1, "kernel"},
79 {BABEL_DEBUG_FILTER, 1, "filter"},
80 {BABEL_DEBUG_TIMEOUT, 1, "timeout"},
81 {BABEL_DEBUG_IF, 1, "interface"},
82 {BABEL_DEBUG_ROUTE, 1, "route"},
83 {BABEL_DEBUG_ALL, 1, "all"},
84 {0, 0, NULL}
85};
86
Paul Jakma57345092011-12-25 17:52:09 +010087/* Zebra node structure. */
88struct cmd_node zebra_node =
89{
90 ZEBRA_NODE,
91 "%s(config-router)# ",
92 1 /* vtysh? yes */
93};
94
95
96/* Zebra route add and delete treatment (ipv6). */
97static int
98babel_zebra_read_ipv6 (int command, struct zclient *zclient,
99 zebra_size_t length)
100{
101 struct stream *s;
102 struct zapi_ipv6 api;
103 unsigned long ifindex = -1;
104 struct in6_addr nexthop;
105 struct prefix_ipv6 prefix;
106
107 s = zclient->ibuf;
108 ifindex = 0;
109 memset (&nexthop, 0, sizeof (struct in6_addr));
110 memset (&api, 0, sizeof(struct zapi_ipv6));
111 memset (&prefix, 0, sizeof (struct prefix_ipv6));
112
113 /* Type, flags, message. */
114 api.type = stream_getc (s);
115 api.flags = stream_getc (s);
116 api.message = stream_getc (s);
117
118 /* IPv6 prefix. */
119 prefix.family = AF_INET6;
120 prefix.prefixlen = stream_getc (s);
121 stream_get (&prefix.prefix, s, PSIZE (prefix.prefixlen));
122
123 /* Nexthop, ifindex, distance, metric. */
124 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) {
125 api.nexthop_num = stream_getc (s);
126 stream_get (&nexthop, s, sizeof(nexthop));
127 }
128 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) {
129 api.ifindex_num = stream_getc (s);
130 ifindex = stream_getl (s);
131 }
132 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
133 api.distance = stream_getc (s);
134 else
135 api.distance = 0;
136 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
137 api.metric = stream_getl (s);
138 else
139 api.metric = 0;
140
141 if (command == ZEBRA_IPV6_ROUTE_ADD)
142 babel_ipv6_route_add(&api, &prefix, ifindex, &nexthop);
143 else
144 babel_ipv6_route_delete(&api, &prefix, ifindex);
145
146 return 0;
147}
148
149static int
150babel_zebra_read_ipv4 (int command, struct zclient *zclient,
151 zebra_size_t length)
152{
153 struct stream *s;
154 struct zapi_ipv4 api;
155 unsigned long ifindex = -1;
156 struct in_addr nexthop;
157 struct prefix_ipv4 prefix;
158
159 s = zclient->ibuf;
160 ifindex = 0;
161 memset (&nexthop, 0, sizeof (struct in_addr));
162 memset (&api, 0, sizeof(struct zapi_ipv4));
163 memset (&prefix, 0, sizeof (struct prefix_ipv4));
164
165 /* Type, flags, message. */
166 api.type = stream_getc (s);
167 api.flags = stream_getc (s);
168 api.message = stream_getc (s);
169
170 /* IPv6 prefix. */
171 prefix.family = AF_INET;
172 prefix.prefixlen = stream_getc (s);
173 stream_get (&prefix.prefix, s, PSIZE (prefix.prefixlen));
174
175 /* Nexthop, ifindex, distance, metric. */
176 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) {
177 api.nexthop_num = stream_getc (s);
178 stream_get (&nexthop, s, sizeof(nexthop));
179 }
180 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) {
181 api.ifindex_num = stream_getc (s);
182 ifindex = stream_getl (s);
183 }
184 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
185 api.distance = stream_getc (s);
186 else
187 api.distance = 0;
188 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
189 api.metric = stream_getl (s);
190 else
191 api.metric = 0;
192
193 if (command == ZEBRA_IPV6_ROUTE_ADD) {
194 babel_ipv4_route_add(&api, &prefix, ifindex, &nexthop);
195 } else {
196 babel_ipv4_route_delete(&api, &prefix, ifindex);
197 }
198
199 return 0;
200}
201
202static int
203babel_redistribute_unset (int type)
204{
205 if (! zclient->redist[type])
206 return CMD_SUCCESS;
207
208 zclient->redist[type] = 0;
209
210 if (zclient->sock > 0)
211 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, type);
212
213 /* perhaps should we remove xroutes having the same type... */
214
215 return CMD_SUCCESS;
216}
217
218
219/* [Babel Command] */
220DEFUN (babel_redistribute_type,
221 babel_redistribute_type_cmd,
222 "redistribute (kernel|connected|static|ospf6|bgp)",
223 "Redistribute information from another routing protocol\n"
224 "Kernel routes\n"
225 "Connected\n"
226 "Static routes\n"
227 "Open Shortest Path First (OSPFv3)\n"
228 "Border Gateway Protocol (BGP)\n")
229{
230 int i;
231
232 for(i = 0; redist_type[i].str != NULL; i++) {
233 if (strncmp (redist_type[i].str, argv[0],
234 redist_type[i].str_min_len) == 0) {
235 zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient,
236 redist_type[i].type);
237 return CMD_SUCCESS;
238 }
239 }
240
241 vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE);
242
243 return CMD_WARNING;
244}
245
246/* [Babel Command] */
247DEFUN (no_babel_redistribute_type,
248 no_babel_redistribute_type_cmd,
249 "no redistribute (kernel|connected|static|ospf6|bgp)",
250 NO_STR
251 "Redistribute information from another routing protocol\n"
252 "Kernel routes\n"
253 "Connected\n"
254 "Static routes\n"
255 "Open Shortest Path First (OSPFv3)\n"
256 "Border Gateway Protocol (BGP)\n")
257{
258 int i;
259
260 for (i = 0; redist_type[i].str; i++) {
261 if (strncmp(redist_type[i].str, argv[0],
262 redist_type[i].str_min_len) == 0) {
263 return babel_redistribute_unset (redist_type[i].type);
264 }
265 }
266
267 vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE);
268
269 return CMD_WARNING;
270}
271
Matthieu Boutierf1305cb2012-01-20 00:19:35 +0100272#ifndef NO_DEBUG
273/* [Babel Command] */
274DEFUN (babel_debug,
275 babel_debug_cmd,
276 "debug (common|kernel|filter|timeout|interface|route|all)",
277 "Enable debug messages for specific or all part.\n"
278 "Common messages (default)\n"
279 "Kernel messages\n"
280 "Filter messages\n"
281 "Timeout messages\n"
282 "Interface messages\n"
283 "Route messages\n"
284 "All messages\n")
285{
286 int i;
287
288 for(i = 0; debug_type[i].str != NULL; i++) {
289 if (strncmp (debug_type[i].str, argv[0],
290 debug_type[i].str_min_len) == 0) {
291 debug |= debug_type[i].type;
292 return CMD_SUCCESS;
293 }
294 }
295
296 vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE);
297
298 return CMD_WARNING;
299}
300
301/* [Babel Command] */
302DEFUN (no_babel_debug,
303 no_babel_debug_cmd,
304 "no debug (common|kernel|filter|timeout|interface|route|all)",
305 NO_STR
306 "Disable debug messages for specific or all part.\n"
307 "Common messages (default)\n"
308 "Kernel messages\n"
309 "Filter messages\n"
310 "Timeout messages\n"
311 "Interface messages\n"
312 "Route messages\n"
313 "All messages\n")
314{
315 int i;
316
317 for (i = 0; debug_type[i].str; i++) {
318 if (strncmp(debug_type[i].str, argv[0],
319 debug_type[i].str_min_len) == 0) {
320 debug &= ~debug_type[i].type;
321 }
322 }
323
324 vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE);
325
326 return CMD_WARNING;
327}
328#endif /* NO_DEBUG */
329
Paul Jakma57345092011-12-25 17:52:09 +0100330
331void babelz_zebra_init(void)
332{
333 zclient = zclient_new();
334 zclient_init(zclient, ZEBRA_ROUTE_BABEL);
335
336 zclient->interface_add = babel_interface_add;
337 zclient->interface_delete = babel_interface_delete;
338 zclient->interface_up = babel_interface_up;
339 zclient->interface_down = babel_interface_down;
340 zclient->interface_address_add = babel_interface_address_add;
341 zclient->interface_address_delete = babel_interface_address_delete;
342 zclient->ipv4_route_add = babel_zebra_read_ipv4;
343 zclient->ipv4_route_delete = babel_zebra_read_ipv4;
344 zclient->ipv6_route_add = babel_zebra_read_ipv6;
345 zclient->ipv6_route_delete = babel_zebra_read_ipv6;
346
347 install_node (&zebra_node, zebra_config_write);
348 install_element(BABEL_NODE, &babel_redistribute_type_cmd);
349 install_element(BABEL_NODE, &no_babel_redistribute_type_cmd);
Matthieu Boutierf1305cb2012-01-20 00:19:35 +0100350 install_element(BABEL_NODE, &babel_debug_cmd);
351 install_element(BABEL_NODE, &no_babel_debug_cmd);
Paul Jakma57345092011-12-25 17:52:09 +0100352}
353
354static int
355zebra_config_write (struct vty *vty)
356{
Paul Jakma57345092011-12-25 17:52:09 +0100357 if (! zclient->enable)
358 {
359 vty_out (vty, "no router zebra%s", VTY_NEWLINE);
360 return 1;
361 }
362 else if (! zclient->redist[ZEBRA_ROUTE_BABEL])
363 {
364 vty_out (vty, "router zebra%s", VTY_NEWLINE);
365 vty_out (vty, " no redistribute babel%s", VTY_NEWLINE);
366 return 1;
367 }
368 return 0;
369}
370
371void
372babel_zebra_close_connexion(void)
373{
374 zclient_stop(zclient);
375}