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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>