]> git.proxmox.com Git - mirror_frr.git/blob - zebra/router-id.c
Merge branch 'cmaster-next' into vtysh-grammar
[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 "zebra_memory.h"
34 #include "ioctl.h"
35 #include "connected.h"
36 #include "network.h"
37 #include "log.h"
38 #include "table.h"
39 #include "rib.h"
40 #include "vrf.h"
41
42 #include "zebra/zserv.h"
43 #include "zebra/zebra_vrf.h"
44 #include "zebra/router-id.h"
45 #include "zebra/redistribute.h"
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 if (ifc->address->family != AF_INET)
67 return 1;
68
69 /* non-redistributable addresses shouldn't be used for RIDs either */
70 if (!zebra_check_addr (ifc->address))
71 return 1;
72
73 return 0;
74 }
75
76 void
77 router_id_get (struct prefix *p, vrf_id_t vrf_id)
78 {
79 struct listnode *node;
80 struct connected *c;
81 struct zebra_vrf *zvrf = vrf_info_get (vrf_id);
82
83 p->u.prefix4.s_addr = 0;
84 p->family = AF_INET;
85 p->prefixlen = 32;
86
87 if (zvrf->rid_user_assigned.u.prefix4.s_addr)
88 p->u.prefix4.s_addr = zvrf->rid_user_assigned.u.prefix4.s_addr;
89 else if (!list_isempty (zvrf->rid_lo_sorted_list))
90 {
91 node = listtail (zvrf->rid_lo_sorted_list);
92 c = listgetdata (node);
93 p->u.prefix4.s_addr = c->address->u.prefix4.s_addr;
94 }
95 else if (!list_isempty (zvrf->rid_all_sorted_list))
96 {
97 node = listtail (zvrf->rid_all_sorted_list);
98 c = listgetdata (node);
99 p->u.prefix4.s_addr = c->address->u.prefix4.s_addr;
100 }
101 }
102
103 static void
104 router_id_set (struct prefix *p, vrf_id_t vrf_id)
105 {
106 struct prefix p2;
107 struct listnode *node;
108 struct zserv *client;
109 struct zebra_vrf *zvrf;
110
111 if (p->u.prefix4.s_addr == 0) /* unset */
112 {
113 zvrf = vrf_info_lookup (vrf_id);
114 if (! zvrf)
115 return;
116 }
117 else /* set */
118 zvrf = vrf_info_get (vrf_id);
119
120 zvrf->rid_user_assigned.u.prefix4.s_addr = p->u.prefix4.s_addr;
121
122 router_id_get (&p2, vrf_id);
123
124 for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client))
125 zsend_router_id_update (client, &p2, vrf_id);
126 }
127
128 void
129 router_id_add_address (struct connected *ifc)
130 {
131 struct list *l = NULL;
132 struct listnode *node;
133 struct prefix before;
134 struct prefix after;
135 struct zserv *client;
136 struct zebra_vrf *zvrf = vrf_info_get (ifc->ifp->vrf_id);
137
138 if (router_id_bad_address (ifc))
139 return;
140
141 router_id_get (&before, zvrf->vrf_id);
142
143 if (!strncmp (ifc->ifp->name, "lo", 2)
144 || !strncmp (ifc->ifp->name, "dummy", 5))
145 l = zvrf->rid_lo_sorted_list;
146 else
147 l = zvrf->rid_all_sorted_list;
148
149 if (!router_id_find_node (l, ifc))
150 listnode_add_sort (l, ifc);
151
152 router_id_get (&after, zvrf->vrf_id);
153
154 if (prefix_same (&before, &after))
155 return;
156
157 for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client))
158 zsend_router_id_update (client, &after, zvrf->vrf_id);
159 }
160
161 void
162 router_id_del_address (struct connected *ifc)
163 {
164 struct connected *c;
165 struct list *l;
166 struct prefix after;
167 struct prefix before;
168 struct listnode *node;
169 struct zserv *client;
170 struct zebra_vrf *zvrf = vrf_info_get (ifc->ifp->vrf_id);
171
172 if (router_id_bad_address (ifc))
173 return;
174
175 router_id_get (&before, zvrf->vrf_id);
176
177 if (!strncmp (ifc->ifp->name, "lo", 2)
178 || !strncmp (ifc->ifp->name, "dummy", 5))
179 l = zvrf->rid_lo_sorted_list;
180 else
181 l = zvrf->rid_all_sorted_list;
182
183 if ((c = router_id_find_node (l, ifc)))
184 listnode_delete (l, c);
185
186 router_id_get (&after, zvrf->vrf_id);
187
188 if (prefix_same (&before, &after))
189 return;
190
191 for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client))
192 zsend_router_id_update (client, &after, zvrf->vrf_id);
193 }
194
195 void
196 router_id_write (struct vty *vty)
197 {
198 struct zebra_vrf *zvrf;
199 vrf_iter_t iter;
200
201 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
202 if ((zvrf = vrf_iter2info (iter)) != NULL)
203 if (zvrf->rid_user_assigned.u.prefix4.s_addr)
204 {
205 if (zvrf->vrf_id == VRF_DEFAULT)
206 vty_out (vty, "router-id %s%s",
207 inet_ntoa (zvrf->rid_user_assigned.u.prefix4),
208 VTY_NEWLINE);
209 else
210 vty_out (vty, "router-id %s vrf %s%s",
211 inet_ntoa (zvrf->rid_user_assigned.u.prefix4),
212 zvrf->name,
213 VTY_NEWLINE);
214 }
215 }
216
217 DEFUN (router_id,
218 router_id_cmd,
219 "router-id A.B.C.D [vrf NAME]",
220 "Manually set the router-id\n"
221 "IP address to use for router-id\n"
222 VRF_CMD_HELP_STR)
223 {
224 int idx_ipv4 = 1;
225 int idx_name = 3;
226
227 struct prefix rid;
228 vrf_id_t vrf_id = VRF_DEFAULT;
229
230 rid.u.prefix4.s_addr = inet_addr (argv[idx_ipv4]->arg);
231 if (!rid.u.prefix4.s_addr)
232 return CMD_WARNING;
233
234 rid.prefixlen = 32;
235 rid.family = AF_INET;
236
237 if (argc > 2)
238 VRF_GET_ID (vrf_id, argv[idx_name]->arg);
239
240 router_id_set (&rid, vrf_id);
241
242 return CMD_SUCCESS;
243 }
244
245 DEFUN (no_router_id,
246 no_router_id_cmd,
247 "no router-id [A.B.C.D [vrf NAME]]",
248 NO_STR
249 "Remove the manually configured router-id\n"
250 "IP address to use for router-id\n"
251 VRF_CMD_HELP_STR)
252 {
253 int idx_name = 4;
254
255 struct prefix rid;
256 vrf_id_t vrf_id = VRF_DEFAULT;
257
258 rid.u.prefix4.s_addr = 0;
259 rid.prefixlen = 0;
260 rid.family = AF_INET;
261
262 if (argc > 3)
263 VRF_GET_ID (vrf_id, argv[idx_name]->arg);
264
265 router_id_set (&rid, vrf_id);
266
267 return CMD_SUCCESS;
268 }
269
270
271
272 static int
273 router_id_cmp (void *a, void *b)
274 {
275 const struct connected *ifa = (const struct connected *)a;
276 const struct connected *ifb = (const struct connected *)b;
277
278 return IPV4_ADDR_CMP(&ifa->address->u.prefix4.s_addr,&ifb->address->u.prefix4.s_addr);
279 }
280
281 void
282 router_id_cmd_init (void)
283 {
284 install_element (CONFIG_NODE, &router_id_cmd);
285 install_element (CONFIG_NODE, &no_router_id_cmd);
286 }
287
288 void
289 router_id_init (struct zebra_vrf *zvrf)
290 {
291 zvrf->rid_all_sorted_list = &zvrf->_rid_all_sorted_list;
292 zvrf->rid_lo_sorted_list = &zvrf->_rid_lo_sorted_list;
293
294 memset (zvrf->rid_all_sorted_list, 0, sizeof (zvrf->_rid_all_sorted_list));
295 memset (zvrf->rid_lo_sorted_list, 0, sizeof (zvrf->_rid_lo_sorted_list));
296 memset (&zvrf->rid_user_assigned, 0, sizeof (zvrf->rid_user_assigned));
297
298 zvrf->rid_all_sorted_list->cmp = router_id_cmp;
299 zvrf->rid_lo_sorted_list->cmp = router_id_cmp;
300
301 zvrf->rid_user_assigned.family = AF_INET;
302 zvrf->rid_user_assigned.prefixlen = 32;
303 }