From 18a6dce6f83dd20caf1f36c8e840868ff0bf6dbd Mon Sep 17 00:00:00 2001 From: hasso Date: Sun, 3 Oct 2004 18:18:34 +0000 Subject: Common router id. --- zebra/ChangeLog | 12 +++ zebra/Makefile.am | 4 +- zebra/main.c | 3 +- zebra/redistribute.c | 5 + zebra/router-id.c | 265 +++++++++++++++++++++++++++++++++++++++++++++++++++ zebra/router-id.h | 43 +++++++++ zebra/zserv.c | 68 ++++++++++++- zebra/zserv.h | 4 + 8 files changed, 400 insertions(+), 4 deletions(-) create mode 100644 zebra/router-id.c create mode 100644 zebra/router-id.h (limited to 'zebra') diff --git a/zebra/ChangeLog b/zebra/ChangeLog index a62fb6cc..19d54312 100644 --- a/zebra/ChangeLog +++ b/zebra/ChangeLog @@ -1,3 +1,15 @@ +2004-10-03 James R. Leu + + * router-id.c, router-id.h: New files. Router id selection process. If + there is non 127.x.x.x address in loopack interface, lowest of them + is chosen. If there isn't, lowest from other interfaces addresses + are chosen. "router-id x.x.x.x" vty command to manual override. + * Makefile.am: Compile new files. + * main.c: Initialize router id. + * redistribute.c: Add interface addresses into router id selection + lists as they (dis)appear. + * zserv.c, zserv.h: Sending router id related messages to daemons. + 2004-09-26 Hasso Tepper * irdp_interface.c, irdp_main.c, irdp_packet.c, rt_netlink.c, diff --git a/zebra/Makefile.am b/zebra/Makefile.am index 87a994f1..f8a0f523 100644 --- a/zebra/Makefile.am +++ b/zebra/Makefile.am @@ -24,11 +24,11 @@ sbin_PROGRAMS = zebra zebra_SOURCES = \ zserv.c main.c interface.c connected.c zebra_rib.c \ redistribute.c debug.c rtadv.c zebra_snmp.c zebra_vty.c \ - irdp_main.c irdp_interface.c irdp_packet.c + irdp_main.c irdp_interface.c irdp_packet.c router-id.c noinst_HEADERS = \ connected.h ioctl.h rib.h rt.h zserv.h redistribute.h debug.h rtadv.h \ - interface.h ipforward.h irdp.h + interface.h ipforward.h irdp.h router-id.h zebra_LDADD = $(otherobj) $(LIBCAP) $(LIB_IPV6) ../lib/libzebra.la diff --git a/zebra/main.c b/zebra/main.c index 0c1a7ddb..e10755b9 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -35,7 +35,7 @@ #include "zebra/rib.h" #include "zebra/zserv.h" #include "zebra/debug.h" -#include "zebra/rib.h" +#include "zebra/router-id.h" #include "zebra/irdp.h" /* Zebra instance */ @@ -314,6 +314,7 @@ main (int argc, char **argv) rib_init (); zebra_if_init (); zebra_debug_init (); + router_id_init(); zebra_vty_init (); access_list_init (); rtadv_init (); diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 6dd3bd2a..100a824e 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -35,6 +35,7 @@ #include "zebra/zserv.h" #include "zebra/redistribute.h" #include "zebra/debug.h" +#include "zebra/router-id.h" /* master zebra server structure */ extern struct zebra_t zebrad; @@ -387,6 +388,8 @@ zebra_interface_address_add_update (struct interface *ifp, p->prefixlen, ifc->ifp->name); } + router_id_add_address(ifc); + for (node = listhead (zebrad.client_list); node; nextnode (node)) if ((client = getdata (node)) != NULL) if (client->ifinfo && CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) @@ -411,6 +414,8 @@ zebra_interface_address_delete_update (struct interface *ifp, p->prefixlen, ifc->ifp->name); } + router_id_del_address(ifc); + for (node = listhead (zebrad.client_list); node; nextnode (node)) if ((client = getdata (node)) != NULL) if (client->ifinfo && CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) diff --git a/zebra/router-id.c b/zebra/router-id.c new file mode 100644 index 00000000..3052e56a --- /dev/null +++ b/zebra/router-id.c @@ -0,0 +1,265 @@ +/* + * Router ID for zebra daemon. + * + * Copyright (C) 2004 James R. Leu + * + * This file is part of Quagga routing suite. + * + * Quagga is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * Quagga is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Zebra; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include + +#include "if.h" +#include "vty.h" +#include "sockunion.h" +#include "prefix.h" +#include "stream.h" +#include "command.h" +#include "memory.h" +#include "ioctl.h" +#include "connected.h" +#include "network.h" +#include "log.h" +#include "table.h" +#include "rib.h" + +#include "zebra/zserv.h" + +static struct list rid_all_sorted_list; +static struct list rid_lo_sorted_list; +static struct prefix rid_user_assigned; + +/* master zebra server structure */ +extern struct zebra_t zebrad; + +static struct connected * +router_id_find_node (struct list *l, struct connected *ifc) +{ + struct listnode *node; + struct connected *c; + + for (node = l->head; node; node = node->next) + { + c = (struct connected *) getdata (node); + if (prefix_same (ifc->address, c->address)) + return c; + } + return NULL; +} + +static int +router_id_bad_address (struct connected *ifc) +{ + struct prefix n; + + if (ifc->address->family != AF_INET) + return 1; + + n.u.prefix4.s_addr = htonl (INADDR_LOOPBACK); + n.prefixlen = 8; + n.family = AF_INET; + + if (prefix_match (&n, ifc->address)) + return 1; + + return 0; +} + +void +router_id_get (struct prefix *p) +{ + struct listnode *node; + struct connected *c; + + p->u.prefix4.s_addr = 0; + p->family = AF_INET; + p->prefixlen = 32; + + if (rid_user_assigned.u.prefix4.s_addr) + p->u.prefix4.s_addr = rid_user_assigned.u.prefix4.s_addr; + else if (!list_isempty (&rid_lo_sorted_list)) + { + node = listtail (&rid_lo_sorted_list); + c = getdata (node); + p->u.prefix4.s_addr = c->address->u.prefix4.s_addr; + } + else if (!list_isempty (&rid_all_sorted_list)) + { + node = listtail (&rid_all_sorted_list); + c = getdata (node); + p->u.prefix4.s_addr = c->address->u.prefix4.s_addr; + } +} + +static void +router_id_set (struct prefix *p) +{ + struct prefix p2; + struct listnode *node; + struct zserv *client; + + rid_user_assigned.u.prefix4.s_addr = p->u.prefix4.s_addr; + + router_id_get (&p2); + for (node = listhead (zebrad.client_list); node; nextnode (node)) + if ((client = getdata (node)) != NULL) + zsend_router_id_update (client, &p2); +} + +void +router_id_add_address (struct connected *ifc) +{ + struct list *l = NULL; + struct listnode *node; + struct prefix before; + struct prefix after; + struct zserv *client; + + if (router_id_bad_address (ifc)) + return; + + router_id_get (&before); + + if (!strncmp (ifc->ifp->name, "lo", 2) + || !strncmp (ifc->ifp->name, "dummy", 5)) + l = &rid_lo_sorted_list; + else + l = &rid_all_sorted_list; + + if (!router_id_find_node (l, ifc)) + listnode_add (l, ifc); + + router_id_get (&after); + + if (prefix_same (&before, &after)) + return; + + for (node = listhead (zebrad.client_list); node; nextnode (node)) + if ((client = getdata (node)) != NULL) + zsend_router_id_update (client, &after); +} + +void +router_id_del_address (struct connected *ifc) +{ + struct connected *c; + struct list *l; + struct prefix after; + struct prefix before; + struct listnode *node; + struct zserv *client; + + if (router_id_bad_address (ifc)) + return; + + router_id_get (&before); + + if (!strncmp (ifc->ifp->name, "lo", 2) + || !strncmp (ifc->ifp->name, "dummy", 5)) + l = &rid_lo_sorted_list; + else + l = &rid_all_sorted_list; + + if ((c = router_id_find_node (l, ifc))) + listnode_delete (l, c); + + router_id_get (&after); + + if (prefix_same (&before, &after)) + return; + + for (node = listhead (zebrad.client_list); node; nextnode (node)) + if ((client = getdata (node)) != NULL) + zsend_router_id_update (client, &after); +} + +void +router_id_write (struct vty *vty) +{ + if (rid_user_assigned.u.prefix4.s_addr) + vty_out (vty, "router-id %s%s", inet_ntoa (rid_user_assigned.u.prefix4), + VTY_NEWLINE); +} + +DEFUN (router_id, + router_id_cmd, + "router-id A.B.C.D", + "Manually set the router-id\n" + "IP address to use for router-id\n") +{ + struct prefix rid; + + rid.u.prefix4.s_addr = inet_addr (argv[0]); + if (!rid.u.prefix4.s_addr) + return CMD_WARNING; + + rid.prefixlen = 32; + rid.family = AF_INET; + + router_id_set (&rid); + + return CMD_SUCCESS; +} + +DEFUN (no_router_id, + no_router_id_cmd, + "no router-id", + NO_STR + "Remove the manually configured router-id\n") +{ + struct prefix rid; + + rid.u.prefix4.s_addr = 0; + rid.prefixlen = 0; + rid.family = AF_INET; + + router_id_set (&rid); + + return CMD_SUCCESS; +} + +int +router_id_cmp (void *a, void *b) +{ + unsigned int A, B; + + A = ((struct connected *) a)->address->u.prefix4.s_addr; + B = ((struct connected *) b)->address->u.prefix4.s_addr; + + if (A > B) + return 1; + else if (A < B) + return -1; + return 0; +} + +void +router_id_init (void) +{ + install_element (CONFIG_NODE, &router_id_cmd); + install_element (CONFIG_NODE, &no_router_id_cmd); + + memset (&rid_all_sorted_list, 0, sizeof (rid_all_sorted_list)); + memset (&rid_lo_sorted_list, 0, sizeof (rid_lo_sorted_list)); + memset (&rid_user_assigned, 0, sizeof (rid_user_assigned)); + + rid_all_sorted_list.cmp = router_id_cmp; + rid_lo_sorted_list.cmp = router_id_cmp; + + rid_user_assigned.family = AF_INET; + rid_user_assigned.prefixlen = 32; +} diff --git a/zebra/router-id.h b/zebra/router-id.h new file mode 100644 index 00000000..7f7a8c3b --- /dev/null +++ b/zebra/router-id.h @@ -0,0 +1,43 @@ +/* + * Router ID for zebra daemon. + * + * Copyright (C) 2004 James R. Leu + * + * This file is part of Quagga routing suite. + * + * Quagga is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * Quagga is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Zebra; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef _ROUTER_ID_H_ +#define _ROUTER_ID_H_ + +#include + +#include "memory.h" +#include "prefix.h" +#include "zclient.h" +#include "if.h" + +extern void router_id_add_address(struct connected *); +extern void router_id_del_address(struct connected *); +extern void router_id_init(void); +extern void router_id_write(struct vty *); +extern void router_id_get(struct prefix *); + +extern void zread_router_id_add(struct zserv *, u_short); +extern void zread_router_id_delete(struct zserv *, u_short); + +#endif diff --git a/zebra/zserv.c b/zebra/zserv.c index f57fe5c4..537b5429 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -36,6 +36,7 @@ #include "privs.h" #include "zebra/zserv.h" +#include "zebra/router-id.h" #include "zebra/redistribute.h" #include "zebra/debug.h" #include "zebra/ipforward.h" @@ -70,7 +71,10 @@ static char *zebra_command_str [] = "ZEBRA_IPV4_NEXTHOP_LOOKUP", "ZEBRA_IPV6_NEXTHOP_LOOKUP", "ZEBRA_IPV4_IMPORT_LOOKUP", - "ZEBRA_IPV6_IMPORT_LOOKUP" + "ZEBRA_IPV6_IMPORT_LOOKUP", + "ZEBRA_ROUTER_ID_ADD", + "ZEBRA_ROUTER_ID_DELETE", + "ZEBRA_ROUTER_ID_UPDATE" }; struct zebra_message_queue @@ -721,6 +725,38 @@ zsend_ipv4_import_lookup (struct zserv *client, struct prefix_ipv4 *p) return 0; } +/* Router-id is updated. Send ZEBRA_ROUTER_ID_ADD to client. */ +int +zsend_router_id_update (struct zserv *client, struct prefix *p) +{ + struct stream *s; + int blen; + + /* Check this client need interface information. */ + if (!client->ridinfo) + return -1; + + s = client->obuf; + stream_reset (s); + + /* Place holder for size. */ + stream_putw (s, 0); + + /* Message type. */ + stream_putc (s, ZEBRA_ROUTER_ID_UPDATE); + + /* Prefix information. */ + stream_putc (s, p->family); + blen = prefix_blen (p); + stream_put (s, &p->u.prefix, blen); + stream_putc (s, p->prefixlen); + + /* Write packet size. */ + stream_putw_at (s, 0, stream_get_endp (s)); + + return writen (client->sock, s->data, stream_get_endp (s)); +} + /* Register zebra server interface information. Send current all interface and address information. */ static void @@ -1122,6 +1158,27 @@ zread_ipv6_nexthop_lookup (struct zserv *client, u_short length) } #endif /* HAVE_IPV6 */ +/* Register zebra server router-id information. Send current router-id */ +void +zread_router_id_add (struct zserv *client, u_short length) +{ + struct prefix p; + + /* Router-id information is needed. */ + client->ridinfo = 1; + + router_id_get (&p); + + zsend_router_id_update (client,&p); +} + +/* Unregister zebra server router-id information. */ +void +zread_router_id_delete (struct zserv *client, u_short length) +{ + client->ridinfo = 0; +} + /* Close zebra client. */ static void zebra_client_close (struct zserv *client) @@ -1233,6 +1290,12 @@ zebra_client_read (struct thread *thread) switch (command) { + case ZEBRA_ROUTER_ID_ADD: + zread_router_id_add (client, length); + break; + case ZEBRA_ROUTER_ID_DELETE: + zread_router_id_delete (client, length); + break; case ZEBRA_INTERFACE_ADD: zread_interface_add (client, length); break; @@ -1676,6 +1739,9 @@ DEFUN (no_ipv6_forwarding, int config_write_forwarding (struct vty *vty) { + /* FIXME: Find better place for that. */ + router_id_write (vty); + if (ipforward ()) vty_out (vty, "ip forwarding%s", VTY_NEWLINE); #ifdef HAVE_IPV6 diff --git a/zebra/zserv.h b/zebra/zserv.h index ac5da1b2..620e24dd 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -56,6 +56,9 @@ struct zserv /* Interface information. */ u_char ifinfo; + + /* Router-id information. */ + u_char ridinfo; }; /* Zebra instance */ @@ -92,6 +95,7 @@ int zsend_interface_address (int, struct zserv *, struct interface *, struct connected *); int zsend_interface_update (int, struct zserv *, struct interface *); int zsend_route_multipath (int, struct zserv *, struct prefix *, struct rib *); +int zsend_router_id_update(struct zserv *, struct prefix *); extern pid_t pid; extern pid_t old_pid; -- cgit v1.2.1