blob: 3d6b511c53c223fc349c489d00b9c794b9f7b2b0 [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"
39
40#include "zebra/zserv.h"
paula1ac18c2005-06-28 17:17:12 +000041#include "zebra/router-id.h"
Paul Jakma6dc686a2007-04-10 19:24:45 +000042#include "zebra/redistribute.h"
hasso18a6dce2004-10-03 18:18:34 +000043
44static struct list rid_all_sorted_list;
45static struct list rid_lo_sorted_list;
46static struct prefix rid_user_assigned;
47
48/* master zebra server structure */
49extern struct zebra_t zebrad;
50
51static struct connected *
52router_id_find_node (struct list *l, struct connected *ifc)
53{
54 struct listnode *node;
55 struct connected *c;
56
paul1eb8ef22005-04-07 07:30:20 +000057 for (ALL_LIST_ELEMENTS_RO (l, node, c))
58 if (prefix_same (ifc->address, c->address))
59 return c;
60
hasso18a6dce2004-10-03 18:18:34 +000061 return NULL;
62}
63
64static int
65router_id_bad_address (struct connected *ifc)
66{
hasso18a6dce2004-10-03 18:18:34 +000067 if (ifc->address->family != AF_INET)
68 return 1;
Paul Jakma6dc686a2007-04-10 19:24:45 +000069
70 /* non-redistributable addresses shouldn't be used for RIDs either */
71 if (!zebra_check_addr (ifc->address))
hasso18a6dce2004-10-03 18:18:34 +000072 return 1;
Paul Jakma6dc686a2007-04-10 19:24:45 +000073
hasso18a6dce2004-10-03 18:18:34 +000074 return 0;
75}
76
77void
78router_id_get (struct prefix *p)
79{
80 struct listnode *node;
81 struct connected *c;
82
83 p->u.prefix4.s_addr = 0;
84 p->family = AF_INET;
85 p->prefixlen = 32;
86
87 if (rid_user_assigned.u.prefix4.s_addr)
88 p->u.prefix4.s_addr = rid_user_assigned.u.prefix4.s_addr;
89 else if (!list_isempty (&rid_lo_sorted_list))
90 {
91 node = listtail (&rid_lo_sorted_list);
paul1eb8ef22005-04-07 07:30:20 +000092 c = listgetdata (node);
hasso18a6dce2004-10-03 18:18:34 +000093 p->u.prefix4.s_addr = c->address->u.prefix4.s_addr;
94 }
95 else if (!list_isempty (&rid_all_sorted_list))
96 {
97 node = listtail (&rid_all_sorted_list);
paul1eb8ef22005-04-07 07:30:20 +000098 c = listgetdata (node);
hasso18a6dce2004-10-03 18:18:34 +000099 p->u.prefix4.s_addr = c->address->u.prefix4.s_addr;
100 }
101}
102
103static void
104router_id_set (struct prefix *p)
105{
106 struct prefix p2;
107 struct listnode *node;
108 struct zserv *client;
109
110 rid_user_assigned.u.prefix4.s_addr = p->u.prefix4.s_addr;
111
112 router_id_get (&p2);
paul1eb8ef22005-04-07 07:30:20 +0000113
114 for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client))
115 zsend_router_id_update (client, &p2);
hasso18a6dce2004-10-03 18:18:34 +0000116}
117
118void
119router_id_add_address (struct connected *ifc)
120{
121 struct list *l = NULL;
122 struct listnode *node;
123 struct prefix before;
124 struct prefix after;
125 struct zserv *client;
126
127 if (router_id_bad_address (ifc))
128 return;
129
130 router_id_get (&before);
131
132 if (!strncmp (ifc->ifp->name, "lo", 2)
133 || !strncmp (ifc->ifp->name, "dummy", 5))
134 l = &rid_lo_sorted_list;
135 else
136 l = &rid_all_sorted_list;
137
138 if (!router_id_find_node (l, ifc))
Stephen Hemmingerb6516822009-12-21 18:50:43 +0300139 listnode_add_sort (l, ifc);
hasso18a6dce2004-10-03 18:18:34 +0000140
141 router_id_get (&after);
142
143 if (prefix_same (&before, &after))
144 return;
145
paul1eb8ef22005-04-07 07:30:20 +0000146 for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client))
147 zsend_router_id_update (client, &after);
hasso18a6dce2004-10-03 18:18:34 +0000148}
149
150void
151router_id_del_address (struct connected *ifc)
152{
153 struct connected *c;
154 struct list *l;
155 struct prefix after;
156 struct prefix before;
157 struct listnode *node;
158 struct zserv *client;
159
160 if (router_id_bad_address (ifc))
161 return;
162
163 router_id_get (&before);
164
165 if (!strncmp (ifc->ifp->name, "lo", 2)
166 || !strncmp (ifc->ifp->name, "dummy", 5))
167 l = &rid_lo_sorted_list;
168 else
169 l = &rid_all_sorted_list;
170
171 if ((c = router_id_find_node (l, ifc)))
172 listnode_delete (l, c);
173
174 router_id_get (&after);
175
176 if (prefix_same (&before, &after))
177 return;
178
paul1eb8ef22005-04-07 07:30:20 +0000179 for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client))
180 zsend_router_id_update (client, &after);
hasso18a6dce2004-10-03 18:18:34 +0000181}
182
183void
184router_id_write (struct vty *vty)
185{
186 if (rid_user_assigned.u.prefix4.s_addr)
187 vty_out (vty, "router-id %s%s", inet_ntoa (rid_user_assigned.u.prefix4),
188 VTY_NEWLINE);
189}
190
191DEFUN (router_id,
192 router_id_cmd,
193 "router-id A.B.C.D",
194 "Manually set the router-id\n"
195 "IP address to use for router-id\n")
196{
197 struct prefix rid;
198
199 rid.u.prefix4.s_addr = inet_addr (argv[0]);
200 if (!rid.u.prefix4.s_addr)
201 return CMD_WARNING;
202
203 rid.prefixlen = 32;
204 rid.family = AF_INET;
205
206 router_id_set (&rid);
207
208 return CMD_SUCCESS;
209}
210
211DEFUN (no_router_id,
212 no_router_id_cmd,
213 "no router-id",
214 NO_STR
215 "Remove the manually configured router-id\n")
216{
217 struct prefix rid;
218
219 rid.u.prefix4.s_addr = 0;
220 rid.prefixlen = 0;
221 rid.family = AF_INET;
222
223 router_id_set (&rid);
224
225 return CMD_SUCCESS;
226}
227
paula1ac18c2005-06-28 17:17:12 +0000228static int
hasso18a6dce2004-10-03 18:18:34 +0000229router_id_cmp (void *a, void *b)
230{
Stephen Hemmingerb6516822009-12-21 18:50:43 +0300231 const struct connected *ifa = (const struct connected *)a;
232 const struct connected *ifb = (const struct connected *)b;
233 unsigned int A = ntohl(ifa->address->u.prefix4.s_addr);
234 unsigned int B = ntohl(ifb->address->u.prefix4.s_addr);
hasso18a6dce2004-10-03 18:18:34 +0000235
Stephen Hemmingerb6516822009-12-21 18:50:43 +0300236 return (int) (A - B);
hasso18a6dce2004-10-03 18:18:34 +0000237}
238
239void
240router_id_init (void)
241{
242 install_element (CONFIG_NODE, &router_id_cmd);
243 install_element (CONFIG_NODE, &no_router_id_cmd);
244
245 memset (&rid_all_sorted_list, 0, sizeof (rid_all_sorted_list));
246 memset (&rid_lo_sorted_list, 0, sizeof (rid_lo_sorted_list));
247 memset (&rid_user_assigned, 0, sizeof (rid_user_assigned));
248
249 rid_all_sorted_list.cmp = router_id_cmp;
250 rid_lo_sorted_list.cmp = router_id_cmp;
251
252 rid_user_assigned.family = AF_INET;
253 rid_user_assigned.prefixlen = 32;
254}