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