]>
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; | |
a41c4e1b | 125 | struct zebra_vrf *zvrf = vrf_info_get(vrf_to_id(ifc->ifp->vrf)); |
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; | |
a41c4e1b | 157 | struct zebra_vrf *zvrf = vrf_info_get(vrf_to_id(ifc->ifp->vrf)); |
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 | ||
813d4307 | 256 | |
d62a17ae | 257 | static int router_id_cmp(void *a, void *b) |
18a6dce6 | 258 | { |
d62a17ae | 259 | const struct connected *ifa = (const struct connected *)a; |
260 | const struct connected *ifb = (const struct connected *)b; | |
18a6dce6 | 261 | |
d62a17ae | 262 | return IPV4_ADDR_CMP(&ifa->address->u.prefix4.s_addr, |
263 | &ifb->address->u.prefix4.s_addr); | |
18a6dce6 | 264 | } |
265 | ||
d62a17ae | 266 | void router_id_cmd_init(void) |
18a6dce6 | 267 | { |
d62a17ae | 268 | install_element(CONFIG_NODE, &router_id_cmd); |
269 | install_element(CONFIG_NODE, &no_router_id_cmd); | |
c6ffe645 FL |
270 | } |
271 | ||
d62a17ae | 272 | void router_id_init(struct zebra_vrf *zvrf) |
c6ffe645 | 273 | { |
d62a17ae | 274 | zvrf->rid_all_sorted_list = &zvrf->_rid_all_sorted_list; |
275 | zvrf->rid_lo_sorted_list = &zvrf->_rid_lo_sorted_list; | |
18a6dce6 | 276 | |
d62a17ae | 277 | memset(zvrf->rid_all_sorted_list, 0, |
278 | sizeof(zvrf->_rid_all_sorted_list)); | |
279 | memset(zvrf->rid_lo_sorted_list, 0, sizeof(zvrf->_rid_lo_sorted_list)); | |
280 | memset(&zvrf->rid_user_assigned, 0, sizeof(zvrf->rid_user_assigned)); | |
18a6dce6 | 281 | |
d62a17ae | 282 | zvrf->rid_all_sorted_list->cmp = router_id_cmp; |
283 | zvrf->rid_lo_sorted_list->cmp = router_id_cmp; | |
18a6dce6 | 284 | |
d62a17ae | 285 | zvrf->rid_user_assigned.family = AF_INET; |
286 | zvrf->rid_user_assigned.prefixlen = 32; | |
18a6dce6 | 287 | } |