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