]> git.proxmox.com Git - mirror_frr.git/blame - zebra/router-id.c
zebra: fix rtnh_len in the rt_netlink messages for multipath case
[mirror_frr.git] / zebra / router-id.c
CommitLineData
18a6dce6 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
19 * along with GNU Zebra; see the file COPYING. If not, write to the Free
20 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21 * 02111-1307, USA.
22 */
23
24#include <zebra.h>
25
26#include "if.h"
27#include "vty.h"
28#include "sockunion.h"
29#include "prefix.h"
30#include "stream.h"
31#include "command.h"
32#include "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"
c6ffe645 39#include "vrf.h"
18a6dce6 40
41#include "zebra/zserv.h"
7c551956 42#include "zebra/zebra_vrf.h"
a1ac18c4 43#include "zebra/router-id.h"
6dc686a2 44#include "zebra/redistribute.h"
18a6dce6 45
18a6dce6 46static struct connected *
47router_id_find_node (struct list *l, struct connected *ifc)
48{
49 struct listnode *node;
50 struct connected *c;
51
1eb8ef25 52 for (ALL_LIST_ELEMENTS_RO (l, node, c))
53 if (prefix_same (ifc->address, c->address))
54 return c;
55
18a6dce6 56 return NULL;
57}
58
59static int
60router_id_bad_address (struct connected *ifc)
61{
18a6dce6 62 if (ifc->address->family != AF_INET)
63 return 1;
6dc686a2
PJ
64
65 /* non-redistributable addresses shouldn't be used for RIDs either */
66 if (!zebra_check_addr (ifc->address))
18a6dce6 67 return 1;
6dc686a2 68
18a6dce6 69 return 0;
70}
71
72void
c6ffe645 73router_id_get (struct prefix *p, vrf_id_t vrf_id)
18a6dce6 74{
75 struct listnode *node;
76 struct connected *c;
c6ffe645 77 struct zebra_vrf *zvrf = vrf_info_get (vrf_id);
18a6dce6 78
79 p->u.prefix4.s_addr = 0;
80 p->family = AF_INET;
81 p->prefixlen = 32;
82
c6ffe645
FL
83 if (zvrf->rid_user_assigned.u.prefix4.s_addr)
84 p->u.prefix4.s_addr = zvrf->rid_user_assigned.u.prefix4.s_addr;
85 else if (!list_isempty (zvrf->rid_lo_sorted_list))
18a6dce6 86 {
c6ffe645 87 node = listtail (zvrf->rid_lo_sorted_list);
1eb8ef25 88 c = listgetdata (node);
18a6dce6 89 p->u.prefix4.s_addr = c->address->u.prefix4.s_addr;
90 }
c6ffe645 91 else if (!list_isempty (zvrf->rid_all_sorted_list))
18a6dce6 92 {
c6ffe645 93 node = listtail (zvrf->rid_all_sorted_list);
1eb8ef25 94 c = listgetdata (node);
18a6dce6 95 p->u.prefix4.s_addr = c->address->u.prefix4.s_addr;
96 }
97}
98
99static void
c6ffe645 100router_id_set (struct prefix *p, vrf_id_t vrf_id)
18a6dce6 101{
102 struct prefix p2;
103 struct listnode *node;
104 struct zserv *client;
c6ffe645 105 struct zebra_vrf *zvrf;
18a6dce6 106
c6ffe645
FL
107 if (p->u.prefix4.s_addr == 0) /* unset */
108 {
109 zvrf = vrf_info_lookup (vrf_id);
110 if (! zvrf)
111 return;
112 }
113 else /* set */
114 zvrf = vrf_info_get (vrf_id);
18a6dce6 115
c6ffe645
FL
116 zvrf->rid_user_assigned.u.prefix4.s_addr = p->u.prefix4.s_addr;
117
118 router_id_get (&p2, vrf_id);
1eb8ef25 119
120 for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client))
c6ffe645 121 zsend_router_id_update (client, &p2, vrf_id);
18a6dce6 122}
123
124void
125router_id_add_address (struct connected *ifc)
126{
127 struct list *l = NULL;
128 struct listnode *node;
129 struct prefix before;
130 struct prefix after;
131 struct zserv *client;
c6ffe645 132 struct zebra_vrf *zvrf = vrf_info_get (ifc->ifp->vrf_id);
18a6dce6 133
134 if (router_id_bad_address (ifc))
135 return;
136
c6ffe645 137 router_id_get (&before, zvrf->vrf_id);
18a6dce6 138
139 if (!strncmp (ifc->ifp->name, "lo", 2)
140 || !strncmp (ifc->ifp->name, "dummy", 5))
c6ffe645 141 l = zvrf->rid_lo_sorted_list;
18a6dce6 142 else
c6ffe645 143 l = zvrf->rid_all_sorted_list;
18a6dce6 144
145 if (!router_id_find_node (l, ifc))
b6516829 146 listnode_add_sort (l, ifc);
18a6dce6 147
c6ffe645 148 router_id_get (&after, zvrf->vrf_id);
18a6dce6 149
150 if (prefix_same (&before, &after))
151 return;
152
1eb8ef25 153 for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client))
c6ffe645 154 zsend_router_id_update (client, &after, zvrf->vrf_id);
18a6dce6 155}
156
157void
158router_id_del_address (struct connected *ifc)
159{
160 struct connected *c;
161 struct list *l;
162 struct prefix after;
163 struct prefix before;
164 struct listnode *node;
165 struct zserv *client;
c6ffe645 166 struct zebra_vrf *zvrf = vrf_info_get (ifc->ifp->vrf_id);
18a6dce6 167
168 if (router_id_bad_address (ifc))
169 return;
170
c6ffe645 171 router_id_get (&before, zvrf->vrf_id);
18a6dce6 172
173 if (!strncmp (ifc->ifp->name, "lo", 2)
174 || !strncmp (ifc->ifp->name, "dummy", 5))
c6ffe645 175 l = zvrf->rid_lo_sorted_list;
18a6dce6 176 else
c6ffe645 177 l = zvrf->rid_all_sorted_list;
18a6dce6 178
179 if ((c = router_id_find_node (l, ifc)))
180 listnode_delete (l, c);
181
c6ffe645 182 router_id_get (&after, zvrf->vrf_id);
18a6dce6 183
184 if (prefix_same (&before, &after))
185 return;
186
1eb8ef25 187 for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client))
c6ffe645 188 zsend_router_id_update (client, &after, zvrf->vrf_id);
18a6dce6 189}
190
191void
192router_id_write (struct vty *vty)
193{
c6ffe645
FL
194 struct zebra_vrf *zvrf;
195 vrf_iter_t iter;
196
197 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
198 if ((zvrf = vrf_iter2info (iter)) != NULL)
199 if (zvrf->rid_user_assigned.u.prefix4.s_addr)
200 {
201 if (zvrf->vrf_id == VRF_DEFAULT)
202 vty_out (vty, "router-id %s%s",
203 inet_ntoa (zvrf->rid_user_assigned.u.prefix4),
204 VTY_NEWLINE);
205 else
1d75f883 206 vty_out (vty, "router-id %s vrf %s%s",
c6ffe645 207 inet_ntoa (zvrf->rid_user_assigned.u.prefix4),
1d75f883 208 zvrf->name,
c6ffe645
FL
209 VTY_NEWLINE);
210 }
18a6dce6 211}
212
213DEFUN (router_id,
214 router_id_cmd,
215 "router-id A.B.C.D",
216 "Manually set the router-id\n"
217 "IP address to use for router-id\n")
218{
219 struct prefix rid;
c6ffe645 220 vrf_id_t vrf_id = VRF_DEFAULT;
18a6dce6 221
222 rid.u.prefix4.s_addr = inet_addr (argv[0]);
223 if (!rid.u.prefix4.s_addr)
224 return CMD_WARNING;
225
226 rid.prefixlen = 32;
227 rid.family = AF_INET;
228
c6ffe645 229 if (argc > 1)
12f6fb97 230 VRF_GET_ID (vrf_id, argv[1]);
c6ffe645
FL
231
232 router_id_set (&rid, vrf_id);
18a6dce6 233
234 return CMD_SUCCESS;
235}
236
c6ffe645
FL
237ALIAS (router_id,
238 router_id_vrf_cmd,
239 "router-id A.B.C.D " VRF_CMD_STR,
240 "Manually set the router-id\n"
241 "IP address to use for router-id\n"
242 VRF_CMD_HELP_STR)
243
18a6dce6 244DEFUN (no_router_id,
245 no_router_id_cmd,
246 "no router-id",
247 NO_STR
248 "Remove the manually configured router-id\n")
249{
250 struct prefix rid;
c6ffe645 251 vrf_id_t vrf_id = VRF_DEFAULT;
18a6dce6 252
253 rid.u.prefix4.s_addr = 0;
254 rid.prefixlen = 0;
255 rid.family = AF_INET;
256
813d4307 257 if (argc > 1)
12f6fb97 258 VRF_GET_ID (vrf_id, argv[1]);
c6ffe645
FL
259
260 router_id_set (&rid, vrf_id);
18a6dce6 261
262 return CMD_SUCCESS;
263}
264
813d4307
DW
265ALIAS (no_router_id,
266 no_router_id_val_cmd,
267 "no router-id A.B.C.D",
268 NO_STR
269 "Remove the manually configured router-id\n"
270 "IP address to use for router-id\n")
271
c6ffe645
FL
272ALIAS (no_router_id,
273 no_router_id_vrf_cmd,
813d4307 274 "no router-id A.B.C.D " VRF_CMD_STR,
c6ffe645
FL
275 NO_STR
276 "Remove the manually configured router-id\n"
813d4307 277 "IP address to use for router-id\n"
c6ffe645
FL
278 VRF_CMD_HELP_STR)
279
a1ac18c4 280static int
18a6dce6 281router_id_cmp (void *a, void *b)
282{
b6516829
SH
283 const struct connected *ifa = (const struct connected *)a;
284 const struct connected *ifb = (const struct connected *)b;
18a6dce6 285
24c84dbe 286 return IPV4_ADDR_CMP(&ifa->address->u.prefix4.s_addr,&ifb->address->u.prefix4.s_addr);
18a6dce6 287}
288
289void
c6ffe645 290router_id_cmd_init (void)
18a6dce6 291{
292 install_element (CONFIG_NODE, &router_id_cmd);
293 install_element (CONFIG_NODE, &no_router_id_cmd);
c6ffe645 294 install_element (CONFIG_NODE, &router_id_vrf_cmd);
813d4307 295 install_element (CONFIG_NODE, &no_router_id_val_cmd);
c6ffe645
FL
296 install_element (CONFIG_NODE, &no_router_id_vrf_cmd);
297}
298
299void
300router_id_init (struct zebra_vrf *zvrf)
301{
302 zvrf->rid_all_sorted_list = &zvrf->_rid_all_sorted_list;
303 zvrf->rid_lo_sorted_list = &zvrf->_rid_lo_sorted_list;
18a6dce6 304
c6ffe645
FL
305 memset (zvrf->rid_all_sorted_list, 0, sizeof (zvrf->_rid_all_sorted_list));
306 memset (zvrf->rid_lo_sorted_list, 0, sizeof (zvrf->_rid_lo_sorted_list));
307 memset (&zvrf->rid_user_assigned, 0, sizeof (zvrf->rid_user_assigned));
18a6dce6 308
c6ffe645
FL
309 zvrf->rid_all_sorted_list->cmp = router_id_cmp;
310 zvrf->rid_lo_sorted_list->cmp = router_id_cmp;
18a6dce6 311
c6ffe645
FL
312 zvrf->rid_user_assigned.family = AF_INET;
313 zvrf->rid_user_assigned.prefixlen = 32;
18a6dce6 314}