]>
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" | |
49 | ||
50 | void babelz_zebra_init(void); | |
51 | ||
52 | ||
53 | /* we must use a pointer because of zclient.c's functions (new, free). */ | |
54 | struct zclient *zclient; | |
55 | static int zebra_config_write (struct vty *vty); | |
56 | /* Redistribution types */ | |
57 | static 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. */ | |
71 | struct 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). */ | |
80 | static int | |
81 | babel_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 | ||
132 | static int | |
133 | babel_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 | ||
185 | static int | |
186 | babel_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] */ | |
203 | DEFUN (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] */ | |
230 | DEFUN (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 | ||
256 | void 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 | ||
277 | static int | |
278 | zebra_config_write (struct vty *vty) | |
279 | { | |
5734509c PJ |
280 | 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 | ||
294 | void | |
295 | babel_zebra_close_connexion(void) | |
296 | { | |
297 | zclient_stop(zclient); | |
298 | } |