blob: 6194582e069f4f60a1c30a3fc4528b11a89e2fc9 [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"
41
42static struct list rid_all_sorted_list;
43static struct list rid_lo_sorted_list;
44static struct prefix rid_user_assigned;
45
46/* master zebra server structure */
47extern struct zebra_t zebrad;
48
49static struct connected *
50router_id_find_node (struct list *l, struct connected *ifc)
51{
52 struct listnode *node;
53 struct connected *c;
54
paul1eb8ef22005-04-07 07:30:20 +000055 for (ALL_LIST_ELEMENTS_RO (l, node, c))
56 if (prefix_same (ifc->address, c->address))
57 return c;
58
hasso18a6dce2004-10-03 18:18:34 +000059 return NULL;
60}
61
62static int
63router_id_bad_address (struct connected *ifc)
64{
65 struct prefix n;
66
67 if (ifc->address->family != AF_INET)
68 return 1;
69
70 n.u.prefix4.s_addr = htonl (INADDR_LOOPBACK);
71 n.prefixlen = 8;
72 n.family = AF_INET;
73
74 if (prefix_match (&n, ifc->address))
75 return 1;
76
77 return 0;
78}
79
80void
81router_id_get (struct prefix *p)
82{
83 struct listnode *node;
84 struct connected *c;
85
86 p->u.prefix4.s_addr = 0;
87 p->family = AF_INET;
88 p->prefixlen = 32;
89
90 if (rid_user_assigned.u.prefix4.s_addr)
91 p->u.prefix4.s_addr = rid_user_assigned.u.prefix4.s_addr;
92 else if (!list_isempty (&rid_lo_sorted_list))
93 {
94 node = listtail (&rid_lo_sorted_list);
paul1eb8ef22005-04-07 07:30:20 +000095 c = listgetdata (node);
hasso18a6dce2004-10-03 18:18:34 +000096 p->u.prefix4.s_addr = c->address->u.prefix4.s_addr;
97 }
98 else if (!list_isempty (&rid_all_sorted_list))
99 {
100 node = listtail (&rid_all_sorted_list);
paul1eb8ef22005-04-07 07:30:20 +0000101 c = listgetdata (node);
hasso18a6dce2004-10-03 18:18:34 +0000102 p->u.prefix4.s_addr = c->address->u.prefix4.s_addr;
103 }
104}
105
106static void
107router_id_set (struct prefix *p)
108{
109 struct prefix p2;
110 struct listnode *node;
111 struct zserv *client;
112
113 rid_user_assigned.u.prefix4.s_addr = p->u.prefix4.s_addr;
114
115 router_id_get (&p2);
paul1eb8ef22005-04-07 07:30:20 +0000116
117 for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client))
118 zsend_router_id_update (client, &p2);
hasso18a6dce2004-10-03 18:18:34 +0000119}
120
121void
122router_id_add_address (struct connected *ifc)
123{
124 struct list *l = NULL;
125 struct listnode *node;
126 struct prefix before;
127 struct prefix after;
128 struct zserv *client;
129
130 if (router_id_bad_address (ifc))
131 return;
132
133 router_id_get (&before);
134
135 if (!strncmp (ifc->ifp->name, "lo", 2)
136 || !strncmp (ifc->ifp->name, "dummy", 5))
137 l = &rid_lo_sorted_list;
138 else
139 l = &rid_all_sorted_list;
140
141 if (!router_id_find_node (l, ifc))
142 listnode_add (l, ifc);
143
144 router_id_get (&after);
145
146 if (prefix_same (&before, &after))
147 return;
148
paul1eb8ef22005-04-07 07:30:20 +0000149 for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client))
150 zsend_router_id_update (client, &after);
hasso18a6dce2004-10-03 18:18:34 +0000151}
152
153void
154router_id_del_address (struct connected *ifc)
155{
156 struct connected *c;
157 struct list *l;
158 struct prefix after;
159 struct prefix before;
160 struct listnode *node;
161 struct zserv *client;
162
163 if (router_id_bad_address (ifc))
164 return;
165
166 router_id_get (&before);
167
168 if (!strncmp (ifc->ifp->name, "lo", 2)
169 || !strncmp (ifc->ifp->name, "dummy", 5))
170 l = &rid_lo_sorted_list;
171 else
172 l = &rid_all_sorted_list;
173
174 if ((c = router_id_find_node (l, ifc)))
175 listnode_delete (l, c);
176
177 router_id_get (&after);
178
179 if (prefix_same (&before, &after))
180 return;
181
paul1eb8ef22005-04-07 07:30:20 +0000182 for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client))
183 zsend_router_id_update (client, &after);
hasso18a6dce2004-10-03 18:18:34 +0000184}
185
186void
187router_id_write (struct vty *vty)
188{
189 if (rid_user_assigned.u.prefix4.s_addr)
190 vty_out (vty, "router-id %s%s", inet_ntoa (rid_user_assigned.u.prefix4),
191 VTY_NEWLINE);
192}
193
194DEFUN (router_id,
195 router_id_cmd,
196 "router-id A.B.C.D",
197 "Manually set the router-id\n"
198 "IP address to use for router-id\n")
199{
200 struct prefix rid;
201
202 rid.u.prefix4.s_addr = inet_addr (argv[0]);
203 if (!rid.u.prefix4.s_addr)
204 return CMD_WARNING;
205
206 rid.prefixlen = 32;
207 rid.family = AF_INET;
208
209 router_id_set (&rid);
210
211 return CMD_SUCCESS;
212}
213
214DEFUN (no_router_id,
215 no_router_id_cmd,
216 "no router-id",
217 NO_STR
218 "Remove the manually configured router-id\n")
219{
220 struct prefix rid;
221
222 rid.u.prefix4.s_addr = 0;
223 rid.prefixlen = 0;
224 rid.family = AF_INET;
225
226 router_id_set (&rid);
227
228 return CMD_SUCCESS;
229}
230
231int
232router_id_cmp (void *a, void *b)
233{
234 unsigned int A, B;
235
236 A = ((struct connected *) a)->address->u.prefix4.s_addr;
237 B = ((struct connected *) b)->address->u.prefix4.s_addr;
238
239 if (A > B)
240 return 1;
241 else if (A < B)
242 return -1;
243 return 0;
244}
245
246void
247router_id_init (void)
248{
249 install_element (CONFIG_NODE, &router_id_cmd);
250 install_element (CONFIG_NODE, &no_router_id_cmd);
251
252 memset (&rid_all_sorted_list, 0, sizeof (rid_all_sorted_list));
253 memset (&rid_lo_sorted_list, 0, sizeof (rid_lo_sorted_list));
254 memset (&rid_user_assigned, 0, sizeof (rid_user_assigned));
255
256 rid_all_sorted_list.cmp = router_id_cmp;
257 rid_lo_sorted_list.cmp = router_id_cmp;
258
259 rid_user_assigned.family = AF_INET;
260 rid_user_assigned.prefixlen = 32;
261}