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