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