]>
Commit | Line | Data |
---|---|---|
5734509c PJ |
1 | /* |
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 | * | |
18 | Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek | |
19 | ||
20 | Permission is hereby granted, free of charge, to any person obtaining a copy | |
21 | of this software and associated documentation files (the "Software"), to deal | |
22 | in the Software without restriction, including without limitation the rights | |
23 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
24 | copies of the Software, and to permit persons to whom the Software is | |
25 | furnished to do so, subject to the following conditions: | |
26 | ||
27 | The above copyright notice and this permission notice shall be included in | |
28 | all copies or substantial portions of the Software. | |
29 | ||
30 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
31 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
32 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
33 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
34 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
35 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
36 | THE 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" | |
f1305cbf | 49 | #include "util.h" |
5734509c PJ |
50 | |
51 | void babelz_zebra_init(void); | |
52 | ||
53 | ||
54 | /* we must use a pointer because of zclient.c's functions (new, free). */ | |
55 | struct zclient *zclient; | |
56 | static int zebra_config_write (struct vty *vty); | |
5734509c | 57 | |
f1305cbf MB |
58 | /* Debug types */ |
59 | static struct { | |
60 | int type; | |
61 | int str_min_len; | |
62 | const char *str; | |
63 | } debug_type[] = { | |
64 | {BABEL_DEBUG_COMMON, 1, "common"}, | |
65 | {BABEL_DEBUG_KERNEL, 1, "kernel"}, | |
66 | {BABEL_DEBUG_FILTER, 1, "filter"}, | |
67 | {BABEL_DEBUG_TIMEOUT, 1, "timeout"}, | |
68 | {BABEL_DEBUG_IF, 1, "interface"}, | |
69 | {BABEL_DEBUG_ROUTE, 1, "route"}, | |
70 | {BABEL_DEBUG_ALL, 1, "all"}, | |
71 | {0, 0, NULL} | |
72 | }; | |
73 | ||
5734509c PJ |
74 | /* Zebra node structure. */ |
75 | struct cmd_node zebra_node = | |
76 | { | |
77 | ZEBRA_NODE, | |
78 | "%s(config-router)# ", | |
79 | 1 /* vtysh? yes */ | |
80 | }; | |
81 | ||
82 | ||
83 | /* Zebra route add and delete treatment (ipv6). */ | |
84 | static int | |
85 | babel_zebra_read_ipv6 (int command, struct zclient *zclient, | |
86 | zebra_size_t length) | |
87 | { | |
88 | struct stream *s; | |
89 | struct zapi_ipv6 api; | |
90 | unsigned long ifindex = -1; | |
91 | struct in6_addr nexthop; | |
92 | struct prefix_ipv6 prefix; | |
93 | ||
94 | s = zclient->ibuf; | |
95 | ifindex = 0; | |
96 | memset (&nexthop, 0, sizeof (struct in6_addr)); | |
97 | memset (&api, 0, sizeof(struct zapi_ipv6)); | |
98 | memset (&prefix, 0, sizeof (struct prefix_ipv6)); | |
99 | ||
100 | /* Type, flags, message. */ | |
101 | api.type = stream_getc (s); | |
102 | api.flags = stream_getc (s); | |
103 | api.message = stream_getc (s); | |
104 | ||
105 | /* IPv6 prefix. */ | |
106 | prefix.family = AF_INET6; | |
107 | prefix.prefixlen = stream_getc (s); | |
108 | stream_get (&prefix.prefix, s, PSIZE (prefix.prefixlen)); | |
109 | ||
110 | /* Nexthop, ifindex, distance, metric. */ | |
111 | if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) { | |
112 | api.nexthop_num = stream_getc (s); | |
113 | stream_get (&nexthop, s, sizeof(nexthop)); | |
114 | } | |
115 | if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) { | |
116 | api.ifindex_num = stream_getc (s); | |
117 | ifindex = stream_getl (s); | |
118 | } | |
119 | if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) | |
120 | api.distance = stream_getc (s); | |
121 | else | |
122 | api.distance = 0; | |
123 | if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) | |
124 | api.metric = stream_getl (s); | |
125 | else | |
126 | api.metric = 0; | |
127 | ||
128 | if (command == ZEBRA_IPV6_ROUTE_ADD) | |
129 | babel_ipv6_route_add(&api, &prefix, ifindex, &nexthop); | |
130 | else | |
131 | babel_ipv6_route_delete(&api, &prefix, ifindex); | |
132 | ||
133 | return 0; | |
134 | } | |
135 | ||
136 | static int | |
137 | babel_zebra_read_ipv4 (int command, struct zclient *zclient, | |
138 | zebra_size_t length) | |
139 | { | |
140 | struct stream *s; | |
141 | struct zapi_ipv4 api; | |
142 | unsigned long ifindex = -1; | |
143 | struct in_addr nexthop; | |
144 | struct prefix_ipv4 prefix; | |
145 | ||
146 | s = zclient->ibuf; | |
147 | ifindex = 0; | |
148 | memset (&nexthop, 0, sizeof (struct in_addr)); | |
149 | memset (&api, 0, sizeof(struct zapi_ipv4)); | |
150 | memset (&prefix, 0, sizeof (struct prefix_ipv4)); | |
151 | ||
152 | /* Type, flags, message. */ | |
153 | api.type = stream_getc (s); | |
154 | api.flags = stream_getc (s); | |
155 | api.message = stream_getc (s); | |
156 | ||
157 | /* IPv6 prefix. */ | |
158 | prefix.family = AF_INET; | |
159 | prefix.prefixlen = stream_getc (s); | |
160 | stream_get (&prefix.prefix, s, PSIZE (prefix.prefixlen)); | |
161 | ||
162 | /* Nexthop, ifindex, distance, metric. */ | |
163 | if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) { | |
164 | api.nexthop_num = stream_getc (s); | |
165 | stream_get (&nexthop, s, sizeof(nexthop)); | |
166 | } | |
167 | if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) { | |
168 | api.ifindex_num = stream_getc (s); | |
169 | ifindex = stream_getl (s); | |
170 | } | |
171 | if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) | |
172 | api.distance = stream_getc (s); | |
173 | else | |
174 | api.distance = 0; | |
175 | if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) | |
176 | api.metric = stream_getl (s); | |
177 | else | |
178 | api.metric = 0; | |
179 | ||
180 | if (command == ZEBRA_IPV6_ROUTE_ADD) { | |
181 | babel_ipv4_route_add(&api, &prefix, ifindex, &nexthop); | |
182 | } else { | |
183 | babel_ipv4_route_delete(&api, &prefix, ifindex); | |
184 | } | |
185 | ||
186 | return 0; | |
187 | } | |
188 | ||
5734509c PJ |
189 | /* [Babel Command] */ |
190 | DEFUN (babel_redistribute_type, | |
191 | babel_redistribute_type_cmd, | |
05c943ac MB |
192 | "redistribute " QUAGGA_REDIST_STR_BABELD, |
193 | "Redistribute\n" | |
194 | QUAGGA_REDIST_HELP_STR_BABELD) | |
5734509c | 195 | { |
05c943ac | 196 | int type; |
5734509c | 197 | |
05c943ac | 198 | type = proto_redistnum(AFI_IP6, argv[0]); |
5734509c | 199 | |
05c943ac MB |
200 | if (type < 0) |
201 | type = proto_redistnum(AFI_IP, argv[0]); | |
5734509c | 202 | |
05c943ac MB |
203 | if (type < 0) { |
204 | vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE); | |
205 | return CMD_WARNING; | |
206 | } | |
207 | ||
208 | zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, type); | |
209 | return CMD_SUCCESS; | |
5734509c PJ |
210 | } |
211 | ||
212 | /* [Babel Command] */ | |
213 | DEFUN (no_babel_redistribute_type, | |
214 | no_babel_redistribute_type_cmd, | |
05c943ac | 215 | "no redistribute " QUAGGA_REDIST_STR_BABELD, |
5734509c | 216 | NO_STR |
05c943ac MB |
217 | "Redistribute\n" |
218 | QUAGGA_REDIST_HELP_STR_BABELD) | |
5734509c | 219 | { |
05c943ac | 220 | int type; |
5734509c | 221 | |
05c943ac | 222 | type = proto_redistnum(AFI_IP6, argv[0]); |
5734509c | 223 | |
05c943ac MB |
224 | if (type < 0) |
225 | type = proto_redistnum(AFI_IP, argv[0]); | |
5734509c | 226 | |
05c943ac MB |
227 | if (type < 0) { |
228 | vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE); | |
229 | return CMD_WARNING; | |
230 | } | |
231 | ||
359be3d0 DO |
232 | zclient_redistribute (ZEBRA_REDISTRIBUTE_DELETE, zclient, type); |
233 | /* perhaps should we remove xroutes having the same type... */ | |
234 | return CMD_SUCCESS; | |
5734509c PJ |
235 | } |
236 | ||
f1305cbf MB |
237 | #ifndef NO_DEBUG |
238 | /* [Babel Command] */ | |
a14ef5ee DO |
239 | DEFUN (debug_babel, |
240 | debug_babel_cmd, | |
241 | "debug babel (common|kernel|filter|timeout|interface|route|all)", | |
f1305cbf | 242 | "Enable debug messages for specific or all part.\n" |
a14ef5ee | 243 | "Babel information\n" |
f1305cbf MB |
244 | "Common messages (default)\n" |
245 | "Kernel messages\n" | |
246 | "Filter messages\n" | |
247 | "Timeout messages\n" | |
248 | "Interface messages\n" | |
249 | "Route messages\n" | |
250 | "All messages\n") | |
251 | { | |
252 | int i; | |
253 | ||
254 | for(i = 0; debug_type[i].str != NULL; i++) { | |
255 | if (strncmp (debug_type[i].str, argv[0], | |
256 | debug_type[i].str_min_len) == 0) { | |
257 | debug |= debug_type[i].type; | |
258 | return CMD_SUCCESS; | |
259 | } | |
260 | } | |
261 | ||
262 | vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE); | |
263 | ||
264 | return CMD_WARNING; | |
265 | } | |
266 | ||
267 | /* [Babel Command] */ | |
a14ef5ee DO |
268 | DEFUN (no_debug_babel, |
269 | no_debug_babel_cmd, | |
270 | "no debug babel (common|kernel|filter|timeout|interface|route|all)", | |
f1305cbf MB |
271 | NO_STR |
272 | "Disable debug messages for specific or all part.\n" | |
a14ef5ee | 273 | "Babel information\n" |
f1305cbf MB |
274 | "Common messages (default)\n" |
275 | "Kernel messages\n" | |
276 | "Filter messages\n" | |
277 | "Timeout messages\n" | |
278 | "Interface messages\n" | |
279 | "Route messages\n" | |
280 | "All messages\n") | |
281 | { | |
282 | int i; | |
283 | ||
284 | for (i = 0; debug_type[i].str; i++) { | |
285 | if (strncmp(debug_type[i].str, argv[0], | |
286 | debug_type[i].str_min_len) == 0) { | |
287 | debug &= ~debug_type[i].type; | |
a0edef1b | 288 | return CMD_SUCCESS; |
f1305cbf MB |
289 | } |
290 | } | |
291 | ||
292 | vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE); | |
293 | ||
294 | return CMD_WARNING; | |
295 | } | |
296 | #endif /* NO_DEBUG */ | |
297 | ||
a14ef5ee DO |
298 | /* Output "debug" statement lines, if necessary. */ |
299 | int | |
300 | debug_babel_config_write (struct vty * vty) | |
301 | { | |
302 | #ifdef NO_DEBUG | |
303 | return 0; | |
304 | #else | |
305 | int i, lines = 0; | |
306 | ||
307 | if (debug == BABEL_DEBUG_ALL) | |
308 | { | |
309 | vty_out (vty, "debug babel all%s", VTY_NEWLINE); | |
310 | lines++; | |
311 | } | |
312 | else | |
313 | for (i = 0; debug_type[i].str != NULL; i++) | |
314 | if | |
315 | ( | |
316 | debug_type[i].type != BABEL_DEBUG_ALL | |
317 | && CHECK_FLAG (debug, debug_type[i].type) | |
318 | ) | |
319 | { | |
320 | vty_out (vty, "debug babel %s%s", debug_type[i].str, VTY_NEWLINE); | |
321 | lines++; | |
322 | } | |
323 | if (lines) | |
324 | { | |
325 | vty_out (vty, "!%s", VTY_NEWLINE); | |
326 | lines++; | |
327 | } | |
328 | return lines; | |
329 | #endif /* NO_DEBUG */ | |
330 | } | |
5734509c PJ |
331 | |
332 | void babelz_zebra_init(void) | |
333 | { | |
334 | zclient = zclient_new(); | |
335 | zclient_init(zclient, ZEBRA_ROUTE_BABEL); | |
336 | ||
337 | zclient->interface_add = babel_interface_add; | |
338 | zclient->interface_delete = babel_interface_delete; | |
339 | zclient->interface_up = babel_interface_up; | |
340 | zclient->interface_down = babel_interface_down; | |
341 | zclient->interface_address_add = babel_interface_address_add; | |
342 | zclient->interface_address_delete = babel_interface_address_delete; | |
343 | zclient->ipv4_route_add = babel_zebra_read_ipv4; | |
344 | zclient->ipv4_route_delete = babel_zebra_read_ipv4; | |
345 | zclient->ipv6_route_add = babel_zebra_read_ipv6; | |
346 | zclient->ipv6_route_delete = babel_zebra_read_ipv6; | |
347 | ||
348 | install_node (&zebra_node, zebra_config_write); | |
349 | install_element(BABEL_NODE, &babel_redistribute_type_cmd); | |
350 | install_element(BABEL_NODE, &no_babel_redistribute_type_cmd); | |
a14ef5ee DO |
351 | install_element(ENABLE_NODE, &debug_babel_cmd); |
352 | install_element(ENABLE_NODE, &no_debug_babel_cmd); | |
353 | install_element(CONFIG_NODE, &debug_babel_cmd); | |
354 | install_element(CONFIG_NODE, &no_debug_babel_cmd); | |
5734509c PJ |
355 | } |
356 | ||
357 | static int | |
358 | zebra_config_write (struct vty *vty) | |
359 | { | |
5734509c PJ |
360 | if (! zclient->enable) |
361 | { | |
362 | vty_out (vty, "no router zebra%s", VTY_NEWLINE); | |
363 | return 1; | |
364 | } | |
365 | else if (! zclient->redist[ZEBRA_ROUTE_BABEL]) | |
366 | { | |
367 | vty_out (vty, "router zebra%s", VTY_NEWLINE); | |
368 | vty_out (vty, " no redistribute babel%s", VTY_NEWLINE); | |
369 | return 1; | |
370 | } | |
371 | return 0; | |
372 | } | |
373 | ||
374 | void | |
375 | babel_zebra_close_connexion(void) | |
376 | { | |
377 | zclient_stop(zclient); | |
378 | } |