summaryrefslogtreecommitdiff
path: root/zebra
diff options
context:
space:
mode:
Diffstat (limited to 'zebra')
-rw-r--r--zebra/ChangeLog12
-rw-r--r--zebra/Makefile.am4
-rw-r--r--zebra/main.c3
-rw-r--r--zebra/redistribute.c5
-rw-r--r--zebra/router-id.c265
-rw-r--r--zebra/router-id.h43
-rw-r--r--zebra/zserv.c68
-rw-r--r--zebra/zserv.h4
8 files changed, 400 insertions, 4 deletions
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 <jleu at mindspring.com>
+
+ * 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 <hasso at quagga.net>
* 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 <zebra.h>
+
+#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 <zebra.h>
+
+#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;