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