]>
Commit | Line | Data |
---|---|---|
18a6dce6 | 1 | /* |
2 | * Router ID for zebra daemon. | |
3 | * | |
d62a17ae | 4 | * Copyright (C) 2004 James R. Leu |
18a6dce6 | 5 | * |
6 | * This file is part of Quagga routing suite. | |
7 | * | |
8 | * Quagga is free software; you can redistribute it and/or modify it | |
9 | * under the terms of the GNU General Public License as published by the | |
10 | * Free Software Foundation; either version 2, or (at your option) any | |
11 | * later version. | |
12 | * | |
13 | * Quagga is distributed in the hope that it will be useful, but | |
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | * General Public License for more details. | |
17 | * | |
896014f4 DL |
18 | * You should have received a copy of the GNU General Public License along |
19 | * with this program; see the file COPYING; if not, write to the Free Software | |
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
18a6dce6 | 21 | */ |
22 | ||
23 | #include <zebra.h> | |
24 | ||
25 | #include "if.h" | |
26 | #include "vty.h" | |
27 | #include "sockunion.h" | |
28 | #include "prefix.h" | |
29 | #include "stream.h" | |
30 | #include "command.h" | |
31 | #include "memory.h" | |
4a1ab8e4 | 32 | #include "zebra_memory.h" |
18a6dce6 | 33 | #include "ioctl.h" |
34 | #include "connected.h" | |
35 | #include "network.h" | |
36 | #include "log.h" | |
37 | #include "table.h" | |
38 | #include "rib.h" | |
c6ffe645 | 39 | #include "vrf.h" |
18a6dce6 | 40 | |
161e9ab7 | 41 | #include "zebra/zebra_router.h" |
bf094f69 | 42 | #include "zebra/zapi_msg.h" |
7c551956 | 43 | #include "zebra/zebra_vrf.h" |
a1ac18c4 | 44 | #include "zebra/router-id.h" |
6dc686a2 | 45 | #include "zebra/redistribute.h" |
18a6dce6 | 46 | |
d62a17ae | 47 | static struct connected *router_id_find_node(struct list *l, |
48 | struct connected *ifc) | |
18a6dce6 | 49 | { |
d62a17ae | 50 | struct listnode *node; |
51 | struct connected *c; | |
18a6dce6 | 52 | |
d62a17ae | 53 | for (ALL_LIST_ELEMENTS_RO(l, node, c)) |
54 | if (prefix_same(ifc->address, c->address)) | |
55 | return c; | |
1eb8ef25 | 56 | |
d62a17ae | 57 | return NULL; |
18a6dce6 | 58 | } |
59 | ||
d62a17ae | 60 | static int router_id_bad_address(struct connected *ifc) |
18a6dce6 | 61 | { |
d62a17ae | 62 | if (ifc->address->family != AF_INET) |
63 | return 1; | |
64 | ||
65 | /* non-redistributable addresses shouldn't be used for RIDs either */ | |
66 | if (!zebra_check_addr(ifc->address)) | |
67 | return 1; | |
68 | ||
69 | return 0; | |
18a6dce6 | 70 | } |
71 | ||
03fba42e | 72 | void router_id_get(struct prefix *p, struct zebra_vrf *zvrf) |
18a6dce6 | 73 | { |
d62a17ae | 74 | struct listnode *node; |
75 | struct connected *c; | |
d62a17ae | 76 | |
975a328e | 77 | p->u.prefix4.s_addr = INADDR_ANY; |
d62a17ae | 78 | p->family = AF_INET; |
79 | p->prefixlen = 32; | |
80 | ||
975a328e | 81 | if (zvrf->rid_user_assigned.u.prefix4.s_addr != INADDR_ANY) |
d62a17ae | 82 | p->u.prefix4.s_addr = zvrf->rid_user_assigned.u.prefix4.s_addr; |
83 | else if (!list_isempty(zvrf->rid_lo_sorted_list)) { | |
84 | node = listtail(zvrf->rid_lo_sorted_list); | |
85 | c = listgetdata(node); | |
86 | p->u.prefix4.s_addr = c->address->u.prefix4.s_addr; | |
87 | } else if (!list_isempty(zvrf->rid_all_sorted_list)) { | |
88 | node = listtail(zvrf->rid_all_sorted_list); | |
89 | c = listgetdata(node); | |
90 | p->u.prefix4.s_addr = c->address->u.prefix4.s_addr; | |
91 | } | |
18a6dce6 | 92 | } |
93 | ||
03fba42e | 94 | static void router_id_set(struct prefix *p, struct zebra_vrf *zvrf) |
18a6dce6 | 95 | { |
d62a17ae | 96 | struct prefix p2; |
97 | struct listnode *node; | |
98 | struct zserv *client; | |
d62a17ae | 99 | |
100 | zvrf->rid_user_assigned.u.prefix4.s_addr = p->u.prefix4.s_addr; | |
101 | ||
03fba42e | 102 | router_id_get(&p2, zvrf); |
d62a17ae | 103 | |
161e9ab7 | 104 | for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) |
03fba42e | 105 | zsend_router_id_update(client, &p2, zvrf->vrf->vrf_id); |
18a6dce6 | 106 | } |
107 | ||
d62a17ae | 108 | void router_id_add_address(struct connected *ifc) |
18a6dce6 | 109 | { |
d62a17ae | 110 | struct list *l = NULL; |
111 | struct listnode *node; | |
112 | struct prefix before; | |
113 | struct prefix after; | |
114 | struct zserv *client; | |
a36898e7 | 115 | struct zebra_vrf *zvrf = vrf_info_get(ifc->ifp->vrf_id); |
d62a17ae | 116 | |
117 | if (router_id_bad_address(ifc)) | |
118 | return; | |
119 | ||
03fba42e | 120 | router_id_get(&before, zvrf); |
d62a17ae | 121 | |
106935f6 | 122 | if (if_is_loopback(ifc->ifp)) |
d62a17ae | 123 | l = zvrf->rid_lo_sorted_list; |
124 | else | |
125 | l = zvrf->rid_all_sorted_list; | |
126 | ||
127 | if (!router_id_find_node(l, ifc)) | |
128 | listnode_add_sort(l, ifc); | |
129 | ||
03fba42e | 130 | router_id_get(&after, zvrf); |
d62a17ae | 131 | |
132 | if (prefix_same(&before, &after)) | |
133 | return; | |
134 | ||
161e9ab7 | 135 | for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) |
d62a17ae | 136 | zsend_router_id_update(client, &after, zvrf_id(zvrf)); |
18a6dce6 | 137 | } |
138 | ||
d62a17ae | 139 | void router_id_del_address(struct connected *ifc) |
18a6dce6 | 140 | { |
d62a17ae | 141 | struct connected *c; |
142 | struct list *l; | |
143 | struct prefix after; | |
144 | struct prefix before; | |
145 | struct listnode *node; | |
146 | struct zserv *client; | |
a36898e7 | 147 | struct zebra_vrf *zvrf = vrf_info_get(ifc->ifp->vrf_id); |
18a6dce6 | 148 | |
d62a17ae | 149 | if (router_id_bad_address(ifc)) |
150 | return; | |
18a6dce6 | 151 | |
03fba42e | 152 | router_id_get(&before, zvrf); |
18a6dce6 | 153 | |
106935f6 | 154 | if (if_is_loopback(ifc->ifp)) |
d62a17ae | 155 | l = zvrf->rid_lo_sorted_list; |
156 | else | |
157 | l = zvrf->rid_all_sorted_list; | |
18a6dce6 | 158 | |
d62a17ae | 159 | if ((c = router_id_find_node(l, ifc))) |
160 | listnode_delete(l, c); | |
18a6dce6 | 161 | |
03fba42e | 162 | router_id_get(&after, zvrf); |
18a6dce6 | 163 | |
d62a17ae | 164 | if (prefix_same(&before, &after)) |
165 | return; | |
18a6dce6 | 166 | |
161e9ab7 | 167 | for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) |
d62a17ae | 168 | zsend_router_id_update(client, &after, zvrf_id(zvrf)); |
18a6dce6 | 169 | } |
170 | ||
03fba42e | 171 | void router_id_write(struct vty *vty, struct zebra_vrf *zvrf) |
18a6dce6 | 172 | { |
03fba42e DS |
173 | char space[2]; |
174 | ||
175 | memset(space, 0, sizeof(space)); | |
176 | ||
177 | if (zvrf_id(zvrf) != VRF_DEFAULT) | |
178 | snprintf(space, sizeof(space), "%s", " "); | |
d62a17ae | 179 | |
03fba42e DS |
180 | if (zvrf->rid_user_assigned.u.prefix4.s_addr != INADDR_ANY) { |
181 | vty_out(vty, "%srouter-id %s\n", space, | |
182 | inet_ntoa(zvrf->rid_user_assigned.u.prefix4)); | |
183 | } | |
18a6dce6 | 184 | } |
185 | ||
186 | DEFUN (router_id, | |
187 | router_id_cmd, | |
03fba42e | 188 | "router-id A.B.C.D vrf NAME", |
18a6dce6 | 189 | "Manually set the router-id\n" |
03fba42e | 190 | "IP address to use for router-id\n" VRF_CMD_HELP_STR) |
18a6dce6 | 191 | { |
d62a17ae | 192 | int idx_ipv4 = 1; |
193 | int idx_name = 3; | |
03fba42e | 194 | struct zebra_vrf *zvrf; |
92300491 | 195 | |
d62a17ae | 196 | struct prefix rid; |
197 | vrf_id_t vrf_id = VRF_DEFAULT; | |
18a6dce6 | 198 | |
d62a17ae | 199 | rid.u.prefix4.s_addr = inet_addr(argv[idx_ipv4]->arg); |
200 | if (!rid.u.prefix4.s_addr) | |
201 | return CMD_WARNING_CONFIG_FAILED; | |
18a6dce6 | 202 | |
d62a17ae | 203 | rid.prefixlen = 32; |
204 | rid.family = AF_INET; | |
18a6dce6 | 205 | |
d62a17ae | 206 | if (argc > 2) |
ec1db588 | 207 | VRF_GET_ID(vrf_id, argv[idx_name]->arg, false); |
c6ffe645 | 208 | |
03fba42e DS |
209 | zvrf = vrf_info_lookup(vrf_id); |
210 | router_id_set(&rid, zvrf); | |
211 | ||
212 | return CMD_SUCCESS; | |
213 | } | |
214 | ||
215 | DEFUN (router_id_in_vrf, | |
216 | router_id_in_vrf_cmd, | |
217 | "router-id A.B.C.D", | |
218 | "Manuall set the router-id\n" | |
219 | "IP address to use for router-id\n") | |
220 | { | |
221 | ZEBRA_DECLVAR_CONTEXT(vrf, zvrf); | |
222 | int idx_ipv4 = 1; | |
223 | struct prefix rid; | |
224 | ||
225 | rid.u.prefix4.s_addr = inet_addr(argv[idx_ipv4]->arg); | |
226 | if (!rid.u.prefix4.s_addr) | |
227 | return CMD_WARNING_CONFIG_FAILED; | |
228 | ||
229 | rid.prefixlen = 32; | |
230 | rid.family = AF_INET; | |
231 | ||
232 | router_id_set(&rid, zvrf); | |
18a6dce6 | 233 | |
d62a17ae | 234 | return CMD_SUCCESS; |
18a6dce6 | 235 | } |
236 | ||
237 | DEFUN (no_router_id, | |
238 | no_router_id_cmd, | |
03fba42e | 239 | "no router-id [A.B.C.D vrf NAME]", |
18a6dce6 | 240 | NO_STR |
92300491 | 241 | "Remove the manually configured router-id\n" |
03fba42e | 242 | "IP address to use for router-id\n" VRF_CMD_HELP_STR) |
18a6dce6 | 243 | { |
d62a17ae | 244 | int idx_name = 4; |
d62a17ae | 245 | struct prefix rid; |
246 | vrf_id_t vrf_id = VRF_DEFAULT; | |
03fba42e | 247 | struct zebra_vrf *zvrf; |
18a6dce6 | 248 | |
d62a17ae | 249 | rid.u.prefix4.s_addr = 0; |
250 | rid.prefixlen = 0; | |
251 | rid.family = AF_INET; | |
18a6dce6 | 252 | |
d62a17ae | 253 | if (argc > 3) |
ec1db588 | 254 | VRF_GET_ID(vrf_id, argv[idx_name]->arg, false); |
c6ffe645 | 255 | |
03fba42e DS |
256 | zvrf = vrf_info_get(vrf_id); |
257 | router_id_set(&rid, zvrf); | |
258 | ||
259 | return CMD_SUCCESS; | |
260 | } | |
261 | ||
262 | DEFUN (no_router_id_in_vrf, | |
263 | no_router_id_in_vrf_cmd, | |
264 | "no router-id [A.B.C.D]", | |
265 | NO_STR | |
266 | "Remove the manually configured router-id\n" | |
267 | "IP address to use for router-id\n") | |
268 | { | |
269 | ZEBRA_DECLVAR_CONTEXT(vrf, zvrf); | |
270 | ||
271 | struct prefix rid; | |
272 | ||
273 | rid.u.prefix4.s_addr = 0; | |
274 | rid.prefixlen = 0; | |
275 | rid.family = AF_INET; | |
276 | ||
277 | router_id_set(&rid, zvrf); | |
18a6dce6 | 278 | |
d62a17ae | 279 | return CMD_SUCCESS; |
18a6dce6 | 280 | } |
281 | ||
13b01f2f JAG |
282 | DEFUN (show_router_id, |
283 | show_router_id_cmd, | |
284 | "show router-id [vrf NAME]", | |
285 | SHOW_STR | |
286 | "Show the configured router-id\n" | |
287 | VRF_CMD_HELP_STR) | |
288 | { | |
289 | int idx_name = 3; | |
290 | ||
291 | vrf_id_t vrf_id = VRF_DEFAULT; | |
292 | struct zebra_vrf *zvrf; | |
293 | ||
294 | if (argc > 2) | |
295 | VRF_GET_ID(vrf_id, argv[idx_name]->arg, false); | |
296 | ||
297 | zvrf = vrf_info_get(vrf_id); | |
298 | ||
299 | if ((zvrf != NULL) && (zvrf->rid_user_assigned.u.prefix4.s_addr)) { | |
300 | vty_out(vty, "zebra:\n"); | |
301 | if (vrf_id == VRF_DEFAULT) | |
302 | vty_out(vty, " router-id %s vrf default\n", | |
303 | inet_ntoa(zvrf->rid_user_assigned.u.prefix4)); | |
304 | else | |
305 | vty_out(vty, " router-id %s vrf %s\n", | |
306 | inet_ntoa(zvrf->rid_user_assigned.u.prefix4), | |
307 | argv[idx_name]->arg); | |
308 | } | |
309 | ||
310 | return CMD_SUCCESS; | |
311 | } | |
813d4307 | 312 | |
d62a17ae | 313 | static int router_id_cmp(void *a, void *b) |
18a6dce6 | 314 | { |
d62a17ae | 315 | const struct connected *ifa = (const struct connected *)a; |
316 | const struct connected *ifb = (const struct connected *)b; | |
18a6dce6 | 317 | |
d62a17ae | 318 | return IPV4_ADDR_CMP(&ifa->address->u.prefix4.s_addr, |
319 | &ifb->address->u.prefix4.s_addr); | |
18a6dce6 | 320 | } |
321 | ||
d62a17ae | 322 | void router_id_cmd_init(void) |
18a6dce6 | 323 | { |
d62a17ae | 324 | install_element(CONFIG_NODE, &router_id_cmd); |
325 | install_element(CONFIG_NODE, &no_router_id_cmd); | |
03fba42e DS |
326 | install_element(CONFIG_NODE, &router_id_in_vrf_cmd); |
327 | install_element(VRF_NODE, &router_id_in_vrf_cmd); | |
328 | install_element(CONFIG_NODE, &no_router_id_in_vrf_cmd); | |
329 | install_element(VRF_NODE, &no_router_id_in_vrf_cmd); | |
13b01f2f | 330 | install_element(VIEW_NODE, &show_router_id_cmd); |
c6ffe645 FL |
331 | } |
332 | ||
d62a17ae | 333 | void router_id_init(struct zebra_vrf *zvrf) |
c6ffe645 | 334 | { |
d62a17ae | 335 | zvrf->rid_all_sorted_list = &zvrf->_rid_all_sorted_list; |
336 | zvrf->rid_lo_sorted_list = &zvrf->_rid_lo_sorted_list; | |
18a6dce6 | 337 | |
d62a17ae | 338 | memset(zvrf->rid_all_sorted_list, 0, |
339 | sizeof(zvrf->_rid_all_sorted_list)); | |
340 | memset(zvrf->rid_lo_sorted_list, 0, sizeof(zvrf->_rid_lo_sorted_list)); | |
341 | memset(&zvrf->rid_user_assigned, 0, sizeof(zvrf->rid_user_assigned)); | |
18a6dce6 | 342 | |
d62a17ae | 343 | zvrf->rid_all_sorted_list->cmp = router_id_cmp; |
344 | zvrf->rid_lo_sorted_list->cmp = router_id_cmp; | |
18a6dce6 | 345 | |
d62a17ae | 346 | zvrf->rid_user_assigned.family = AF_INET; |
347 | zvrf->rid_user_assigned.prefixlen = 32; | |
18a6dce6 | 348 | } |