blob: a4eb73ae5303a0390a398c3bd0078888f7281c1c [file] [log] [blame]
hasso18a6dce2004-10-03 18:18:34 +00001/*
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"
Feng Luac19a442015-05-22 11:40:07 +020039#include "vrf.h"
hasso18a6dce2004-10-03 18:18:34 +000040
41#include "zebra/zserv.h"
paula1ac18c2005-06-28 17:17:12 +000042#include "zebra/router-id.h"
Paul Jakma6dc686a2007-04-10 19:24:45 +000043#include "zebra/redistribute.h"
hasso18a6dce2004-10-03 18:18:34 +000044
hasso18a6dce2004-10-03 18:18:34 +000045/* master zebra server structure */
46extern struct zebra_t zebrad;
47
48static struct connected *
49router_id_find_node (struct list *l, struct connected *ifc)
50{
51 struct listnode *node;
52 struct connected *c;
53
paul1eb8ef22005-04-07 07:30:20 +000054 for (ALL_LIST_ELEMENTS_RO (l, node, c))
55 if (prefix_same (ifc->address, c->address))
56 return c;
57
hasso18a6dce2004-10-03 18:18:34 +000058 return NULL;
59}
60
61static int
62router_id_bad_address (struct connected *ifc)
63{
hasso18a6dce2004-10-03 18:18:34 +000064 if (ifc->address->family != AF_INET)
65 return 1;
Paul Jakma6dc686a2007-04-10 19:24:45 +000066
67 /* non-redistributable addresses shouldn't be used for RIDs either */
68 if (!zebra_check_addr (ifc->address))
hasso18a6dce2004-10-03 18:18:34 +000069 return 1;
Paul Jakma6dc686a2007-04-10 19:24:45 +000070
hasso18a6dce2004-10-03 18:18:34 +000071 return 0;
72}
73
74void
Feng Luac19a442015-05-22 11:40:07 +020075router_id_get (struct prefix *p, vrf_id_t vrf_id)
hasso18a6dce2004-10-03 18:18:34 +000076{
77 struct listnode *node;
78 struct connected *c;
Feng Luac19a442015-05-22 11:40:07 +020079 struct zebra_vrf *zvrf = vrf_info_get (vrf_id);
hasso18a6dce2004-10-03 18:18:34 +000080
81 p->u.prefix4.s_addr = 0;
82 p->family = AF_INET;
83 p->prefixlen = 32;
84
Feng Luac19a442015-05-22 11:40:07 +020085 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))
hasso18a6dce2004-10-03 18:18:34 +000088 {
Feng Luac19a442015-05-22 11:40:07 +020089 node = listtail (zvrf->rid_lo_sorted_list);
paul1eb8ef22005-04-07 07:30:20 +000090 c = listgetdata (node);
hasso18a6dce2004-10-03 18:18:34 +000091 p->u.prefix4.s_addr = c->address->u.prefix4.s_addr;
92 }
Feng Luac19a442015-05-22 11:40:07 +020093 else if (!list_isempty (zvrf->rid_all_sorted_list))
hasso18a6dce2004-10-03 18:18:34 +000094 {
Feng Luac19a442015-05-22 11:40:07 +020095 node = listtail (zvrf->rid_all_sorted_list);
paul1eb8ef22005-04-07 07:30:20 +000096 c = listgetdata (node);
hasso18a6dce2004-10-03 18:18:34 +000097 p->u.prefix4.s_addr = c->address->u.prefix4.s_addr;
98 }
99}
100
101static void
Feng Luac19a442015-05-22 11:40:07 +0200102router_id_set (struct prefix *p, vrf_id_t vrf_id)
hasso18a6dce2004-10-03 18:18:34 +0000103{
104 struct prefix p2;
105 struct listnode *node;
106 struct zserv *client;
Feng Luac19a442015-05-22 11:40:07 +0200107 struct zebra_vrf *zvrf;
hasso18a6dce2004-10-03 18:18:34 +0000108
Feng Luac19a442015-05-22 11:40:07 +0200109 if (p->u.prefix4.s_addr == 0) /* unset */
110 {
111 zvrf = vrf_info_lookup (vrf_id);
112 if (! zvrf)
113 return;
114 }
115 else /* set */
116 zvrf = vrf_info_get (vrf_id);
hasso18a6dce2004-10-03 18:18:34 +0000117
Feng Luac19a442015-05-22 11:40:07 +0200118 zvrf->rid_user_assigned.u.prefix4.s_addr = p->u.prefix4.s_addr;
119
120 router_id_get (&p2, vrf_id);
paul1eb8ef22005-04-07 07:30:20 +0000121
122 for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client))
Feng Luac19a442015-05-22 11:40:07 +0200123 zsend_router_id_update (client, &p2, vrf_id);
hasso18a6dce2004-10-03 18:18:34 +0000124}
125
126void
127router_id_add_address (struct connected *ifc)
128{
129 struct list *l = NULL;
130 struct listnode *node;
131 struct prefix before;
132 struct prefix after;
133 struct zserv *client;
Feng Luac19a442015-05-22 11:40:07 +0200134 struct zebra_vrf *zvrf = vrf_info_get (ifc->ifp->vrf_id);
hasso18a6dce2004-10-03 18:18:34 +0000135
136 if (router_id_bad_address (ifc))
137 return;
138
Feng Luac19a442015-05-22 11:40:07 +0200139 router_id_get (&before, zvrf->vrf_id);
hasso18a6dce2004-10-03 18:18:34 +0000140
141 if (!strncmp (ifc->ifp->name, "lo", 2)
142 || !strncmp (ifc->ifp->name, "dummy", 5))
Feng Luac19a442015-05-22 11:40:07 +0200143 l = zvrf->rid_lo_sorted_list;
hasso18a6dce2004-10-03 18:18:34 +0000144 else
Feng Luac19a442015-05-22 11:40:07 +0200145 l = zvrf->rid_all_sorted_list;
hasso18a6dce2004-10-03 18:18:34 +0000146
147 if (!router_id_find_node (l, ifc))
Stephen Hemmingerb6516822009-12-21 18:50:43 +0300148 listnode_add_sort (l, ifc);
hasso18a6dce2004-10-03 18:18:34 +0000149
Feng Luac19a442015-05-22 11:40:07 +0200150 router_id_get (&after, zvrf->vrf_id);
hasso18a6dce2004-10-03 18:18:34 +0000151
152 if (prefix_same (&before, &after))
153 return;
154
paul1eb8ef22005-04-07 07:30:20 +0000155 for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client))
Feng Luac19a442015-05-22 11:40:07 +0200156 zsend_router_id_update (client, &after, zvrf->vrf_id);
hasso18a6dce2004-10-03 18:18:34 +0000157}
158
159void
160router_id_del_address (struct connected *ifc)
161{
162 struct connected *c;
163 struct list *l;
164 struct prefix after;
165 struct prefix before;
166 struct listnode *node;
167 struct zserv *client;
Feng Luac19a442015-05-22 11:40:07 +0200168 struct zebra_vrf *zvrf = vrf_info_get (ifc->ifp->vrf_id);
hasso18a6dce2004-10-03 18:18:34 +0000169
170 if (router_id_bad_address (ifc))
171 return;
172
Feng Luac19a442015-05-22 11:40:07 +0200173 router_id_get (&before, zvrf->vrf_id);
hasso18a6dce2004-10-03 18:18:34 +0000174
175 if (!strncmp (ifc->ifp->name, "lo", 2)
176 || !strncmp (ifc->ifp->name, "dummy", 5))
Feng Luac19a442015-05-22 11:40:07 +0200177 l = zvrf->rid_lo_sorted_list;
hasso18a6dce2004-10-03 18:18:34 +0000178 else
Feng Luac19a442015-05-22 11:40:07 +0200179 l = zvrf->rid_all_sorted_list;
hasso18a6dce2004-10-03 18:18:34 +0000180
181 if ((c = router_id_find_node (l, ifc)))
182 listnode_delete (l, c);
183
Feng Luac19a442015-05-22 11:40:07 +0200184 router_id_get (&after, zvrf->vrf_id);
hasso18a6dce2004-10-03 18:18:34 +0000185
186 if (prefix_same (&before, &after))
187 return;
188
paul1eb8ef22005-04-07 07:30:20 +0000189 for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client))
Feng Luac19a442015-05-22 11:40:07 +0200190 zsend_router_id_update (client, &after, zvrf->vrf_id);
hasso18a6dce2004-10-03 18:18:34 +0000191}
192
193void
194router_id_write (struct vty *vty)
195{
Feng Luac19a442015-05-22 11:40:07 +0200196 struct zebra_vrf *zvrf;
197 vrf_iter_t iter;
198
199 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
200 if ((zvrf = vrf_iter2info (iter)) != NULL)
201 if (zvrf->rid_user_assigned.u.prefix4.s_addr)
202 {
203 if (zvrf->vrf_id == VRF_DEFAULT)
204 vty_out (vty, "router-id %s%s",
205 inet_ntoa (zvrf->rid_user_assigned.u.prefix4),
206 VTY_NEWLINE);
207 else
208 vty_out (vty, "router-id %s vrf %u%s",
209 inet_ntoa (zvrf->rid_user_assigned.u.prefix4),
210 zvrf->vrf_id,
211 VTY_NEWLINE);
212 }
hasso18a6dce2004-10-03 18:18:34 +0000213}
214
215DEFUN (router_id,
216 router_id_cmd,
217 "router-id A.B.C.D",
218 "Manually set the router-id\n"
219 "IP address to use for router-id\n")
220{
221 struct prefix rid;
Feng Luac19a442015-05-22 11:40:07 +0200222 vrf_id_t vrf_id = VRF_DEFAULT;
hasso18a6dce2004-10-03 18:18:34 +0000223
224 rid.u.prefix4.s_addr = inet_addr (argv[0]);
225 if (!rid.u.prefix4.s_addr)
226 return CMD_WARNING;
227
228 rid.prefixlen = 32;
229 rid.family = AF_INET;
230
Feng Luac19a442015-05-22 11:40:07 +0200231 if (argc > 1)
232 VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]);
233
234 router_id_set (&rid, vrf_id);
hasso18a6dce2004-10-03 18:18:34 +0000235
236 return CMD_SUCCESS;
237}
238
Feng Luac19a442015-05-22 11:40:07 +0200239ALIAS (router_id,
240 router_id_vrf_cmd,
241 "router-id A.B.C.D " VRF_CMD_STR,
242 "Manually set the router-id\n"
243 "IP address to use for router-id\n"
244 VRF_CMD_HELP_STR)
245
hasso18a6dce2004-10-03 18:18:34 +0000246DEFUN (no_router_id,
247 no_router_id_cmd,
248 "no router-id",
249 NO_STR
250 "Remove the manually configured router-id\n")
251{
252 struct prefix rid;
Feng Luac19a442015-05-22 11:40:07 +0200253 vrf_id_t vrf_id = VRF_DEFAULT;
hasso18a6dce2004-10-03 18:18:34 +0000254
255 rid.u.prefix4.s_addr = 0;
256 rid.prefixlen = 0;
257 rid.family = AF_INET;
258
Feng Luac19a442015-05-22 11:40:07 +0200259 if (argc > 0)
260 VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]);
261
262 router_id_set (&rid, vrf_id);
hasso18a6dce2004-10-03 18:18:34 +0000263
264 return CMD_SUCCESS;
265}
266
Feng Luac19a442015-05-22 11:40:07 +0200267ALIAS (no_router_id,
268 no_router_id_vrf_cmd,
269 "no router-id " VRF_CMD_STR,
270 NO_STR
271 "Remove the manually configured router-id\n"
272 VRF_CMD_HELP_STR)
273
paula1ac18c2005-06-28 17:17:12 +0000274static int
hasso18a6dce2004-10-03 18:18:34 +0000275router_id_cmp (void *a, void *b)
276{
Stephen Hemmingerb6516822009-12-21 18:50:43 +0300277 const struct connected *ifa = (const struct connected *)a;
278 const struct connected *ifb = (const struct connected *)b;
hasso18a6dce2004-10-03 18:18:34 +0000279
Ken Williams24c84db2014-04-15 02:23:11 +0000280 return IPV4_ADDR_CMP(&ifa->address->u.prefix4.s_addr,&ifb->address->u.prefix4.s_addr);
hasso18a6dce2004-10-03 18:18:34 +0000281}
282
283void
Feng Luac19a442015-05-22 11:40:07 +0200284router_id_cmd_init (void)
hasso18a6dce2004-10-03 18:18:34 +0000285{
286 install_element (CONFIG_NODE, &router_id_cmd);
287 install_element (CONFIG_NODE, &no_router_id_cmd);
Feng Luac19a442015-05-22 11:40:07 +0200288 install_element (CONFIG_NODE, &router_id_vrf_cmd);
289 install_element (CONFIG_NODE, &no_router_id_vrf_cmd);
290}
hasso18a6dce2004-10-03 18:18:34 +0000291
Feng Luac19a442015-05-22 11:40:07 +0200292void
293router_id_init (struct zebra_vrf *zvrf)
294{
295 zvrf->rid_all_sorted_list = &zvrf->_rid_all_sorted_list;
296 zvrf->rid_lo_sorted_list = &zvrf->_rid_lo_sorted_list;
hasso18a6dce2004-10-03 18:18:34 +0000297
Feng Luac19a442015-05-22 11:40:07 +0200298 memset (zvrf->rid_all_sorted_list, 0, sizeof (zvrf->_rid_all_sorted_list));
299 memset (zvrf->rid_lo_sorted_list, 0, sizeof (zvrf->_rid_lo_sorted_list));
300 memset (&zvrf->rid_user_assigned, 0, sizeof (zvrf->rid_user_assigned));
hasso18a6dce2004-10-03 18:18:34 +0000301
Feng Luac19a442015-05-22 11:40:07 +0200302 zvrf->rid_all_sorted_list->cmp = router_id_cmp;
303 zvrf->rid_lo_sorted_list->cmp = router_id_cmp;
304
305 zvrf->rid_user_assigned.family = AF_INET;
306 zvrf->rid_user_assigned.prefixlen = 32;
hasso18a6dce2004-10-03 18:18:34 +0000307}