]> git.proxmox.com Git - mirror_frr.git/blob - zebra/router-id.c
2005-06-28 Paul Jakma <paul.jakma@sun.com>
[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 #include "zebra/router-id.h"
42
43 static struct list rid_all_sorted_list;
44 static struct list rid_lo_sorted_list;
45 static struct prefix rid_user_assigned;
46
47 /* master zebra server structure */
48 extern struct zebra_t zebrad;
49
50 static struct connected *
51 router_id_find_node (struct list *l, struct connected *ifc)
52 {
53 struct listnode *node;
54 struct connected *c;
55
56 for (ALL_LIST_ELEMENTS_RO (l, node, c))
57 if (prefix_same (ifc->address, c->address))
58 return c;
59
60 return NULL;
61 }
62
63 static int
64 router_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
81 void
82 router_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);
96 c = listgetdata (node);
97 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);
102 c = listgetdata (node);
103 p->u.prefix4.s_addr = c->address->u.prefix4.s_addr;
104 }
105 }
106
107 static void
108 router_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);
117
118 for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client))
119 zsend_router_id_update (client, &p2);
120 }
121
122 void
123 router_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
150 for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client))
151 zsend_router_id_update (client, &after);
152 }
153
154 void
155 router_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
183 for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client))
184 zsend_router_id_update (client, &after);
185 }
186
187 void
188 router_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
195 DEFUN (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
215 DEFUN (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
232 static int
233 router_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
247 void
248 router_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 }