]>
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 | ||
106935f6 | 135 | if (if_is_loopback(ifc->ifp)) |
d62a17ae | 136 | l = zvrf->rid_lo_sorted_list; |
137 | else | |
138 | l = zvrf->rid_all_sorted_list; | |
139 | ||
140 | if (!router_id_find_node(l, ifc)) | |
141 | listnode_add_sort(l, ifc); | |
142 | ||
143 | router_id_get(&after, zvrf_id(zvrf)); | |
144 | ||
145 | if (prefix_same(&before, &after)) | |
146 | return; | |
147 | ||
148 | for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) | |
149 | zsend_router_id_update(client, &after, zvrf_id(zvrf)); | |
18a6dce6 | 150 | } |
151 | ||
d62a17ae | 152 | void router_id_del_address(struct connected *ifc) |
18a6dce6 | 153 | { |
d62a17ae | 154 | struct connected *c; |
155 | struct list *l; | |
156 | struct prefix after; | |
157 | struct prefix before; | |
158 | struct listnode *node; | |
159 | struct zserv *client; | |
160 | struct zebra_vrf *zvrf = vrf_info_get(ifc->ifp->vrf_id); | |
18a6dce6 | 161 | |
d62a17ae | 162 | if (router_id_bad_address(ifc)) |
163 | return; | |
18a6dce6 | 164 | |
d62a17ae | 165 | router_id_get(&before, zvrf_id(zvrf)); |
18a6dce6 | 166 | |
106935f6 | 167 | if (if_is_loopback(ifc->ifp)) |
d62a17ae | 168 | l = zvrf->rid_lo_sorted_list; |
169 | else | |
170 | l = zvrf->rid_all_sorted_list; | |
18a6dce6 | 171 | |
d62a17ae | 172 | if ((c = router_id_find_node(l, ifc))) |
173 | listnode_delete(l, c); | |
18a6dce6 | 174 | |
d62a17ae | 175 | router_id_get(&after, zvrf_id(zvrf)); |
18a6dce6 | 176 | |
d62a17ae | 177 | if (prefix_same(&before, &after)) |
178 | return; | |
18a6dce6 | 179 | |
d62a17ae | 180 | for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) |
181 | zsend_router_id_update(client, &after, zvrf_id(zvrf)); | |
18a6dce6 | 182 | } |
183 | ||
d62a17ae | 184 | void router_id_write(struct vty *vty) |
18a6dce6 | 185 | { |
d62a17ae | 186 | struct vrf *vrf; |
187 | struct zebra_vrf *zvrf; | |
188 | ||
a2addae8 RW |
189 | RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) |
190 | if ((zvrf = vrf->info) != NULL) | |
191 | if (zvrf->rid_user_assigned.u.prefix4.s_addr) { | |
192 | if (zvrf_id(zvrf) == VRF_DEFAULT) | |
193 | vty_out(vty, "router-id %s\n", | |
194 | inet_ntoa( | |
195 | zvrf->rid_user_assigned | |
196 | .u.prefix4)); | |
197 | else | |
198 | vty_out(vty, "router-id %s vrf %s\n", | |
199 | inet_ntoa( | |
200 | zvrf->rid_user_assigned | |
201 | .u.prefix4), | |
202 | zvrf_name(zvrf)); | |
203 | } | |
18a6dce6 | 204 | } |
205 | ||
206 | DEFUN (router_id, | |
207 | router_id_cmd, | |
92300491 | 208 | "router-id A.B.C.D [vrf NAME]", |
18a6dce6 | 209 | "Manually set the router-id\n" |
92300491 DW |
210 | "IP address to use for router-id\n" |
211 | VRF_CMD_HELP_STR) | |
18a6dce6 | 212 | { |
d62a17ae | 213 | int idx_ipv4 = 1; |
214 | int idx_name = 3; | |
92300491 | 215 | |
d62a17ae | 216 | struct prefix rid; |
217 | vrf_id_t vrf_id = VRF_DEFAULT; | |
18a6dce6 | 218 | |
d62a17ae | 219 | rid.u.prefix4.s_addr = inet_addr(argv[idx_ipv4]->arg); |
220 | if (!rid.u.prefix4.s_addr) | |
221 | return CMD_WARNING_CONFIG_FAILED; | |
18a6dce6 | 222 | |
d62a17ae | 223 | rid.prefixlen = 32; |
224 | rid.family = AF_INET; | |
18a6dce6 | 225 | |
d62a17ae | 226 | if (argc > 2) |
ec1db588 | 227 | VRF_GET_ID(vrf_id, argv[idx_name]->arg, false); |
c6ffe645 | 228 | |
d62a17ae | 229 | router_id_set(&rid, vrf_id); |
18a6dce6 | 230 | |
d62a17ae | 231 | return CMD_SUCCESS; |
18a6dce6 | 232 | } |
233 | ||
234 | DEFUN (no_router_id, | |
235 | no_router_id_cmd, | |
92300491 | 236 | "no router-id [A.B.C.D [vrf NAME]]", |
18a6dce6 | 237 | NO_STR |
92300491 DW |
238 | "Remove the manually configured router-id\n" |
239 | "IP address to use for router-id\n" | |
240 | VRF_CMD_HELP_STR) | |
18a6dce6 | 241 | { |
d62a17ae | 242 | int idx_name = 4; |
92300491 | 243 | |
d62a17ae | 244 | struct prefix rid; |
245 | vrf_id_t vrf_id = VRF_DEFAULT; | |
18a6dce6 | 246 | |
d62a17ae | 247 | rid.u.prefix4.s_addr = 0; |
248 | rid.prefixlen = 0; | |
249 | rid.family = AF_INET; | |
18a6dce6 | 250 | |
d62a17ae | 251 | if (argc > 3) |
ec1db588 | 252 | VRF_GET_ID(vrf_id, argv[idx_name]->arg, false); |
c6ffe645 | 253 | |
d62a17ae | 254 | router_id_set(&rid, vrf_id); |
18a6dce6 | 255 | |
d62a17ae | 256 | return CMD_SUCCESS; |
18a6dce6 | 257 | } |
258 | ||
813d4307 | 259 | |
d62a17ae | 260 | static int router_id_cmp(void *a, void *b) |
18a6dce6 | 261 | { |
d62a17ae | 262 | const struct connected *ifa = (const struct connected *)a; |
263 | const struct connected *ifb = (const struct connected *)b; | |
18a6dce6 | 264 | |
d62a17ae | 265 | return IPV4_ADDR_CMP(&ifa->address->u.prefix4.s_addr, |
266 | &ifb->address->u.prefix4.s_addr); | |
18a6dce6 | 267 | } |
268 | ||
d62a17ae | 269 | void router_id_cmd_init(void) |
18a6dce6 | 270 | { |
d62a17ae | 271 | install_element(CONFIG_NODE, &router_id_cmd); |
272 | install_element(CONFIG_NODE, &no_router_id_cmd); | |
c6ffe645 FL |
273 | } |
274 | ||
d62a17ae | 275 | void router_id_init(struct zebra_vrf *zvrf) |
c6ffe645 | 276 | { |
d62a17ae | 277 | zvrf->rid_all_sorted_list = &zvrf->_rid_all_sorted_list; |
278 | zvrf->rid_lo_sorted_list = &zvrf->_rid_lo_sorted_list; | |
18a6dce6 | 279 | |
d62a17ae | 280 | memset(zvrf->rid_all_sorted_list, 0, |
281 | sizeof(zvrf->_rid_all_sorted_list)); | |
282 | memset(zvrf->rid_lo_sorted_list, 0, sizeof(zvrf->_rid_lo_sorted_list)); | |
283 | memset(&zvrf->rid_user_assigned, 0, sizeof(zvrf->rid_user_assigned)); | |
18a6dce6 | 284 | |
d62a17ae | 285 | zvrf->rid_all_sorted_list->cmp = router_id_cmp; |
286 | zvrf->rid_lo_sorted_list->cmp = router_id_cmp; | |
18a6dce6 | 287 | |
d62a17ae | 288 | zvrf->rid_user_assigned.family = AF_INET; |
289 | zvrf->rid_user_assigned.prefixlen = 32; | |
18a6dce6 | 290 | } |