summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2014-09-30 08:20:31 +0300
committerTimo Teräs <timo.teras@iki.fi>2014-09-30 08:20:45 +0300
commitae9537903c496dc50693c59b7b0751aee38ed012 (patch)
treeb1eddd7d5178eac802cb4018a0d75bd899133457
parent55bccfd7198195aef8f968691b53ec867cbe3989 (diff)
downloadquagga-old-nhrp.tar.bz2
quagga-old-nhrp.tar.xz
add nhrpd skeletonold-nhrp
-rw-r--r--Makefile.am6
-rw-r--r--SERVICES2
-rwxr-xr-xconfigure.ac18
-rw-r--r--lib/log.c5
-rw-r--r--lib/log.h3
-rw-r--r--nhrpd/Makefile.am18
-rw-r--r--nhrpd/nhrp_config.c342
-rw-r--r--nhrpd/nhrp_main.c230
-rw-r--r--nhrpd/nhrpd.h43
-rw-r--r--vtysh/Makefile.am2
-rw-r--r--vtysh/vtysh.c1
-rw-r--r--vtysh/vtysh.h5
-rw-r--r--zebra/client_main.c1
-rw-r--r--zebra/zebra_rib.c2
14 files changed, 668 insertions, 10 deletions
diff --git a/Makefile.am b/Makefile.am
index 6916470b..ff32ae1f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,10 +1,10 @@
## Process this file with automake to produce Makefile.in.
SUBDIRS = lib @ZEBRA@ @BGPD@ @RIPD@ @RIPNGD@ @OSPFD@ @OSPF6D@ @BABELD@ \
- @ISISD@ @WATCHQUAGGA@ @VTYSH@ @OSPFCLIENT@ @DOC@ m4 @pkgsrcdir@ \
- redhat @SOLARIS@ tests
+ @NHRPD@ @ISISD@ @WATCHQUAGGA@ @VTYSH@ @OSPFCLIENT@ @DOC@ \
+ m4 @pkgsrcdir@ redhat @SOLARIS@ tests
-DIST_SUBDIRS = lib zebra bgpd ripd ripngd ospfd ospf6d babeld \
+DIST_SUBDIRS = lib zebra bgpd ripd ripngd ospfd ospf6d babeld nhrpd \
isisd watchquagga vtysh ospfclient doc m4 pkgsrc redhat tests \
solaris
diff --git a/SERVICES b/SERVICES
index 9c3546bc..612a671a 100644
--- a/SERVICES
+++ b/SERVICES
@@ -17,3 +17,5 @@ bgpd 2605/tcp
ospf6d 2606/tcp
ospfapi 2607/tcp
isisd 2608/tcp
+babeld 2609/tcp
+nhrpd 2610/tcp
diff --git a/configure.ac b/configure.ac
index f1df482b..b4c572e7 100755
--- a/configure.ac
+++ b/configure.ac
@@ -216,6 +216,8 @@ AC_ARG_ENABLE(ospf6d,
[ --disable-ospf6d do not build ospf6d])
AC_ARG_ENABLE(babeld,
[ --disable-babeld do not build babeld])
+AC_ARG_ENABLE(nhrpd,
+[ --disable-nhrpd do not build nhrpd])
AC_ARG_ENABLE(watchquagga,
[ --disable-watchquagga do not build watchquagga])
AC_ARG_ENABLE(isisd,
@@ -1309,6 +1311,13 @@ else
fi
AM_CONDITIONAL(BABELD, test "x$BABELD" = "xbabeld")
+if test "${enable_nhrpd}" = "no";then
+ NHRPD=""
+else
+ NHRPD="nhrpd"
+fi
+AM_CONDITIONAL(NHRPD, test "x$NHRPD" = "xnhrpd")
+
if test "${enable_watchquagga}" = "no";then
WATCHQUAGGA=""
else
@@ -1371,6 +1380,7 @@ AC_SUBST(RIPNGD)
AC_SUBST(OSPFD)
AC_SUBST(OSPF6D)
AC_SUBST(BABELD)
+AC_SUBST(NHRPD)
AC_SUBST(WATCHQUAGGA)
AC_SUBST(ISISD)
AC_SUBST(SOLARIS)
@@ -1672,6 +1682,7 @@ AC_DEFINE_UNQUOTED(PATH_BGPD_PID, "$quagga_statedir/bgpd.pid",bgpd PID)
AC_DEFINE_UNQUOTED(PATH_OSPFD_PID, "$quagga_statedir/ospfd.pid",ospfd PID)
AC_DEFINE_UNQUOTED(PATH_OSPF6D_PID, "$quagga_statedir/ospf6d.pid",ospf6d PID)
AC_DEFINE_UNQUOTED(PATH_BABELD_PID, "$quagga_statedir/babeld.pid",babeld PID)
+AC_DEFINE_UNQUOTED(PATH_NHRPD_PID, "$quagga_statedir/nhrpd.pid",nhrpd PID)
AC_DEFINE_UNQUOTED(PATH_ISISD_PID, "$quagga_statedir/isisd.pid",isisd PID)
AC_DEFINE_UNQUOTED(PATH_WATCHQUAGGA_PID, "$quagga_statedir/watchquagga.pid",watchquagga PID)
AC_DEFINE_UNQUOTED(ZEBRA_SERV_PATH, "$quagga_statedir/zserv.api",zebra api socket)
@@ -1682,6 +1693,7 @@ AC_DEFINE_UNQUOTED(BGP_VTYSH_PATH, "$quagga_statedir/bgpd.vty",bgpd vty socket)
AC_DEFINE_UNQUOTED(OSPF_VTYSH_PATH, "$quagga_statedir/ospfd.vty",ospfd vty socket)
AC_DEFINE_UNQUOTED(OSPF6_VTYSH_PATH, "$quagga_statedir/ospf6d.vty",ospf6d vty socket)
AC_DEFINE_UNQUOTED(BABEL_VTYSH_PATH, "$quagga_statedir/babeld.vty",babeld vty socket)
+AC_DEFINE_UNQUOTED(NHRP_VTYSH_PATH, "$quagga_statedir/nhrpd.vty",nhrpd vty socket)
AC_DEFINE_UNQUOTED(ISIS_VTYSH_PATH, "$quagga_statedir/isisd.vty",isisd vty socket)
AC_DEFINE_UNQUOTED(DAEMON_VTY_DIR, "$quagga_statedir",daemon vty directory)
@@ -1706,9 +1718,9 @@ AC_MSG_RESULT($ac_cv_htonl_works)
AC_CONFIG_FILES([Makefile lib/Makefile zebra/Makefile ripd/Makefile
ripngd/Makefile bgpd/Makefile ospfd/Makefile watchquagga/Makefile
- ospf6d/Makefile isisd/Makefile babeld/Makefile vtysh/Makefile
- doc/Makefile ospfclient/Makefile tests/Makefile m4/Makefile
- tests/bgpd.tests/Makefile
+ ospf6d/Makefile isisd/Makefile babeld/Makefile nhrpd/Makefile
+ vtysh/Makefile doc/Makefile ospfclient/Makefile m4/Makefile
+ tests/Makefile tests/bgpd.tests/Makefile
tests/libzebra.tests/Makefile
redhat/Makefile
pkgsrc/Makefile
diff --git a/lib/log.c b/lib/log.c
index 04f8fab6..22a6ec02 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -52,6 +52,7 @@ const char *zlog_proto_names[] =
"OSPF6",
"ISIS",
"MASC",
+ "NHRP",
NULL,
};
@@ -978,6 +979,8 @@ proto_redistnum(int afi, const char *s)
return ZEBRA_ROUTE_BGP;
else if (strncmp (s, "ba", 2) == 0)
return ZEBRA_ROUTE_BABEL;
+ else if (strncmp (s, "n", 1) == 0)
+ return ZEBRA_ROUTE_NHRP;
}
if (afi == AFI_IP6)
{
@@ -997,6 +1000,8 @@ proto_redistnum(int afi, const char *s)
return ZEBRA_ROUTE_BGP;
else if (strncmp (s, "ba", 2) == 0)
return ZEBRA_ROUTE_BABEL;
+ else if (strncmp (s, "n", 1) == 0)
+ return ZEBRA_ROUTE_NHRP;
}
return -1;
}
diff --git a/lib/log.h b/lib/log.h
index f3b43ad1..526b91bd 100644
--- a/lib/log.h
+++ b/lib/log.h
@@ -53,7 +53,8 @@ typedef enum
ZLOG_BABEL,
ZLOG_OSPF6,
ZLOG_ISIS,
- ZLOG_MASC
+ ZLOG_MASC,
+ ZLOG_NHRP
} zlog_proto_t;
/* If maxlvl is set to ZLOG_DISABLED, then no messages will be sent
diff --git a/nhrpd/Makefile.am b/nhrpd/Makefile.am
new file mode 100644
index 00000000..d5e663e7
--- /dev/null
+++ b/nhrpd/Makefile.am
@@ -0,0 +1,18 @@
+## Process this file with automake to produce Makefile.in.
+
+INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib
+DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\"
+INSTALL_SDATA=@INSTALL@ -m 600
+
+AM_CFLAGS = $(PICFLAGS)
+AM_LDFLAGS = $(PILDFLAGS)
+
+sbin_PROGRAMS = nhrpd
+
+nhrpd_SOURCES = \
+ nhrp_config.c \
+ nhrp_main.c
+
+nhrpd_LDADD = ../lib/libzebra.la @LIBCAP@
+
+#dist_examples_DATA = nhrpd.conf.sample
diff --git a/nhrpd/nhrp_config.c b/nhrpd/nhrp_config.c
new file mode 100644
index 00000000..c7f931f2
--- /dev/null
+++ b/nhrpd/nhrp_config.c
@@ -0,0 +1,342 @@
+/*
+ * NHRP configuration.
+ * Copyright (c) 2014 Timo Teräs
+ *
+ * This file is free software: you may copy, redistribute and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This file 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* quagga's includes */
+#include "zebra.h"
+#include "command.h"
+#include "zclient.h"
+#include "stream.h"
+
+#include "nhrpd.h"
+
+static struct zclient *zclient;
+
+static struct cmd_node zebra_node = {
+ ZEBRA_NODE,
+ "%s(config-router)# ",
+ 1 /* vtysh? yes */
+};
+
+static struct cmd_node debug_node = {
+ DEBUG_NODE,
+ "",
+ 1
+};
+
+static const struct message debug_type[] = {
+ { NHRP_DEBUG_ALL, "all" },
+ { NHRP_DEBUG_COMMON, "common" },
+ { NHRP_DEBUG_KERNEL, "kernel" },
+ { NHRP_DEBUG_ROUTE, "route" },
+ { 0, NULL },
+};
+
+#if 0
+/* Zebra route add and delete treatment (ipv6). */
+static int
+babel_zebra_read_ipv6 (int command, struct zclient *zclient,
+ zebra_size_t length)
+{
+ struct stream *s;
+ struct zapi_ipv6 api;
+ unsigned long ifindex = -1;
+ struct in6_addr nexthop;
+ struct prefix_ipv6 prefix;
+
+ s = zclient->ibuf;
+ ifindex = 0;
+ memset (&nexthop, 0, sizeof (struct in6_addr));
+ memset (&api, 0, sizeof(struct zapi_ipv6));
+ memset (&prefix, 0, sizeof (struct prefix_ipv6));
+
+ /* Type, flags, message. */
+ api.type = stream_getc (s);
+ api.flags = stream_getc (s);
+ api.message = stream_getc (s);
+
+ /* IPv6 prefix. */
+ prefix.family = AF_INET6;
+ prefix.prefixlen = stream_getc (s);
+ stream_get (&prefix.prefix, s, PSIZE (prefix.prefixlen));
+
+ /* Nexthop, ifindex, distance, metric. */
+ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) {
+ api.nexthop_num = stream_getc (s);
+ stream_get (&nexthop, s, sizeof(nexthop));
+ }
+ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) {
+ api.ifindex_num = stream_getc (s);
+ ifindex = stream_getl (s);
+ }
+ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
+ api.distance = stream_getc (s);
+ else
+ api.distance = 0;
+ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
+ api.metric = stream_getl (s);
+ else
+ api.metric = 0;
+
+ if (command == ZEBRA_IPV6_ROUTE_ADD)
+ babel_ipv6_route_add(&api, &prefix, ifindex, &nexthop);
+ else
+ babel_ipv6_route_delete(&api, &prefix, ifindex);
+
+ return 0;
+}
+
+static int
+babel_zebra_read_ipv4 (int command, struct zclient *zclient,
+ zebra_size_t length)
+{
+ struct stream *s;
+ struct zapi_ipv4 api;
+ unsigned long ifindex = -1;
+ struct in_addr nexthop;
+ struct prefix_ipv4 prefix;
+
+ s = zclient->ibuf;
+ ifindex = 0;
+ memset (&nexthop, 0, sizeof (struct in_addr));
+ memset (&api, 0, sizeof(struct zapi_ipv4));
+ memset (&prefix, 0, sizeof (struct prefix_ipv4));
+
+ /* Type, flags, message. */
+ api.type = stream_getc (s);
+ api.flags = stream_getc (s);
+ api.message = stream_getc (s);
+
+ /* IPv6 prefix. */
+ prefix.family = AF_INET;
+ prefix.prefixlen = stream_getc (s);
+ stream_get (&prefix.prefix, s, PSIZE (prefix.prefixlen));
+
+ /* Nexthop, ifindex, distance, metric. */
+ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) {
+ api.nexthop_num = stream_getc (s);
+ stream_get (&nexthop, s, sizeof(nexthop));
+ }
+ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) {
+ api.ifindex_num = stream_getc (s);
+ ifindex = stream_getl (s);
+ }
+ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
+ api.distance = stream_getc (s);
+ else
+ api.distance = 0;
+ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
+ api.metric = stream_getl (s);
+ else
+ api.metric = 0;
+
+ if (command == ZEBRA_IPV6_ROUTE_ADD) {
+ babel_ipv4_route_add(&api, &prefix, ifindex, &nexthop);
+ } else {
+ babel_ipv4_route_delete(&api, &prefix, ifindex);
+ }
+
+ return 0;
+}
+
+/* [NHRP Command] */
+DEFUN(nhrp_redistribute_type, nhrp_redistribute_type_cmd,
+ "redistribute " QUAGGA_REDIST_STR_BABELD,
+ "Redistribute\n"
+ QUAGGA_REDIST_HELP_STR_BABELD)
+{
+ int type;
+
+ type = proto_redistnum(AFI_IP6, argv[0]);
+ if (type < 0)
+ type = proto_redistnum(AFI_IP, argv[0]);
+ if (type < 0) {
+ vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, type);
+ return CMD_SUCCESS;
+}
+
+/* [Babel Command] */
+DEFUN (no_babel_redistribute_type,
+ no_babel_redistribute_type_cmd,
+ "no redistribute " QUAGGA_REDIST_STR_BABELD,
+ NO_STR
+ "Redistribute\n"
+ QUAGGA_REDIST_HELP_STR_BABELD)
+{
+ int type;
+
+ type = proto_redistnum(AFI_IP6, argv[0]);
+
+ if (type < 0)
+ type = proto_redistnum(AFI_IP, argv[0]);
+
+ if (type < 0) {
+ vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ zclient_redistribute (ZEBRA_REDISTRIBUTE_DELETE, zclient, type);
+ /* perhaps should we remove xroutes having the same type... */
+ return CMD_SUCCESS;
+}
+#endif
+
+#ifndef NO_DEBUG
+
+DEFUN(show_debugging_nhrp, show_debugging_nhrp_cmd,
+ "show debugging nhrp",
+ SHOW_STR
+ "Debugging information\n"
+ "NHRP configuration\n")
+{
+ int i;
+
+ vty_out(vty, "NHRP debugging status:%s", VTY_NEWLINE);
+
+ for (i = 0; debug_type[i].str != NULL; i++) {
+ if (debug_type[i].key == NHRP_DEBUG_ALL)
+ continue;
+ if (!(debug_type[i].key & debug_flags))
+ continue;
+
+ vty_out(vty, " NHRP %s debugging is on%s",
+ debug_type[i].str, VTY_NEWLINE);
+ }
+
+ return CMD_SUCCESS;
+}
+
+static int toggle_debug(struct vty *vty, const char *type, int on_off)
+{
+ int i;
+
+ for (i = 0; debug_type[i].str != NULL; i++) {
+ if (strcmp(debug_type[i].str, type) != 0)
+ continue;
+ if (on_off)
+ debug_flags |= debug_type[i].key;
+ else
+ debug_flags &= ~debug_type[i].key;
+ return CMD_SUCCESS;
+ }
+ vty_out(vty, "Invalid type %s%s", type, VTY_NEWLINE);
+ return CMD_WARNING;
+}
+
+DEFUN (debug_nhrp, debug_nhrp_cmd,
+ "debug nhrp (common|kernel|route|all)",
+ "Enable debug messages for specific or all parts.\n"
+ "NHRP information\n"
+ "Common messages (default)\n"
+ "Kernel messages\n"
+ "Route messages\n"
+ "All messages\n")
+{
+ return toggle_debug(vty, argv[0], 1);
+}
+
+DEFUN (no_debug_nhrp, no_debug_nhrp_cmd,
+ "no debug nhrp (common|kernel|route|all)",
+ NO_STR
+ "Disable debug messages for specific or all parts.\n"
+ "NHRP information\n"
+ "Common messages (default)\n"
+ "Kernel messages\n"
+ "Route messages\n"
+ "All messages\n")
+{
+ return toggle_debug(vty, argv[0], 0);
+}
+
+#endif /* NO_DEBUG */
+
+static int nhrp_config_write(struct vty *vty)
+{
+ int lines = 0;
+
+#ifndef NO_DEBUG
+ if (debug_flags == NHRP_DEBUG_ALL) {
+ vty_out (vty, "debug nhrp all%s", VTY_NEWLINE);
+ lines++;
+ } else {
+ int i;
+
+ for (i = 0; debug_type[i].str != NULL; i++) {
+ if (debug_type[i].key == NHRP_DEBUG_ALL)
+ continue;
+ if (!(debug_flags & debug_type[i].key))
+ continue;
+ vty_out (vty, "debug nhrp %s%s", debug_type[i].str, VTY_NEWLINE);
+ lines++;
+ }
+ }
+#endif /* NO_DEBUG */
+
+ if (lines) {
+ vty_out (vty, "!%s", VTY_NEWLINE);
+ lines++;
+ }
+
+ if (!zclient->enable) {
+ vty_out (vty, "no router zebra%s", VTY_NEWLINE);
+ lines++;
+ } else if (!zclient->redist[ZEBRA_ROUTE_NHRP]) {
+ vty_out(vty, "router zebra%s", VTY_NEWLINE);
+ vty_out(vty, " no redistribute nhrp%s", VTY_NEWLINE);
+ lines += 2;
+ }
+
+ return lines;
+}
+
+void nhrp_zebra_init(void)
+{
+ zclient = zclient_new();
+#if 0
+ zclient->interface_add = babel_interface_add;
+ zclient->interface_delete = babel_interface_delete;
+ zclient->interface_up = babel_interface_up;
+ zclient->interface_down = babel_interface_down;
+ zclient->interface_address_add = babel_interface_address_add;
+ zclient->interface_address_delete = babel_interface_address_delete;
+ zclient->ipv4_route_add = babel_zebra_read_ipv4;
+ zclient->ipv4_route_delete = babel_zebra_read_ipv4;
+ zclient->ipv6_route_add = babel_zebra_read_ipv6;
+ zclient->ipv6_route_delete = babel_zebra_read_ipv6;
+#endif
+ zclient_init(zclient, ZEBRA_ROUTE_NHRP);
+
+ install_node(&zebra_node, nhrp_config_write);
+ install_default(ZEBRA_NODE);
+
+ install_element(VIEW_NODE, &show_debugging_nhrp_cmd);
+
+ install_element(ENABLE_NODE, &show_debugging_nhrp_cmd);
+ install_element(ENABLE_NODE, &debug_nhrp_cmd);
+ install_element(ENABLE_NODE, &no_debug_nhrp_cmd);
+
+ install_element(CONFIG_NODE, &debug_nhrp_cmd);
+ install_element(CONFIG_NODE, &no_debug_nhrp_cmd);
+}
+
+void nhrp_zebra_terminate(void)
+{
+ zclient_stop(zclient);
+}
diff --git a/nhrpd/nhrp_main.c b/nhrpd/nhrp_main.c
new file mode 100644
index 00000000..6552bb69
--- /dev/null
+++ b/nhrpd/nhrp_main.c
@@ -0,0 +1,230 @@
+/*
+ * NHRP daemon main functions.
+ * Copyright (c) 2014 Timo Teräs
+ *
+ * This file is free software: you may copy, redistribute and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This file 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <unistd.h>
+
+#include "zebra.h"
+#include "privs.h"
+#include "getopt.h"
+#include "thread.h"
+#include "sigevent.h"
+#include "version.h"
+#include "log.h"
+#include "memory.h"
+
+#include "nhrpd.h"
+
+unsigned int debug_flags = 0;
+
+struct thread_master *master;
+struct timeval current_time;
+static const char *pid_file = PATH_NHRPD_PID;
+static char config_default[] = SYSCONFDIR NHRP_DEFAULT_CONFIG;
+static char *config_file = NULL;
+static char *vty_addr = NULL;
+static int vty_port = NHRP_VTY_PORT;
+static int do_daemonise = 0;
+
+/* nhrpd options. */
+struct option longopts[] = {
+ { "daemon", no_argument, NULL, 'd'},
+ { "config_file", required_argument, NULL, 'f'},
+ { "pid_file", required_argument, NULL, 'i'},
+ { "socket", required_argument, NULL, 'z'},
+ { "help", no_argument, NULL, 'h'},
+ { "vty_addr", required_argument, NULL, 'A'},
+ { "vty_port", required_argument, NULL, 'P'},
+ { "user", required_argument, NULL, 'u'},
+ { "group", required_argument, NULL, 'g'},
+ { "version", no_argument, NULL, 'v'},
+ { 0 }
+};
+
+/* nhrpd privileges */
+static zebra_capabilities_t _caps_p [] = {
+ ZCAP_NET_RAW, ZCAP_BIND
+};
+
+static struct zebra_privs_t nhrpd_privs = {
+#ifdef QUAGGA_USER
+ .user = QUAGGA_USER,
+#endif
+#ifdef QUAGGA_GROUP
+ .group = QUAGGA_GROUP,
+#endif
+#ifdef VTY_GROUP
+ .vty_group = VTY_GROUP,
+#endif
+ .caps_p = _caps_p,
+ .cap_num_p = 2,
+ .cap_num_i = 0
+};
+
+static void usage(const char *progname, int status)
+{
+ if (status != 0)
+ fprintf(stderr, "Try `%s --help' for more information.\n", progname);
+ else
+ printf(
+"Usage : %s [OPTION...]\n\
+Daemon which manages NHRP protocol.\n\n\
+-d, --daemon Runs in daemon mode\n\
+-f, --config_file Set configuration file name\n\
+-i, --pid_file Set process identifier file name\n\
+-z, --socket Set path of zebra socket\n\
+-A, --vty_addr Set vty's bind address\n\
+-P, --vty_port Set vty's port number\n\
+-u, --user User to run as\n\
+-g, --group Group to run as\n\
+-v, --version Print program version\n\
+-h, --help Display this help and exit\n\
+\n\
+Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
+
+ exit(status);
+}
+
+static void parse_arguments(const char *progname, int argc, char **argv)
+{
+ int rc, opt;
+
+ while (1) {
+ opt = getopt_long(argc, argv, "df:i:z:hA:P:u:g:v", longopts, 0);
+ if(opt < 0) break;
+
+ switch (opt) {
+ case 0:
+ break;
+ case 'd':
+ do_daemonise = -1;
+ break;
+ case 'f':
+ config_file = optarg;
+ break;
+ case 'i':
+ pid_file = optarg;
+ break;
+ case 'z':
+ zclient_serv_path_set(optarg);
+ break;
+ case 'A':
+ vty_addr = optarg;
+ break;
+ case 'P':
+ vty_port = atoi (optarg);
+ if (vty_port <= 0 || vty_port > 0xffff)
+ vty_port = NHRP_VTY_PORT;
+ break;
+ case 'u':
+ nhrpd_privs.user = optarg;
+ break;
+ case 'g':
+ nhrpd_privs.group = optarg;
+ break;
+ case 'v':
+ print_version(progname);
+ exit(0);
+ break;
+ case 'h':
+ usage(progname, 0);
+ break;
+ default:
+ usage(progname, 1);
+ break;
+ }
+ }
+}
+
+static void nhrp_sigusr1(void)
+{
+ zlog_rotate(NULL);
+}
+
+static void nhrp_request_stop(void)
+{
+ debugf(NHRP_DEBUG_COMMON, "Exiting...");
+
+ nhrp_zebra_terminate();
+ /* memory_terminate(); */
+ vty_terminate();
+ cmd_terminate();
+ /* signal_terminate(); */
+ zprivs_terminate(&nhrpd_privs);
+
+ debugf(NHRP_DEBUG_COMMON, "Remove pid file.");
+ if (pid_file) unlink(pid_file);
+ debugf(NHRP_DEBUG_COMMON, "Done.");
+
+ closezlog(zlog_default);
+
+ exit(0);
+}
+
+static struct quagga_signal_t sighandlers[] = {
+ { .signal = SIGUSR1, .handler = &nhrp_sigusr1, },
+ { .signal = SIGINT, .handler = &nhrp_request_stop, },
+ { .signal = SIGTERM, .handler = &nhrp_request_stop, },
+};
+
+int main(int argc, char **argv)
+{
+ struct thread thread;
+ const char *progname;
+
+ /* Set umask before anything for security */
+ umask(0027);
+ progname = basename(argv[0]);
+ zlog_default = openzlog(progname, ZLOG_NHRP, LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
+ zlog_set_level(NULL, ZLOG_DEST_STDOUT, LOG_WARNING);
+
+ parse_arguments(progname, argc, argv);
+
+ /* Library inits. */
+ master = thread_master_create();
+ zprivs_init(&nhrpd_privs);
+ signal_init(master, array_size(sighandlers), sighandlers);
+ cmd_init(1);
+ vty_init(master);
+ memory_init();
+ nhrp_zebra_init();
+
+ if (do_daemonise && daemon(0, 0) < 0) {
+ zlog_err("daemonise: %s", safe_strerror(errno));
+ exit (1);
+ }
+
+ /* write pid file */
+ if (pid_output(pid_file) < 0) {
+ zlog_err("error while writing pidfile");
+ exit (1);
+ }
+
+ /* Get zebra configuration file. */
+ zlog_set_level(NULL, ZLOG_DEST_STDOUT, do_daemonise ? ZLOG_DISABLED : LOG_DEBUG);
+ vty_read_config(config_file, config_default);
+
+ /* Create VTY socket */
+ vty_serv_sock(vty_addr, vty_port, NHRP_VTYSH_PATH);
+ zlog_notice("nhrpd starting: vty@%d", vty_port);
+
+ /* Main loop */
+ while (thread_fetch(master, &thread))
+ thread_call(&thread);
+
+ return 0;
+}
diff --git a/nhrpd/nhrpd.h b/nhrpd/nhrpd.h
new file mode 100644
index 00000000..016ab34e
--- /dev/null
+++ b/nhrpd/nhrpd.h
@@ -0,0 +1,43 @@
+
+#define NHRP_DEBUG_COMMON (1 << 0)
+#define NHRP_DEBUG_KERNEL (1 << 1)
+#define NHRP_DEBUG_ROUTE (1 << 2)
+#define NHRP_DEBUG_ALL (0xFFFF)
+
+#define NHRP_VTY_PORT 2610
+#define NHRP_DEFAULT_CONFIG "nhrpd.conf"
+
+#if defined(__GNUC__) && (__GNUC__ >= 3)
+#define likely(_x) __builtin_expect(!!(_x), 1)
+#define unlikely(_x) __builtin_expect(!!(_x), 0)
+#else
+#define likely(_x) !!(_x)
+#define unlikely(_x) !!(_x)
+#endif
+
+extern unsigned int debug_flags;
+
+#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
+
+#define debugf(level, ...) \
+ do { \
+ if (unlikely(debug_flags & level)) \
+ zlog_debug(__VA_ARGS__); \
+ } while(0)
+
+#elif defined __GNUC__
+
+#define debugf(level, _args...) \
+ do { \
+ if (unlikely(debug_flags & level)) \
+ zlog_debug(_args); \
+ } while(0)
+
+#else
+
+static inline void debugf(int level, const char *format, ...) { }
+
+void nhrp_zebra_init(void);
+void nhrp_zebra_terminate(void);
+
+#endif
diff --git a/vtysh/Makefile.am b/vtysh/Makefile.am
index 5c325ec2..92feb27e 100644
--- a/vtysh/Makefile.am
+++ b/vtysh/Makefile.am
@@ -24,7 +24,7 @@ EXTRA_DIST = extract.pl
vtysh_cmd_FILES = $(top_srcdir)/bgpd/*.c $(top_srcdir)/isisd/*.c \
$(top_srcdir)/ospfd/*.c $(top_srcdir)/ospf6d/*.c \
$(top_srcdir)/ripd/*.c $(top_srcdir)/ripngd/*.c \
- $(top_srcdir)/babeld/*.c \
+ $(top_srcdir)/babeld/*.c $(top_srcdir)/nhrpd/*.c \
$(top_srcdir)/lib/keychain.c $(top_srcdir)/lib/routemap.c \
$(top_srcdir)/lib/filter.c $(top_srcdir)/lib/plist.c \
$(top_srcdir)/lib/distribute.c $(top_srcdir)/lib/if_rmap.c \
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index 89b9b257..6c98a611 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -59,6 +59,7 @@ struct vtysh_client
{ .fd = -1, .name = "bgpd", .flag = VTYSH_BGPD, .path = BGP_VTYSH_PATH},
{ .fd = -1, .name = "isisd", .flag = VTYSH_ISISD, .path = ISIS_VTYSH_PATH},
{ .fd = -1, .name = "babeld", .flag = VTYSH_BABELD, .path = BABEL_VTYSH_PATH},
+ { .fd = -1, .name = "nhrpd", .flag = VTYSH_NHRPD, .path = NHRP_VTYSH_PATH},
};
diff --git a/vtysh/vtysh.h b/vtysh/vtysh.h
index 3cc7bafe..bf120c51 100644
--- a/vtysh/vtysh.h
+++ b/vtysh/vtysh.h
@@ -29,8 +29,9 @@
#define VTYSH_OSPF6D 0x10
#define VTYSH_BGPD 0x20
#define VTYSH_ISISD 0x40
-#define VTYSH_BABELD 0x80
-#define VTYSH_ALL VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ISISD|VTYSH_BABELD
+#define VTYSH_BABELD 0x80
+#define VTYSH_NHRPD 0x100
+#define VTYSH_ALL VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ISISD|VTYSH_BABELD|VTYSH_NHRPD
#define VTYSH_RMAP VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_BABELD
#define VTYSH_INTERFACE VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_ISISD|VTYSH_BABELD
diff --git a/zebra/client_main.c b/zebra/client_main.c
index 8b95907b..6fe86c76 100644
--- a/zebra/client_main.c
+++ b/zebra/client_main.c
@@ -119,6 +119,7 @@ struct zebra_info
{ "ospf", ZEBRA_ROUTE_OSPF },
{ "ospf6", ZEBRA_ROUTE_OSPF6 },
{ "bgp", ZEBRA_ROUTE_BGP },
+ { "nhrp", ZEBRA_ROUTE_NHRP },
{ NULL, 0 }
};
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index dc7e1ca1..4f7ff234 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -69,6 +69,7 @@ static const struct
[ZEBRA_ROUTE_ISIS] = {ZEBRA_ROUTE_ISIS, 115},
[ZEBRA_ROUTE_BGP] = {ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */},
[ZEBRA_ROUTE_BABEL] = {ZEBRA_ROUTE_BABEL, 95},
+ [ZEBRA_ROUTE_NHRP] = {ZEBRA_ROUTE_NHRP, 10},
/* no entry/default: 150 */
};
@@ -1510,6 +1511,7 @@ static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = {
[ZEBRA_ROUTE_BGP] = 3,
[ZEBRA_ROUTE_HSLS] = 4,
[ZEBRA_ROUTE_BABEL] = 2,
+ [ZEBRA_ROUTE_NHRP] = 2,
};
/* Look into the RN and queue it into one or more priority queues,