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