]>
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 | ||
d62a17ae | 72 | void router_id_get(struct prefix *p, vrf_id_t vrf_id) |
18a6dce6 | 73 | { |
d62a17ae | 74 | struct listnode *node; |
75 | struct connected *c; | |
76 | struct zebra_vrf *zvrf = vrf_info_get(vrf_id); | |
77 | ||
78 | p->u.prefix4.s_addr = 0; | |
79 | p->family = AF_INET; | |
80 | p->prefixlen = 32; | |
81 | ||
82 | if (zvrf->rid_user_assigned.u.prefix4.s_addr) | |
83 | p->u.prefix4.s_addr = zvrf->rid_user_assigned.u.prefix4.s_addr; | |
84 | else if (!list_isempty(zvrf->rid_lo_sorted_list)) { | |
85 | node = listtail(zvrf->rid_lo_sorted_list); | |
86 | c = listgetdata(node); | |
87 | p->u.prefix4.s_addr = c->address->u.prefix4.s_addr; | |
88 | } else if (!list_isempty(zvrf->rid_all_sorted_list)) { | |
89 | node = listtail(zvrf->rid_all_sorted_list); | |
90 | c = listgetdata(node); | |
91 | p->u.prefix4.s_addr = c->address->u.prefix4.s_addr; | |
92 | } | |
18a6dce6 | 93 | } |
94 | ||
d62a17ae | 95 | static void router_id_set(struct prefix *p, vrf_id_t vrf_id) |
18a6dce6 | 96 | { |
d62a17ae | 97 | struct prefix p2; |
98 | struct listnode *node; | |
99 | struct zserv *client; | |
100 | struct zebra_vrf *zvrf; | |
101 | ||
102 | if (p->u.prefix4.s_addr == 0) /* unset */ | |
103 | { | |
104 | zvrf = vrf_info_lookup(vrf_id); | |
105 | if (!zvrf) | |
106 | return; | |
107 | } else /* set */ | |
108 | zvrf = vrf_info_get(vrf_id); | |
109 | ||
110 | zvrf->rid_user_assigned.u.prefix4.s_addr = p->u.prefix4.s_addr; | |
111 | ||
112 | router_id_get(&p2, vrf_id); | |
113 | ||
161e9ab7 | 114 | for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) |
d62a17ae | 115 | zsend_router_id_update(client, &p2, vrf_id); |
18a6dce6 | 116 | } |
117 | ||
d62a17ae | 118 | void router_id_add_address(struct connected *ifc) |
18a6dce6 | 119 | { |
d62a17ae | 120 | struct list *l = NULL; |
121 | struct listnode *node; | |
122 | struct prefix before; | |
123 | struct prefix after; | |
124 | struct zserv *client; | |
a36898e7 | 125 | struct zebra_vrf *zvrf = vrf_info_get(ifc->ifp->vrf_id); |
d62a17ae | 126 | |
127 | if (router_id_bad_address(ifc)) | |
128 | return; | |
129 | ||
130 | router_id_get(&before, zvrf_id(zvrf)); | |
131 | ||
106935f6 | 132 | if (if_is_loopback(ifc->ifp)) |
d62a17ae | 133 | l = zvrf->rid_lo_sorted_list; |
134 | else | |
135 | l = zvrf->rid_all_sorted_list; | |
136 | ||
137 | if (!router_id_find_node(l, ifc)) | |
138 | listnode_add_sort(l, ifc); | |
139 | ||
140 | router_id_get(&after, zvrf_id(zvrf)); | |
141 | ||
142 | if (prefix_same(&before, &after)) | |
143 | return; | |
144 | ||
161e9ab7 | 145 | for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) |
d62a17ae | 146 | zsend_router_id_update(client, &after, zvrf_id(zvrf)); |
18a6dce6 | 147 | } |
148 | ||
d62a17ae | 149 | void router_id_del_address(struct connected *ifc) |
18a6dce6 | 150 | { |
d62a17ae | 151 | struct connected *c; |
152 | struct list *l; | |
153 | struct prefix after; | |
154 | struct prefix before; | |
155 | struct listnode *node; | |
156 | struct zserv *client; | |
a36898e7 | 157 | struct zebra_vrf *zvrf = vrf_info_get(ifc->ifp->vrf_id); |
18a6dce6 | 158 | |
d62a17ae | 159 | if (router_id_bad_address(ifc)) |
160 | return; | |
18a6dce6 | 161 | |
d62a17ae | 162 | router_id_get(&before, zvrf_id(zvrf)); |
18a6dce6 | 163 | |
106935f6 | 164 | if (if_is_loopback(ifc->ifp)) |
d62a17ae | 165 | l = zvrf->rid_lo_sorted_list; |
166 | else | |
167 | l = zvrf->rid_all_sorted_list; | |
18a6dce6 | 168 | |
d62a17ae | 169 | if ((c = router_id_find_node(l, ifc))) |
170 | listnode_delete(l, c); | |
18a6dce6 | 171 | |
d62a17ae | 172 | router_id_get(&after, zvrf_id(zvrf)); |
18a6dce6 | 173 | |
d62a17ae | 174 | if (prefix_same(&before, &after)) |
175 | return; | |
18a6dce6 | 176 | |
161e9ab7 | 177 | for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) |
d62a17ae | 178 | zsend_router_id_update(client, &after, zvrf_id(zvrf)); |
18a6dce6 | 179 | } |
180 | ||
d62a17ae | 181 | void router_id_write(struct vty *vty) |
18a6dce6 | 182 | { |
d62a17ae | 183 | struct vrf *vrf; |
184 | struct zebra_vrf *zvrf; | |
185 | ||
a2addae8 RW |
186 | RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) |
187 | if ((zvrf = vrf->info) != NULL) | |
188 | if (zvrf->rid_user_assigned.u.prefix4.s_addr) { | |
189 | if (zvrf_id(zvrf) == VRF_DEFAULT) | |
190 | vty_out(vty, "router-id %s\n", | |
191 | inet_ntoa( | |
192 | zvrf->rid_user_assigned | |
193 | .u.prefix4)); | |
194 | else | |
195 | vty_out(vty, "router-id %s vrf %s\n", | |
196 | inet_ntoa( | |
197 | zvrf->rid_user_assigned | |
198 | .u.prefix4), | |
199 | zvrf_name(zvrf)); | |
200 | } | |
18a6dce6 | 201 | } |
202 | ||
203 | DEFUN (router_id, | |
204 | router_id_cmd, | |
92300491 | 205 | "router-id A.B.C.D [vrf NAME]", |
18a6dce6 | 206 | "Manually set the router-id\n" |
92300491 DW |
207 | "IP address to use for router-id\n" |
208 | VRF_CMD_HELP_STR) | |
18a6dce6 | 209 | { |
d62a17ae | 210 | int idx_ipv4 = 1; |
211 | int idx_name = 3; | |
92300491 | 212 | |
d62a17ae | 213 | struct prefix rid; |
214 | vrf_id_t vrf_id = VRF_DEFAULT; | |
18a6dce6 | 215 | |
d62a17ae | 216 | rid.u.prefix4.s_addr = inet_addr(argv[idx_ipv4]->arg); |
217 | if (!rid.u.prefix4.s_addr) | |
218 | return CMD_WARNING_CONFIG_FAILED; | |
18a6dce6 | 219 | |
d62a17ae | 220 | rid.prefixlen = 32; |
221 | rid.family = AF_INET; | |
18a6dce6 | 222 | |
d62a17ae | 223 | if (argc > 2) |
ec1db588 | 224 | VRF_GET_ID(vrf_id, argv[idx_name]->arg, false); |
c6ffe645 | 225 | |
d62a17ae | 226 | router_id_set(&rid, vrf_id); |
18a6dce6 | 227 | |
d62a17ae | 228 | return CMD_SUCCESS; |
18a6dce6 | 229 | } |
230 | ||
231 | DEFUN (no_router_id, | |
232 | no_router_id_cmd, | |
92300491 | 233 | "no router-id [A.B.C.D [vrf NAME]]", |
18a6dce6 | 234 | NO_STR |
92300491 DW |
235 | "Remove the manually configured router-id\n" |
236 | "IP address to use for router-id\n" | |
237 | VRF_CMD_HELP_STR) | |
18a6dce6 | 238 | { |
d62a17ae | 239 | int idx_name = 4; |
92300491 | 240 | |
d62a17ae | 241 | struct prefix rid; |
242 | vrf_id_t vrf_id = VRF_DEFAULT; | |
18a6dce6 | 243 | |
d62a17ae | 244 | rid.u.prefix4.s_addr = 0; |
245 | rid.prefixlen = 0; | |
246 | rid.family = AF_INET; | |
18a6dce6 | 247 | |
d62a17ae | 248 | if (argc > 3) |
ec1db588 | 249 | VRF_GET_ID(vrf_id, argv[idx_name]->arg, false); |
c6ffe645 | 250 | |
d62a17ae | 251 | router_id_set(&rid, vrf_id); |
18a6dce6 | 252 | |
d62a17ae | 253 | return CMD_SUCCESS; |
18a6dce6 | 254 | } |
255 | ||
13b01f2f JAG |
256 | DEFUN (show_router_id, |
257 | show_router_id_cmd, | |
258 | "show router-id [vrf NAME]", | |
259 | SHOW_STR | |
260 | "Show the configured router-id\n" | |
261 | VRF_CMD_HELP_STR) | |
262 | { | |
263 | int idx_name = 3; | |
264 | ||
265 | vrf_id_t vrf_id = VRF_DEFAULT; | |
266 | struct zebra_vrf *zvrf; | |
267 | ||
268 | if (argc > 2) | |
269 | VRF_GET_ID(vrf_id, argv[idx_name]->arg, false); | |
270 | ||
271 | zvrf = vrf_info_get(vrf_id); | |
272 | ||
273 | if ((zvrf != NULL) && (zvrf->rid_user_assigned.u.prefix4.s_addr)) { | |
274 | vty_out(vty, "zebra:\n"); | |
275 | if (vrf_id == VRF_DEFAULT) | |
276 | vty_out(vty, " router-id %s vrf default\n", | |
277 | inet_ntoa(zvrf->rid_user_assigned.u.prefix4)); | |
278 | else | |
279 | vty_out(vty, " router-id %s vrf %s\n", | |
280 | inet_ntoa(zvrf->rid_user_assigned.u.prefix4), | |
281 | argv[idx_name]->arg); | |
282 | } | |
283 | ||
284 | return CMD_SUCCESS; | |
285 | } | |
813d4307 | 286 | |
d62a17ae | 287 | static int router_id_cmp(void *a, void *b) |
18a6dce6 | 288 | { |
d62a17ae | 289 | const struct connected *ifa = (const struct connected *)a; |
290 | const struct connected *ifb = (const struct connected *)b; | |
18a6dce6 | 291 | |
d62a17ae | 292 | return IPV4_ADDR_CMP(&ifa->address->u.prefix4.s_addr, |
293 | &ifb->address->u.prefix4.s_addr); | |
18a6dce6 | 294 | } |
295 | ||
d62a17ae | 296 | void router_id_cmd_init(void) |
18a6dce6 | 297 | { |
d62a17ae | 298 | install_element(CONFIG_NODE, &router_id_cmd); |
299 | install_element(CONFIG_NODE, &no_router_id_cmd); | |
13b01f2f | 300 | install_element(VIEW_NODE, &show_router_id_cmd); |
c6ffe645 FL |
301 | } |
302 | ||
d62a17ae | 303 | void router_id_init(struct zebra_vrf *zvrf) |
c6ffe645 | 304 | { |
d62a17ae | 305 | zvrf->rid_all_sorted_list = &zvrf->_rid_all_sorted_list; |
306 | zvrf->rid_lo_sorted_list = &zvrf->_rid_lo_sorted_list; | |
18a6dce6 | 307 | |
d62a17ae | 308 | memset(zvrf->rid_all_sorted_list, 0, |
309 | sizeof(zvrf->_rid_all_sorted_list)); | |
310 | memset(zvrf->rid_lo_sorted_list, 0, sizeof(zvrf->_rid_lo_sorted_list)); | |
311 | memset(&zvrf->rid_user_assigned, 0, sizeof(zvrf->rid_user_assigned)); | |
18a6dce6 | 312 | |
d62a17ae | 313 | zvrf->rid_all_sorted_list->cmp = router_id_cmp; |
314 | zvrf->rid_lo_sorted_list->cmp = router_id_cmp; | |
18a6dce6 | 315 | |
d62a17ae | 316 | zvrf->rid_user_assigned.family = AF_INET; |
317 | zvrf->rid_user_assigned.prefixlen = 32; | |
18a6dce6 | 318 | } |