]>
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 | |
41 | #include "zebra/zserv.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 | |
1f9a9fff PJ |
47 | /* master zebra server structure */ |
48 | extern struct zebra_t zebrad; | |
49 | ||
d62a17ae | 50 | static struct connected *router_id_find_node(struct list *l, |
51 | struct connected *ifc) | |
18a6dce6 | 52 | { |
d62a17ae | 53 | struct listnode *node; |
54 | struct connected *c; | |
18a6dce6 | 55 | |
d62a17ae | 56 | for (ALL_LIST_ELEMENTS_RO(l, node, c)) |
57 | if (prefix_same(ifc->address, c->address)) | |
58 | return c; | |
1eb8ef25 | 59 | |
d62a17ae | 60 | return NULL; |
18a6dce6 | 61 | } |
62 | ||
d62a17ae | 63 | static int router_id_bad_address(struct connected *ifc) |
18a6dce6 | 64 | { |
d62a17ae | 65 | if (ifc->address->family != AF_INET) |
66 | return 1; | |
67 | ||
68 | /* non-redistributable addresses shouldn't be used for RIDs either */ | |
69 | if (!zebra_check_addr(ifc->address)) | |
70 | return 1; | |
71 | ||
72 | return 0; | |
18a6dce6 | 73 | } |
74 | ||
d62a17ae | 75 | void router_id_get(struct prefix *p, vrf_id_t vrf_id) |
18a6dce6 | 76 | { |
d62a17ae | 77 | struct listnode *node; |
78 | struct connected *c; | |
79 | struct zebra_vrf *zvrf = vrf_info_get(vrf_id); | |
80 | ||
81 | p->u.prefix4.s_addr = 0; | |
82 | p->family = AF_INET; | |
83 | p->prefixlen = 32; | |
84 | ||
85 | if (zvrf->rid_user_assigned.u.prefix4.s_addr) | |
86 | p->u.prefix4.s_addr = zvrf->rid_user_assigned.u.prefix4.s_addr; | |
87 | else if (!list_isempty(zvrf->rid_lo_sorted_list)) { | |
88 | node = listtail(zvrf->rid_lo_sorted_list); | |
89 | c = listgetdata(node); | |
90 | p->u.prefix4.s_addr = c->address->u.prefix4.s_addr; | |
91 | } else if (!list_isempty(zvrf->rid_all_sorted_list)) { | |
92 | node = listtail(zvrf->rid_all_sorted_list); | |
93 | c = listgetdata(node); | |
94 | p->u.prefix4.s_addr = c->address->u.prefix4.s_addr; | |
95 | } | |
18a6dce6 | 96 | } |
97 | ||
d62a17ae | 98 | static void router_id_set(struct prefix *p, vrf_id_t vrf_id) |
18a6dce6 | 99 | { |
d62a17ae | 100 | struct prefix p2; |
101 | struct listnode *node; | |
102 | struct zserv *client; | |
103 | struct zebra_vrf *zvrf; | |
104 | ||
105 | if (p->u.prefix4.s_addr == 0) /* unset */ | |
106 | { | |
107 | zvrf = vrf_info_lookup(vrf_id); | |
108 | if (!zvrf) | |
109 | return; | |
110 | } else /* set */ | |
111 | zvrf = vrf_info_get(vrf_id); | |
112 | ||
113 | zvrf->rid_user_assigned.u.prefix4.s_addr = p->u.prefix4.s_addr; | |
114 | ||
115 | router_id_get(&p2, vrf_id); | |
116 | ||
117 | for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) | |
118 | zsend_router_id_update(client, &p2, vrf_id); | |
18a6dce6 | 119 | } |
120 | ||
d62a17ae | 121 | void router_id_add_address(struct connected *ifc) |
18a6dce6 | 122 | { |
d62a17ae | 123 | struct list *l = NULL; |
124 | struct listnode *node; | |
125 | struct prefix before; | |
126 | struct prefix after; | |
127 | struct zserv *client; | |
128 | struct zebra_vrf *zvrf = vrf_info_get(ifc->ifp->vrf_id); | |
129 | ||
130 | if (router_id_bad_address(ifc)) | |
131 | return; | |
132 | ||
133 | router_id_get(&before, zvrf_id(zvrf)); | |
134 | ||
135 | if (!strncmp(ifc->ifp->name, "lo", 2) | |
136 | || !strncmp(ifc->ifp->name, "dummy", 5)) | |
137 | l = zvrf->rid_lo_sorted_list; | |
138 | else | |
139 | l = zvrf->rid_all_sorted_list; | |
140 | ||
141 | if (!router_id_find_node(l, ifc)) | |
142 | listnode_add_sort(l, ifc); | |
143 | ||
144 | router_id_get(&after, zvrf_id(zvrf)); | |
145 | ||
146 | if (prefix_same(&before, &after)) | |
147 | return; | |
148 | ||
149 | for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) | |
150 | zsend_router_id_update(client, &after, zvrf_id(zvrf)); | |
18a6dce6 | 151 | } |
152 | ||
d62a17ae | 153 | void router_id_del_address(struct connected *ifc) |
18a6dce6 | 154 | { |
d62a17ae | 155 | struct connected *c; |
156 | struct list *l; | |
157 | struct prefix after; | |
158 | struct prefix before; | |
159 | struct listnode *node; | |
160 | struct zserv *client; | |
161 | struct zebra_vrf *zvrf = vrf_info_get(ifc->ifp->vrf_id); | |
18a6dce6 | 162 | |
d62a17ae | 163 | if (router_id_bad_address(ifc)) |
164 | return; | |
18a6dce6 | 165 | |
d62a17ae | 166 | router_id_get(&before, zvrf_id(zvrf)); |
18a6dce6 | 167 | |
d62a17ae | 168 | if (!strncmp(ifc->ifp->name, "lo", 2) |
169 | || !strncmp(ifc->ifp->name, "dummy", 5)) | |
170 | l = zvrf->rid_lo_sorted_list; | |
171 | else | |
172 | l = zvrf->rid_all_sorted_list; | |
18a6dce6 | 173 | |
d62a17ae | 174 | if ((c = router_id_find_node(l, ifc))) |
175 | listnode_delete(l, c); | |
18a6dce6 | 176 | |
d62a17ae | 177 | router_id_get(&after, zvrf_id(zvrf)); |
18a6dce6 | 178 | |
d62a17ae | 179 | if (prefix_same(&before, &after)) |
180 | return; | |
18a6dce6 | 181 | |
d62a17ae | 182 | for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) |
183 | zsend_router_id_update(client, &after, zvrf_id(zvrf)); | |
18a6dce6 | 184 | } |
185 | ||
d62a17ae | 186 | void router_id_write(struct vty *vty) |
18a6dce6 | 187 | { |
d62a17ae | 188 | struct vrf *vrf; |
189 | struct zebra_vrf *zvrf; | |
190 | ||
a2addae8 RW |
191 | RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) |
192 | if ((zvrf = vrf->info) != NULL) | |
193 | if (zvrf->rid_user_assigned.u.prefix4.s_addr) { | |
194 | if (zvrf_id(zvrf) == VRF_DEFAULT) | |
195 | vty_out(vty, "router-id %s\n", | |
196 | inet_ntoa( | |
197 | zvrf->rid_user_assigned | |
198 | .u.prefix4)); | |
199 | else | |
200 | vty_out(vty, "router-id %s vrf %s\n", | |
201 | inet_ntoa( | |
202 | zvrf->rid_user_assigned | |
203 | .u.prefix4), | |
204 | zvrf_name(zvrf)); | |
205 | } | |
18a6dce6 | 206 | } |
207 | ||
208 | DEFUN (router_id, | |
209 | router_id_cmd, | |
92300491 | 210 | "router-id A.B.C.D [vrf NAME]", |
18a6dce6 | 211 | "Manually set the router-id\n" |
92300491 DW |
212 | "IP address to use for router-id\n" |
213 | VRF_CMD_HELP_STR) | |
18a6dce6 | 214 | { |
d62a17ae | 215 | int idx_ipv4 = 1; |
216 | int idx_name = 3; | |
92300491 | 217 | |
d62a17ae | 218 | struct prefix rid; |
219 | vrf_id_t vrf_id = VRF_DEFAULT; | |
18a6dce6 | 220 | |
d62a17ae | 221 | rid.u.prefix4.s_addr = inet_addr(argv[idx_ipv4]->arg); |
222 | if (!rid.u.prefix4.s_addr) | |
223 | return CMD_WARNING_CONFIG_FAILED; | |
18a6dce6 | 224 | |
d62a17ae | 225 | rid.prefixlen = 32; |
226 | rid.family = AF_INET; | |
18a6dce6 | 227 | |
d62a17ae | 228 | if (argc > 2) |
229 | VRF_GET_ID(vrf_id, argv[idx_name]->arg); | |
c6ffe645 | 230 | |
d62a17ae | 231 | router_id_set(&rid, vrf_id); |
18a6dce6 | 232 | |
d62a17ae | 233 | return CMD_SUCCESS; |
18a6dce6 | 234 | } |
235 | ||
236 | DEFUN (no_router_id, | |
237 | no_router_id_cmd, | |
92300491 | 238 | "no router-id [A.B.C.D [vrf NAME]]", |
18a6dce6 | 239 | NO_STR |
92300491 DW |
240 | "Remove the manually configured router-id\n" |
241 | "IP address to use for router-id\n" | |
242 | VRF_CMD_HELP_STR) | |
18a6dce6 | 243 | { |
d62a17ae | 244 | int idx_name = 4; |
92300491 | 245 | |
d62a17ae | 246 | struct prefix rid; |
247 | vrf_id_t vrf_id = VRF_DEFAULT; | |
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) |
254 | VRF_GET_ID(vrf_id, argv[idx_name]->arg); | |
c6ffe645 | 255 | |
d62a17ae | 256 | router_id_set(&rid, vrf_id); |
18a6dce6 | 257 | |
d62a17ae | 258 | return CMD_SUCCESS; |
18a6dce6 | 259 | } |
260 | ||
813d4307 | 261 | |
d62a17ae | 262 | static int router_id_cmp(void *a, void *b) |
18a6dce6 | 263 | { |
d62a17ae | 264 | const struct connected *ifa = (const struct connected *)a; |
265 | const struct connected *ifb = (const struct connected *)b; | |
18a6dce6 | 266 | |
d62a17ae | 267 | return IPV4_ADDR_CMP(&ifa->address->u.prefix4.s_addr, |
268 | &ifb->address->u.prefix4.s_addr); | |
18a6dce6 | 269 | } |
270 | ||
d62a17ae | 271 | void router_id_cmd_init(void) |
18a6dce6 | 272 | { |
d62a17ae | 273 | install_element(CONFIG_NODE, &router_id_cmd); |
274 | install_element(CONFIG_NODE, &no_router_id_cmd); | |
c6ffe645 FL |
275 | } |
276 | ||
d62a17ae | 277 | void router_id_init(struct zebra_vrf *zvrf) |
c6ffe645 | 278 | { |
d62a17ae | 279 | zvrf->rid_all_sorted_list = &zvrf->_rid_all_sorted_list; |
280 | zvrf->rid_lo_sorted_list = &zvrf->_rid_lo_sorted_list; | |
18a6dce6 | 281 | |
d62a17ae | 282 | memset(zvrf->rid_all_sorted_list, 0, |
283 | sizeof(zvrf->_rid_all_sorted_list)); | |
284 | memset(zvrf->rid_lo_sorted_list, 0, sizeof(zvrf->_rid_lo_sorted_list)); | |
285 | memset(&zvrf->rid_user_assigned, 0, sizeof(zvrf->rid_user_assigned)); | |
18a6dce6 | 286 | |
d62a17ae | 287 | zvrf->rid_all_sorted_list->cmp = router_id_cmp; |
288 | zvrf->rid_lo_sorted_list->cmp = router_id_cmp; | |
18a6dce6 | 289 | |
d62a17ae | 290 | zvrf->rid_user_assigned.family = AF_INET; |
291 | zvrf->rid_user_assigned.prefixlen = 32; | |
18a6dce6 | 292 | } |