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