blob: 7ba1adfee05cef16a15fb97b7cc3d96ab59c42d9 [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"
49
50void babelz_zebra_init(void);
51
52
53/* we must use a pointer because of zclient.c's functions (new, free). */
54struct zclient *zclient;
55static int zebra_config_write (struct vty *vty);
56/* Redistribution types */
57static struct {
58 int type;
59 int str_min_len;
60 const char *str;
61} redist_type[] = {
62 {ZEBRA_ROUTE_KERNEL, 1, "kernel"},
63 {ZEBRA_ROUTE_CONNECT, 1, "connected"},
64 {ZEBRA_ROUTE_STATIC, 1, "static"},
65 {ZEBRA_ROUTE_OSPF6, 1, "ospf6"},
66 {ZEBRA_ROUTE_BGP, 1, "bgp"},
67 {0, 0, NULL}
68};
69
70/* Zebra node structure. */
71struct cmd_node zebra_node =
72{
73 ZEBRA_NODE,
74 "%s(config-router)# ",
75 1 /* vtysh? yes */
76};
77
78
79/* Zebra route add and delete treatment (ipv6). */
80static int
81babel_zebra_read_ipv6 (int command, struct zclient *zclient,
82 zebra_size_t length)
83{
84 struct stream *s;
85 struct zapi_ipv6 api;
86 unsigned long ifindex = -1;
87 struct in6_addr nexthop;
88 struct prefix_ipv6 prefix;
89
90 s = zclient->ibuf;
91 ifindex = 0;
92 memset (&nexthop, 0, sizeof (struct in6_addr));
93 memset (&api, 0, sizeof(struct zapi_ipv6));
94 memset (&prefix, 0, sizeof (struct prefix_ipv6));
95
96 /* Type, flags, message. */
97 api.type = stream_getc (s);
98 api.flags = stream_getc (s);
99 api.message = stream_getc (s);
100
101 /* IPv6 prefix. */
102 prefix.family = AF_INET6;
103 prefix.prefixlen = stream_getc (s);
104 stream_get (&prefix.prefix, s, PSIZE (prefix.prefixlen));
105
106 /* Nexthop, ifindex, distance, metric. */
107 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) {
108 api.nexthop_num = stream_getc (s);
109 stream_get (&nexthop, s, sizeof(nexthop));
110 }
111 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) {
112 api.ifindex_num = stream_getc (s);
113 ifindex = stream_getl (s);
114 }
115 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
116 api.distance = stream_getc (s);
117 else
118 api.distance = 0;
119 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
120 api.metric = stream_getl (s);
121 else
122 api.metric = 0;
123
124 if (command == ZEBRA_IPV6_ROUTE_ADD)
125 babel_ipv6_route_add(&api, &prefix, ifindex, &nexthop);
126 else
127 babel_ipv6_route_delete(&api, &prefix, ifindex);
128
129 return 0;
130}
131
132static int
133babel_zebra_read_ipv4 (int command, struct zclient *zclient,
134 zebra_size_t length)
135{
136 struct stream *s;
137 struct zapi_ipv4 api;
138 unsigned long ifindex = -1;
139 struct in_addr nexthop;
140 struct prefix_ipv4 prefix;
141
142 s = zclient->ibuf;
143 ifindex = 0;
144 memset (&nexthop, 0, sizeof (struct in_addr));
145 memset (&api, 0, sizeof(struct zapi_ipv4));
146 memset (&prefix, 0, sizeof (struct prefix_ipv4));
147
148 /* Type, flags, message. */
149 api.type = stream_getc (s);
150 api.flags = stream_getc (s);
151 api.message = stream_getc (s);
152
153 /* IPv6 prefix. */
154 prefix.family = AF_INET;
155 prefix.prefixlen = stream_getc (s);
156 stream_get (&prefix.prefix, s, PSIZE (prefix.prefixlen));
157
158 /* Nexthop, ifindex, distance, metric. */
159 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) {
160 api.nexthop_num = stream_getc (s);
161 stream_get (&nexthop, s, sizeof(nexthop));
162 }
163 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) {
164 api.ifindex_num = stream_getc (s);
165 ifindex = stream_getl (s);
166 }
167 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
168 api.distance = stream_getc (s);
169 else
170 api.distance = 0;
171 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
172 api.metric = stream_getl (s);
173 else
174 api.metric = 0;
175
176 if (command == ZEBRA_IPV6_ROUTE_ADD) {
177 babel_ipv4_route_add(&api, &prefix, ifindex, &nexthop);
178 } else {
179 babel_ipv4_route_delete(&api, &prefix, ifindex);
180 }
181
182 return 0;
183}
184
185static int
186babel_redistribute_unset (int type)
187{
188 if (! zclient->redist[type])
189 return CMD_SUCCESS;
190
191 zclient->redist[type] = 0;
192
193 if (zclient->sock > 0)
194 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, type);
195
196 /* perhaps should we remove xroutes having the same type... */
197
198 return CMD_SUCCESS;
199}
200
201
202/* [Babel Command] */
203DEFUN (babel_redistribute_type,
204 babel_redistribute_type_cmd,
205 "redistribute (kernel|connected|static|ospf6|bgp)",
206 "Redistribute information from another routing protocol\n"
207 "Kernel routes\n"
208 "Connected\n"
209 "Static routes\n"
210 "Open Shortest Path First (OSPFv3)\n"
211 "Border Gateway Protocol (BGP)\n")
212{
213 int i;
214
215 for(i = 0; redist_type[i].str != NULL; i++) {
216 if (strncmp (redist_type[i].str, argv[0],
217 redist_type[i].str_min_len) == 0) {
218 zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient,
219 redist_type[i].type);
220 return CMD_SUCCESS;
221 }
222 }
223
224 vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE);
225
226 return CMD_WARNING;
227}
228
229/* [Babel Command] */
230DEFUN (no_babel_redistribute_type,
231 no_babel_redistribute_type_cmd,
232 "no redistribute (kernel|connected|static|ospf6|bgp)",
233 NO_STR
234 "Redistribute information from another routing protocol\n"
235 "Kernel routes\n"
236 "Connected\n"
237 "Static routes\n"
238 "Open Shortest Path First (OSPFv3)\n"
239 "Border Gateway Protocol (BGP)\n")
240{
241 int i;
242
243 for (i = 0; redist_type[i].str; i++) {
244 if (strncmp(redist_type[i].str, argv[0],
245 redist_type[i].str_min_len) == 0) {
246 return babel_redistribute_unset (redist_type[i].type);
247 }
248 }
249
250 vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE);
251
252 return CMD_WARNING;
253}
254
255
256void babelz_zebra_init(void)
257{
258 zclient = zclient_new();
259 zclient_init(zclient, ZEBRA_ROUTE_BABEL);
260
261 zclient->interface_add = babel_interface_add;
262 zclient->interface_delete = babel_interface_delete;
263 zclient->interface_up = babel_interface_up;
264 zclient->interface_down = babel_interface_down;
265 zclient->interface_address_add = babel_interface_address_add;
266 zclient->interface_address_delete = babel_interface_address_delete;
267 zclient->ipv4_route_add = babel_zebra_read_ipv4;
268 zclient->ipv4_route_delete = babel_zebra_read_ipv4;
269 zclient->ipv6_route_add = babel_zebra_read_ipv6;
270 zclient->ipv6_route_delete = babel_zebra_read_ipv6;
271
272 install_node (&zebra_node, zebra_config_write);
273 install_element(BABEL_NODE, &babel_redistribute_type_cmd);
274 install_element(BABEL_NODE, &no_babel_redistribute_type_cmd);
275}
276
277static int
278zebra_config_write (struct vty *vty)
279{
Paul Jakma57345092011-12-25 17:52:09 +0100280 if (! zclient->enable)
281 {
282 vty_out (vty, "no router zebra%s", VTY_NEWLINE);
283 return 1;
284 }
285 else if (! zclient->redist[ZEBRA_ROUTE_BABEL])
286 {
287 vty_out (vty, "router zebra%s", VTY_NEWLINE);
288 vty_out (vty, " no redistribute babel%s", VTY_NEWLINE);
289 return 1;
290 }
291 return 0;
292}
293
294void
295babel_zebra_close_connexion(void)
296{
297 zclient_stop(zclient);
298}