summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am15
-rw-r--r--bgpd/Makefile.am2
-rw-r--r--bgpd/bgp_main.c36
-rw-r--r--bgpd/bgp_network.c25
-rwxr-xr-xconfigure.ac242
-rwxr-xr-xconfigure.in381
-rw-r--r--lib/Makefile.am8
-rw-r--r--lib/memory.h2
-rw-r--r--lib/privs.c377
-rw-r--r--lib/privs.h91
-rw-r--r--lib/vty.c58
-rw-r--r--lib/zebra.h6
-rw-r--r--ospf6d/Makefile.am2
-rw-r--r--ospf6d/ospf6_main.c42
-rw-r--r--ospf6d/ospf6_network.c9
-rw-r--r--ospfclient/Makefile.am21
-rw-r--r--ospfclient/ospfclient.c333
-rw-r--r--ospfd/Makefile.am20
-rw-r--r--ospfd/ospf_main.c46
-rw-r--r--ospfd/ospf_network.c12
-rw-r--r--ospfd/ospfd.c55
-rw-r--r--redhat/zebra.pam26
-rw-r--r--redhat/zebra.spec.in372
-rw-r--r--ripd/Makefile.am2
-rw-r--r--ripd/rip_interface.c118
-rw-r--r--ripd/rip_main.c37
-rw-r--r--ripd/ripd.c147
-rw-r--r--ripngd/Makefile.am6
-rw-r--r--ripngd/ripng_main.c47
-rw-r--r--ripngd/ripngd.c26
-rw-r--r--vtysh/Makefile.am8
-rw-r--r--zebra/Makefile.am3
-rw-r--r--zebra/ioctl.c17
-rw-r--r--zebra/ipforward_proc.c34
-rw-r--r--zebra/ipforward_sysctl.c43
-rw-r--r--zebra/main.c51
-rw-r--r--zebra/rt_netlink.c226
-rw-r--r--zebra/rt_socket.c53
-rw-r--r--zebra/rtadv.c11
-rw-r--r--zebra/zserv.c13
40 files changed, 2547 insertions, 476 deletions
diff --git a/Makefile.am b/Makefile.am
index 72a09dcf..0c7b1fbf 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,16 +1,19 @@
## Process this file with automake to produce Makefile.in.
-SUBDIRS = lib @ZEBRA@ @BGPD@ @RIPD@ @RIPNGD@ @OSPFD@ @OSPF6D@ @VTYSH@ doc
+SUBDIRS = lib @ZEBRA@ @BGPD@ @RIPD@ @RIPNGD@ @OSPFD@ @OSPF6D@ \
+ @VTYSH@ @OSPFCLIENT@ doc
+
+DIST_SUBDIRS = lib zebra bgpd ripd ripngd ospfd ospf6d vtysh \
+ ospfclient doc
EXTRA_DIST = aclocal.m4 SERVICES TODO REPORTING-BUGS vtysh/Makefile.in \
- vtysh/Makefile.am update-autotools
+ vtysh/Makefile.am update-autotools doc/mpls
dist-hook:
mkdir $(distdir)/tools
cp -p $(srcdir)/tools/*.pl $(distdir)/tools
cp -p $(srcdir)/tools/*.el $(distdir)/tools
cp -p $(srcdir)/tools/*.cgi $(distdir)/tools
- mkdir $(distdir)/init
- mkdir $(distdir)/init/redhat
- cp -p $(srcdir)/init/redhat/*.init $(distdir)/init/redhat
- cp -p $(srcdir)/init/redhat/zebra.* $(distdir)/init/redhat
+ cp -p $(srcdir)/redhat/*.init $(distdir)/redhat
+ cp -p $(srcdir)/redhat/zebra.* $(distdir)/redhat
+ rm -rf `find $(distdir)/doc -type d -name CVS`
diff --git a/bgpd/Makefile.am b/bgpd/Makefile.am
index 7f739f6e..0e549cc0 100644
--- a/bgpd/Makefile.am
+++ b/bgpd/Makefile.am
@@ -24,7 +24,7 @@ noinst_HEADERS = \
bgpd_SOURCES = \
bgp_main.c $(libbgp_a_SOURCES)
-bgpd_LDADD = ../lib/libzebra.a
+bgpd_LDADD = ../lib/libzebra.a @LIBCAP@
sysconf_DATA = bgpd.conf.sample bgpd.conf.sample2
diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c
index 7fc68fa7..60a7ee76 100644
--- a/bgpd/bgp_main.c
+++ b/bgpd/bgp_main.c
@@ -29,6 +29,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "memory.h"
#include "prefix.h"
#include "log.h"
+#include "privs.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_attr.h"
@@ -45,6 +46,7 @@ struct option longopts[] =
{ "vty_port", required_argument, NULL, 'P'},
{ "retain", no_argument, NULL, 'r'},
{ "no_kernel", no_argument, NULL, 'n'},
+ { "user", required_argument, NULL, 'u'},
{ "version", no_argument, NULL, 'v'},
{ "help", no_argument, NULL, 'h'},
{ 0 }
@@ -70,6 +72,21 @@ char *pid_file = PATH_BGPD_PID;
int vty_port = BGP_VTY_PORT;
char *vty_addr = NULL;
+/* privileges */
+struct zebra_privs_t bgpd_privs =
+{
+ .caps_p =
+ {
+ ZCAP_BIND
+ },
+ .cap_num_p = 1,
+ .cap_num_i = 0,
+#if defined(ZEBRA_USER) && defined(ZEBRA_GROUP)
+ .user = ZEBRA_USER,
+ .group = ZEBRA_GROUP
+#endif
+};
+
/* Help information display. */
static void
usage (char *progname, int status)
@@ -89,6 +106,7 @@ redistribution between different routing protocols.\n\n\
-P, --vty_port Set vty's port number\n\
-r, --retain When program terminates, retain added route by bgpd.\n\
-n, --no_kernel Do not install route to kernel.\n\
+-u, --user User and group to run as\n\
-v, --version Print program version\n\
-h, --help Display this help and exit\n\
\n\
@@ -113,7 +131,7 @@ sighup (int sig)
vty_read_config (config_file, config_current, config_default);
/* Create VTY's socket */
- vty_serv_sock (vty_addr, vty_port ? vty_port : BGP_VTY_PORT, BGP_VTYSH_PATH);
+ vty_serv_sock (vty_addr, vty_port, BGP_VTYSH_PATH);
/* Try to return to normal operation. */
}
@@ -197,7 +215,7 @@ main (int argc, char **argv)
/* Command line argument treatment. */
while (1)
{
- opt = getopt_long (argc, argv, "df:hp:A:P:rnv", longopts, 0);
+ opt = getopt_long (argc, argv, "df:hp:A:P:rnu:v", longopts, 0);
if (opt == EOF)
break;
@@ -222,7 +240,15 @@ main (int argc, char **argv)
vty_addr = optarg;
break;
case 'P':
- vty_port = atoi (optarg);
+ /* Deal with atoi() returning 0 on failure, and bgpd not
+ listening on bgp port... */
+ if (strcmp(optarg, "0") == 0)
+ {
+ vty_port = 0;
+ break;
+ }
+ vty_port = atoi (optarg);
+ vty_port = (vty_port ? vty_port : BGP_VTY_PORT);
break;
case 'r':
retain_mode = 1;
@@ -230,6 +256,9 @@ main (int argc, char **argv)
case 'n':
bgp_option_set (BGP_OPT_NO_FIB);
break;
+ case 'u':
+ bgpd_privs.user = bgpd_privs.group = optarg;
+ break;
case 'v':
print_version (progname);
exit (0);
@@ -249,6 +278,7 @@ main (int argc, char **argv)
/* Initializations. */
srand (time (NULL));
signal_init ();
+ zprivs_init (&bgpd_privs);
cmd_init (1);
vty_init ();
memory_init ();
diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c
index 40e9cdb3..019b78b7 100644
--- a/bgpd/bgp_network.c
+++ b/bgpd/bgp_network.c
@@ -27,12 +27,16 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "if.h"
#include "prefix.h"
#include "command.h"
+#include "privs.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_fsm.h"
#include "bgpd/bgp_attr.h"
#include "bgpd/bgp_debug.h"
#include "bgpd/bgp_network.h"
+
+extern struct zebra_privs_t bgpd_privs;
+
/* Accept bgp connection. */
static int
@@ -153,9 +157,16 @@ bgp_bind_address (int sock, struct in_addr *addr)
#endif /* HAVE_SIN_LEN */
memcpy (&local.sin_addr, addr, sizeof (struct in_addr));
+ if ( bgpd_privs.change (ZPRIVS_RAISE) )
+ zlog_err ("bgp_bind_address: could not raise privs");
+
ret = bind (sock, (struct sockaddr *)&local, sizeof (struct sockaddr_in));
if (ret < 0)
;
+
+ if (bgpd_privs.change (ZPRIVS_LOWER) )
+ zlog_err ("bgp_bind_address: could not lower privs");
+
return 0;
}
@@ -306,6 +317,9 @@ bgp_socket (struct bgp *bgp, unsigned short port)
sockopt_reuseaddr (sock);
sockopt_reuseport (sock);
+
+ if (bgpd_privs.change (ZPRIVS_RAISE) )
+ zlog_err ("bgp_socket: could not raise privs");
ret = bind (sock, ainfo->ai_addr, ainfo->ai_addrlen);
if (ret < 0)
@@ -314,6 +328,10 @@ bgp_socket (struct bgp *bgp, unsigned short port)
close (sock);
continue;
}
+
+ if (bgpd_privs.change (ZPRIVS_LOWER) )
+ zlog_err ("bgp_bind_address: could not lower privs");
+
ret = listen (sock, 3);
if (ret < 0)
{
@@ -359,6 +377,9 @@ bgp_socket (struct bgp *bgp, unsigned short port)
sin.sin_len = socklen;
#endif /* HAVE_SIN_LEN */
+ if ( bgpd_privs.change (ZPRIVS_RAISE) )
+ zlog_err ("bgp_socket: could not raise privs");
+
ret = bind (sock, (struct sockaddr *) &sin, socklen);
if (ret < 0)
{
@@ -366,6 +387,10 @@ bgp_socket (struct bgp *bgp, unsigned short port)
close (sock);
return ret;
}
+
+ if (bgpd_privs.change (ZPRIVS_LOWER) )
+ zlog_err ("bgp_socket: could not lower privs");
+
ret = listen (sock, 3);
if (ret < 0)
{
diff --git a/configure.ac b/configure.ac
index 1adc8a7f..fd264b7a 100755
--- a/configure.ac
+++ b/configure.ac
@@ -4,7 +4,7 @@
##
## Copyright (c) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
##
-AC_PREREQ(2.53)
+AC_PREREQ(2.13)
AC_INIT(lib/zebra.h)
AM_INIT_AUTOMAKE(zebra, 0.94)
@@ -87,11 +87,23 @@ dnl Temporary option until OSPF NSSA implementation complete
AC_ARG_ENABLE(nssa,
[ --enable-nssa enable OSPF NSSA option])
AC_ARG_ENABLE(opaque-lsa,
-[ --enable-opaque-lsa enable OSPF Opaque-LSA support (RFC2370)])
+[ --enable-opaque-lsa enable OSPF Opaque-LSA with OSPFAPI support (RFC2370)])
+AC_ARG_ENABLE(ospfapi,
+[ --disable-ospfapi do not build OSPFAPI to access the OSPF LSA Database,
+ (this is the default if --enable-opaque-lsa is not set)])
+AC_ARG_ENABLE(ospfclient,
+[ --disable-ospfclient do not build OSPFAPI client for OSPFAPI,
+ (this is the default if --disable-ospfapi is set)])
AC_ARG_ENABLE(ospf-te,
[ --enable-ospf-te enable Traffic Engineering Extension to OSPF])
AC_ARG_ENABLE(multipath,
[ --enable-multipath=ARG enable multipath function, ARG must be digit])
+AC_ARG_ENABLE(zebra_user,
+[ --enable-user=ARG user to run zebra suite as (default zebra)])
+AC_ARG_ENABLE(zebra_group,
+[ --enable-group=ARG group to run zebra suite as (default zebra)])
+AC_ARG_ENABLE(vty_group,
+[ --enable-vty-group=ARG set vty sockets to have specified group as owner])
dnl AC_ARG_ENABLE(rtadv,
dnl [ --enable-rtadv enable IPV6 router advertisment option])
@@ -127,6 +139,27 @@ dnl if test "${enable_rtadv}" = "yes"; then
dnl AC_DEFINE(HAVE_RTADV)
dnl fi
+if test "${enable_user}" = "yes" ; then
+ enable_user="zebra"
+elif test "${enable_user}" = "no"; then
+ enable_user="root"
+fi
+AC_DEFINE_UNQUOTED(ZEBRA_USER, "${enable_user}", Zebra User)
+
+if test "${enable_group}" = "yes" ; then
+ enable_group="zebra"
+elif test "${enable_group}" = "no"; then
+ enable_group="root"
+fi
+AC_DEFINE_UNQUOTED(ZEBRA_GROUP, "${enable_group}", Zebra Group)
+
+if test x"${enable_vty_group}" = x"yes" ; then
+ AC_MSG_ERROR([--enable-vty-group requires a group as argument])
+fi
+if test x"${enable_vty_group}" != x"no"; then
+ AC_DEFINE_UNQUOTED(VTY_GROUP, "${enable_vty_group}", VTY Sockets Group)
+fi
+
changequote(, )dnl
MULTIPATH_NUM=1
@@ -209,7 +242,11 @@ case "${enable_vtysh}" in
if test $ac_cv_header_readline_history_h = no;then
AC_MSG_ERROR([readline is too old to have readline/history.h, please update to the latest readline library.])
fi
- ;;
+ AC_CHECK_LIB(readline, rl_completion_matches)
+ if test $ac_cv_lib_readline_rl_completion_matches = no; then
+ AC_DEFINE(rl_completion_matches,completion_matches,Old readline)
+ fi
+ ;;
"no" ) VTYSH="";;
* ) ;;
esac
@@ -218,6 +255,25 @@ dnl ----------
dnl PAM module
dnl ----------
if test "$with_libpam" = "yes"; then
+ AC_CHECK_HEADER(security/pam_misc.h)
+ if test "$ac_cv_header_security_pam_misc_h" = yes; then
+ AC_DEFINE(HAVE_PAM_MISC_H,,Have pam_misc.h)
+ AC_DEFINE(PAM_CONV_FUNC,misc_conv,Have misc_conv)
+ pam_conv_func="misc_conv"
+ fi
+ AC_CHECK_HEADER(security/openpam.h)
+ if test "$ac_cv_header_security_openpam_h" = yes; then
+ AC_DEFINE(HAVE_OPENPAM_H,,Have openpam.h)
+ AC_DEFINE(PAM_CONV_FUNC,openpam_ttyconv,Have openpam_ttyconv)
+ pam_conv_func="openpam_ttyconv"
+ fi
+ if test -z "$ac_cv_header_security_pam_misc_h$ac_cv_header_security_openpam_h" ; then
+ AC_MSG_WARN([*** pam support will not be built ***])
+ with_libpam="no"
+ fi
+fi
+
+if test "$with_libpam" = "yes"; then
dnl took this test from proftpd's configure.in and suited to our needs
dnl -------------------------------------------------------------------------
dnl
@@ -226,7 +282,7 @@ dnl of the PAM library. Prior to 0.72 release, the Linux PAM shared library
dnl omitted requiring libdl linking information. PAM-0.72 or better ships
dnl with RedHat 6.2 and Debian 2.2 or better.
AC_CHECK_LIB(pam, pam_start,
- [AC_CHECK_LIB(pam, misc_conv,
+ [AC_CHECK_LIB(pam, $pam_conv_func,
[AC_DEFINE(USE_PAM,,Use PAM for authentication)
LIBPAM="-lpam"],
[AC_DEFINE(USE_PAM,,Use PAM for authentication)
@@ -235,7 +291,7 @@ AC_CHECK_LIB(pam, pam_start,
],
[AC_CHECK_LIB(pam, pam_end,
- [AC_CHECK_LIB(pam, misc_conv,
+ [AC_CHECK_LIB(pam, $pam_conv_func,
[AC_DEFINE(USE_PAM)
LIBPAM="-lpam -ldl"],
[AC_DEFINE(USE_PAM)
@@ -534,6 +590,18 @@ else
OSPFD="ospfd"
fi
+OSPFCLIENT=""
+if test "${enable_opaque_lsa}" = "yes"; then
+ if test "${enable_ospfapi}" != "no";then
+ AC_DEFINE(SUPPORT_OSPF_API,,OSPFAPI)
+
+ if test "${enable_ospfclient}" != "no";then
+ OSPFCLIENT="ospfclient"
+ fi
+ fi
+
+fi
+
case "${enable_ripngd}" in
"yes") RIPNGD="ripngd";;
"no" ) RIPNGD="";;
@@ -559,6 +627,8 @@ AC_SUBST(OSPF6D)
AC_SUBST(VTYSH)
AC_SUBST(INCLUDES)
AC_SUBST(CURSES)
+AC_SUBST(OSPFCLIENT)
+AC_SUBST(OSPFAPI)
AC_CHECK_LIB(c, inet_ntop, [AC_DEFINE(HAVE_INET_NTOP,,inet_ntop)])
AC_CHECK_LIB(c, inet_pton, [AC_DEFINE(HAVE_INET_PTON,,inet_pton)])
AC_CHECK_LIB(crypt, crypt)
@@ -587,33 +657,66 @@ dnl check SNMP library
dnl ------------------
if test "${enable_snmp}" = "yes";then
dnl AC_CHECK_LIB(snmp, asn_parse_int, HAVE_SNMP=yes)
- old_libs="${LIBS}"
- LIBS="-L/usr/local/lib"
- unset ac_cv_lib_snmp_asn_parse_int
- AC_CHECK_LIB(snmp, asn_parse_int, HAVE_SNMP=yes, )
if test "${HAVE_SNMP}" = ""; then
+ old_libs="${LIBS}"
+ LIBS="-L/usr/lib"
unset ac_cv_lib_snmp_asn_parse_int
- AC_CHECK_LIB(crypto, main, [NEED_CRYPTO=yes ], )
- if test "${NEED_CRYPTO}" = ""; then
- AC_CHECK_LIB(snmp, asn_parse_int, [HAVE_SNMP=yes; NEED_CRYPTO=yes ],)
- else
- AC_CHECK_LIB(snmp, asn_parse_int, [HAVE_SNMP=yes; NEED_CRYPTO=yes;LIBS="$LIBS -lcrypto" ],,"-lcrypto")
- fi
+ AC_CHECK_LIB(crypto, main, NEED_CRYPTO=yes, )
+ if test "${NEED_CRYPTO}" = ""; then
+ AC_CHECK_LIB(netsnmp, asn_parse_int, [HAVE_NETSNMP=yes; HAVE_SNMP=yes ])
+ else
+ AC_CHECK_LIB(netsnmp, asn_parse_int, [HAVE_NETSNMP=yes; HAVE_SNMP=yes; NEED_CRYPTO=yes;LIBS="$LIBS -lcrypto" ],,"-lcrypto")
+ fi
+ LIBS="${old_libs}"
+ fi
+ if test "${HAVE_SNMP}" = ""; then
+ old_libs="${LIBS}"
+ LIBS="-L/usr/lib"
+ unset ac_cv_lib_snmp_asn_parse_int
+ AC_CHECK_LIB(snmp, asn_parse_int, HAVE_SNMP=yes, )
+ if test "${HAVE_SNMP}" = ""; then
+ unset ac_cv_lib_snmp_asn_parse_int
+ AC_CHECK_LIB(crypto, main, NEED_CRYPTO=yes, )
+ if test "${NEED_CRYPTO}" = "yes"; then
+ AC_CHECK_LIB(snmp, asn_parse_int, [HAVE_SNMP=yes; NEED_CRYPTO=yes; LIBS="$LIBS -lcrypto" ],,"-lcrypto")
+ fi
+ fi
+ LIBS="${old_libs}"
fi
- LIBS="${old_libs}"
if test "${HAVE_SNMP}" = ""; then
- old_libs="${LIBS}"
- LIBS="-L/usr/local/lib"
- AC_CHECK_LIB(snmp, asn_parse_int, HAVE_SNMP=yes)
- LIBS="${old_libs}"
+ old_libs="${LIBS}"
+ LIBS="-L/usr/local/lib"
+ unset ac_cv_lib_snmp_asn_parse_int
+ AC_CHECK_LIB(snmp, asn_parse_int, HAVE_SNMP=yes)
+ if test "${HAVE_SNMP}" = ""; then
+ unset ac_cv_lib_snmp_asn_parse_int
+ AC_CHECK_LIB(crypto, main, NEED_CRYPTO=yes, )
+ if test "${NEED_CRYPTO}" = "yes"; then
+ AC_CHECK_LIB(snmp, asn_parse_int, [HAVE_SNMP=yes; NEED_CRYPTO=yes; LIBS="$LIBS -lcrypto" ],,"-lcrypto")
+ fi
+ fi
+ LIBS="${old_libs}"
fi
+
if test "${HAVE_SNMP}" = "yes"; then
- for ac_snmp in /usr/include/ucd-snmp/asn1.h /usr/local/include/ucd-snmp/asn1.h /dev/null
+ for ac_snmp in /usr/include/net-snmp/library/asn1.h /usr/include/ucd-snmp/asn1.h /usr/local/include/ucd-snmp/asn1.h /dev/null
do
test -f "${ac_snmp}" && break
done
+
case ${ac_snmp} in
+ /usr/include/net-snmp/*)
+ AC_DEFINE(HAVE_SNMP,,SNMP)
+ AC_DEFINE(HAVE_NETSNMP,,SNMP)
+ AC_DEFINE(UCD_COMPATIBLE,,SNMP)
+ CFLAGS="${CFLAGS} -I/usr/include/net-snmp -I/usr/include/net-snmp/library"
+ if test "${HAVE_NETSNMP}" = "yes"; then
+ LIBS="${LIBS} -lnetsnmp"
+ else
+ LIBS="${LIBS} -lsnmp"
+ fi
+ ;;
/usr/include/ucd-snmp/*)
AC_DEFINE(HAVE_SNMP,,SNMP)
CFLAGS="${CFLAGS} -I/usr/include/ucd-snmp"
@@ -749,6 +852,28 @@ AC_TRY_COMPILE([#include <sys/resource.h>
AC_DEFINE(HAVE_RUSAGE,,rusage)],
AC_MSG_RESULT(no))
+dnl -------------------
+dnl capabilities checks
+dnl -------------------
+AC_MSG_CHECKING(whether prctl PR_SET_KEEPCAPS is available)
+AC_TRY_COMPILE([#include <sys/prctl.h>],[prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);],
+ [AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_PR_SET_KEEPCAPS,,prctl)
+ zebra_ac_keepcaps="yes"],
+ AC_MSG_RESULT(no)
+)
+if test x"${zebra_ac_keepcaps}" = x"yes"; then
+ AC_CHECK_HEADERS(sys/capability.h)
+fi
+if test x"${ac_cv_header_sys_capability_h}" = x"yes"; then
+ AC_CHECK_LIB(cap, cap_init,
+ [AC_DEFINE(HAVE_LCAPS,1,Capabilities)
+ LIBCAP="-lcap"
+ ]
+ )
+fi
+AC_SUBST(LIBCAP)
+
dnl -------------
dnl check version
dnl -------------
@@ -756,28 +881,55 @@ file="${srcdir}/lib/version.h"
VERSION=`sed -ne 's/^#.*ZEBRA_VERSION.*\"\([^\"]*\)\"$/\1/p' $file`
AC_SUBST(VERSION)
+dnl ----------
+dnl configure date
+dnl ----------
+CONFDATE=`date '+%Y%m%d'`
+AC_SUBST(CONFDATE)
+
dnl ------------------------------
-dnl set paths for process id files
+dnl set paths for state directory
dnl ------------------------------
-AC_CACHE_CHECK(pid file directory,ac_piddir,
-[for ZEBRA_PID_DIR in /var/run dnl
- /var/adm dnl
- /etc dnl
- /dev/null;
-do
- test -d $ZEBRA_PID_DIR && break
-done
-ac_piddir=$ZEBRA_PID_DIR
-if test $ZEBRA_PID_DIR = "/dev/null"; then
- echo "PID DIRECTORY NOT FOUND!"
-fi])
-AC_DEFINE_UNQUOTED(PATH_ZEBRA_PID, "$ac_piddir/zebra.pid",zebra PID)
-AC_DEFINE_UNQUOTED(PATH_RIPD_PID, "$ac_piddir/ripd.pid",ripd PID)
-AC_DEFINE_UNQUOTED(PATH_RIPNGD_PID, "$ac_piddir/ripngd.pid",ripngd PID)
-AC_DEFINE_UNQUOTED(PATH_BGPD_PID, "$ac_piddir/bgpd.pid",bgpd PID)
-AC_DEFINE_UNQUOTED(PATH_OSPFD_PID, "$ac_piddir/ospfd.pid",ospfd PID)
-AC_DEFINE_UNQUOTED(PATH_OSPF6D_PID, "$ac_piddir/ospf6d.pid",ospf6d PID)
+if test "${prefix}" = "NONE"; then
+ zebra_statedir_prefix="";
+else
+ zebra_statedir_prefix=${prefix}
+fi
+if test "${localstatedir}" = '${prefix}/var'; then
+ AC_CACHE_CHECK(state directory,ac_statedir,
+ [for ZEBRA_STATE_DIR in ${zebra_statedir_prefix}/var/run dnl
+ ${zebra_statedir_prefix}/var/adm dnl
+ ${zebra_statedir_prefix}/etc dnl
+ /var/run dnl
+ /var/adm dnl
+ /etc dnl
+ /dev/null;
+ do
+ test -d $ZEBRA_STATE_DIR && break
+ done
+ zebra_statedir=$ZEBRA_STATE_DIR])
+else
+ zebra_statedir=${localstatedir}
+ AC_MSG_CHECKING(directory to use for state file)
+ AC_MSG_RESULT(${zebra_statedir})
+fi
+if test $zebra_statedir = "/dev/null"; then
+ echo "STATE DIRECTORY NOT FOUND!"
+fi
+AC_DEFINE_UNQUOTED(PATH_ZEBRA_PID, "$zebra_statedir/zebra.pid",zebra PID)
+AC_DEFINE_UNQUOTED(PATH_RIPD_PID, "$zebra_statedir/ripd.pid",ripd PID)
+AC_DEFINE_UNQUOTED(PATH_RIPNGD_PID, "$zebra_statedir/ripngd.pid",ripngd PID)
+AC_DEFINE_UNQUOTED(PATH_BGPD_PID, "$zebra_statedir/bgpd.pid",bgpd PID)
+AC_DEFINE_UNQUOTED(PATH_OSPFD_PID, "$zebra_statedir/ospfd.pid",ospfd PID)
+AC_DEFINE_UNQUOTED(PATH_OSPF6D_PID, "$zebra_statedir/ospf6d.pid",ospf6d PID)
+AC_DEFINE_UNQUOTED(ZEBRA_SERV_PATH, "$zebra_statedir/zserv.api",zebra api socket)
+AC_DEFINE_UNQUOTED(ZEBRA_VTYSH_PATH, "$zebra_statedir/zebra.vty",zebra vty socket)
+AC_DEFINE_UNQUOTED(RIP_VTYSH_PATH, "$zebra_statedir/ripd.vty",rip vty socket)
+AC_DEFINE_UNQUOTED(RIPNG_VTYSH_PATH, "$zebra_statedir/ripngd.vty",ripng vty socket)
+AC_DEFINE_UNQUOTED(BGP_VTYSH_PATH, "$zebra_statedir/bgpd.vty",bgpd vty socket)
+AC_DEFINE_UNQUOTED(OSPF_VTYSH_PATH, "$zebra_statedir/ospfd.vty",ospfd vty socket)
+AC_DEFINE_UNQUOTED(OSPF6_VTYSH_PATH, "$zebra_statedir/ospf6d.vty",ospf6d vty socket)
dnl ---------------------------
dnl Check htonl works correctly
@@ -798,7 +950,11 @@ ac_cv_htonl_works=yes,
ac_cv_htonl_works=no)])
AC_MSG_RESULT($ac_cv_htonl_works)
-AC_OUTPUT(Makefile lib/Makefile zebra/Makefile ripd/Makefile ripngd/Makefile bgpd/Makefile ospfd/Makefile ospf6d/Makefile vtysh/Makefile doc/Makefile)
+AC_OUTPUT(Makefile lib/Makefile zebra/Makefile ripd/Makefile
+ ripngd/Makefile bgpd/Makefile ospfd/Makefile
+ ospf6d/Makefile vtysh/Makefile doc/Makefile
+ ospfclient/Makefile
+ redhat/zebra.spec)
echo "
zebra configuration
@@ -808,5 +964,5 @@ host operationg system : ${host_os}
source code location : ${srcdir}
compiler : ${CC}
compiler flags : ${CFLAGS}
-directory for pid files : ${ac_piddir}
-"
+directory for state files : ${zebra_statedir}
+" \ No newline at end of file
diff --git a/configure.in b/configure.in
index 5c9cb547..fd264b7a 100755
--- a/configure.in
+++ b/configure.in
@@ -7,7 +7,7 @@
AC_PREREQ(2.13)
AC_INIT(lib/zebra.h)
-AM_INIT_AUTOMAKE(zebra, 0.93)
+AM_INIT_AUTOMAKE(zebra, 0.94)
AM_CONFIG_HEADER(config.h)
dnl -----------------------------------
@@ -87,11 +87,23 @@ dnl Temporary option until OSPF NSSA implementation complete
AC_ARG_ENABLE(nssa,
[ --enable-nssa enable OSPF NSSA option])
AC_ARG_ENABLE(opaque-lsa,
-[ --enable-opaque-lsa enable OSPF Opaque-LSA support (RFC2370)])
+[ --enable-opaque-lsa enable OSPF Opaque-LSA with OSPFAPI support (RFC2370)])
+AC_ARG_ENABLE(ospfapi,
+[ --disable-ospfapi do not build OSPFAPI to access the OSPF LSA Database,
+ (this is the default if --enable-opaque-lsa is not set)])
+AC_ARG_ENABLE(ospfclient,
+[ --disable-ospfclient do not build OSPFAPI client for OSPFAPI,
+ (this is the default if --disable-ospfapi is set)])
AC_ARG_ENABLE(ospf-te,
[ --enable-ospf-te enable Traffic Engineering Extension to OSPF])
AC_ARG_ENABLE(multipath,
[ --enable-multipath=ARG enable multipath function, ARG must be digit])
+AC_ARG_ENABLE(zebra_user,
+[ --enable-user=ARG user to run zebra suite as (default zebra)])
+AC_ARG_ENABLE(zebra_group,
+[ --enable-group=ARG group to run zebra suite as (default zebra)])
+AC_ARG_ENABLE(vty_group,
+[ --enable-vty-group=ARG set vty sockets to have specified group as owner])
dnl AC_ARG_ENABLE(rtadv,
dnl [ --enable-rtadv enable IPV6 router advertisment option])
@@ -102,31 +114,52 @@ if test "${enable_broken_aliases}" = "yes"; then
echo "Sorry, you can't use netlink with broken aliases"
exit 1
fi
- AC_DEFINE(HAVE_BROKEN_ALIASES)
+ AC_DEFINE(HAVE_BROKEN_ALIASES,,Broken Alias)
enable_netlink=no
fi
if test "${enable_tcp_zebra}" = "yes"; then
- AC_DEFINE(HAVE_TCP_ZEBRA)
+ AC_DEFINE(HAVE_TCP_ZEBRA,,Use TCP for zebra communication)
fi
if test "${enable_nssa}" = "yes"; then
- AC_DEFINE(HAVE_NSSA)
+ AC_DEFINE(HAVE_NSSA,,OSPF NSSA)
fi
if test "${enable_opaque_lsa}" = "yes"; then
- AC_DEFINE(HAVE_OPAQUE_LSA)
+ AC_DEFINE(HAVE_OPAQUE_LSA,,OSPF Opaque LSA)
fi
if test "${enable_ospf_te}" = "yes"; then
- AC_DEFINE(HAVE_OPAQUE_LSA)
- AC_DEFINE(HAVE_OSPF_TE)
+ AC_DEFINE(HAVE_OPAQUE_LSA,,OSPF Opaque LSA)
+ AC_DEFINE(HAVE_OSPF_TE,,OSPF TE)
fi
dnl if test "${enable_rtadv}" = "yes"; then
dnl AC_DEFINE(HAVE_RTADV)
dnl fi
+if test "${enable_user}" = "yes" ; then
+ enable_user="zebra"
+elif test "${enable_user}" = "no"; then
+ enable_user="root"
+fi
+AC_DEFINE_UNQUOTED(ZEBRA_USER, "${enable_user}", Zebra User)
+
+if test "${enable_group}" = "yes" ; then
+ enable_group="zebra"
+elif test "${enable_group}" = "no"; then
+ enable_group="root"
+fi
+AC_DEFINE_UNQUOTED(ZEBRA_GROUP, "${enable_group}", Zebra Group)
+
+if test x"${enable_vty_group}" = x"yes" ; then
+ AC_MSG_ERROR([--enable-vty-group requires a group as argument])
+fi
+if test x"${enable_vty_group}" != x"no"; then
+ AC_DEFINE_UNQUOTED(VTY_GROUP, "${enable_vty_group}", VTY Sockets Group)
+fi
+
changequote(, )dnl
MULTIPATH_NUM=1
@@ -162,30 +195,30 @@ dnl Some systems (Solaris 2.x) require libnsl (Network Services Library)
case "$host" in
*-sunos5.6* | *-solaris2.6*)
opsys=sol2-6
- AC_DEFINE(SUNOS_5)
+ AC_DEFINE(SUNOS_5,,SunOS 5)
AC_CHECK_LIB(xnet, main)
CURSES=-lcurses
;;
*-sunos5* | *-solaris2*)
- AC_DEFINE(SUNOS_5)
+ AC_DEFINE(SUNOS_5,,SunOS 5)
AC_CHECK_LIB(socket, main)
AC_CHECK_LIB(nsl, main)
CURSES=-lcurses
;;
*-linux-*)
opsys=gnu-linux
- AC_DEFINE(GNU_LINUX)
+ AC_DEFINE(GNU_LINUX,,GNU Linux)
;;
*-nec-sysv4*)
AC_CHECK_LIB(nsl, gethostbyname)
AC_CHECK_LIB(socket, socket)
;;
*-freebsd3.2)
- AC_DEFINE(FREEBSD_32)
+ AC_DEFINE(FREEBSD_32,,FreeBSD 3.2)
;;
*-openbsd*)
opsys=openbsd
- AC_DEFINE(OPEN_BSD)
+ AC_DEFINE(OPEN_BSD,,OpenBSD)
;;
*-bsdi*)
opsys=bsdi
@@ -194,18 +227,12 @@ case "$host" in
;;
esac
-case "${host_cpu}-${host_os}" in
- i?86-solaris*)
- AC_DEFINE(SOLARIS_X86)
- ;;
-esac
-
dnl ---------------------
dnl Integrated VTY option
dnl ---------------------
case "${enable_vtysh}" in
"yes") VTYSH="vtysh";
- AC_DEFINE(VTYSH)
+ AC_DEFINE(VTYSH,,VTY shell)
AC_CHECK_LIB(tinfo, tputs, , AC_CHECK_LIB(ncurses, tputs))
AC_CHECK_LIB(readline, main)
if test $ac_cv_lib_readline_main = no; then
@@ -215,7 +242,11 @@ case "${enable_vtysh}" in
if test $ac_cv_header_readline_history_h = no;then
AC_MSG_ERROR([readline is too old to have readline/history.h, please update to the latest readline library.])
fi
- ;;
+ AC_CHECK_LIB(readline, rl_completion_matches)
+ if test $ac_cv_lib_readline_rl_completion_matches = no; then
+ AC_DEFINE(rl_completion_matches,completion_matches,Old readline)
+ fi
+ ;;
"no" ) VTYSH="";;
* ) ;;
esac
@@ -224,6 +255,25 @@ dnl ----------
dnl PAM module
dnl ----------
if test "$with_libpam" = "yes"; then
+ AC_CHECK_HEADER(security/pam_misc.h)
+ if test "$ac_cv_header_security_pam_misc_h" = yes; then
+ AC_DEFINE(HAVE_PAM_MISC_H,,Have pam_misc.h)
+ AC_DEFINE(PAM_CONV_FUNC,misc_conv,Have misc_conv)
+ pam_conv_func="misc_conv"
+ fi
+ AC_CHECK_HEADER(security/openpam.h)
+ if test "$ac_cv_header_security_openpam_h" = yes; then
+ AC_DEFINE(HAVE_OPENPAM_H,,Have openpam.h)
+ AC_DEFINE(PAM_CONV_FUNC,openpam_ttyconv,Have openpam_ttyconv)
+ pam_conv_func="openpam_ttyconv"
+ fi
+ if test -z "$ac_cv_header_security_pam_misc_h$ac_cv_header_security_openpam_h" ; then
+ AC_MSG_WARN([*** pam support will not be built ***])
+ with_libpam="no"
+ fi
+fi
+
+if test "$with_libpam" = "yes"; then
dnl took this test from proftpd's configure.in and suited to our needs
dnl -------------------------------------------------------------------------
dnl
@@ -232,16 +282,16 @@ dnl of the PAM library. Prior to 0.72 release, the Linux PAM shared library
dnl omitted requiring libdl linking information. PAM-0.72 or better ships
dnl with RedHat 6.2 and Debian 2.2 or better.
AC_CHECK_LIB(pam, pam_start,
- [AC_CHECK_LIB(pam, misc_conv,
- [AC_DEFINE(USE_PAM)
+ [AC_CHECK_LIB(pam, $pam_conv_func,
+ [AC_DEFINE(USE_PAM,,Use PAM for authentication)
LIBPAM="-lpam"],
- [AC_DEFINE(USE_PAM)
+ [AC_DEFINE(USE_PAM,,Use PAM for authentication)
LIBPAM="-lpam -lpam_misc"]
)
],
[AC_CHECK_LIB(pam, pam_end,
- [AC_CHECK_LIB(pam, misc_conv,
+ [AC_CHECK_LIB(pam, $pam_conv_func,
[AC_DEFINE(USE_PAM)
LIBPAM="-lpam -ldl"],
[AC_DEFINE(USE_PAM)
@@ -257,36 +307,7 @@ AC_SUBST(LIBPAM)
dnl -------------------------------
dnl Endian-ness check
dnl -------------------------------
-AC_DEFUN(ZEBRA_AC_C_BIGENDIAN,
-[AC_CACHE_CHECK(whether byte ordering is bigendian, ac_cv_c_bigendian,
-[ac_cv_c_bigendian=unknown
-# See if sys/param.h defines the BYTE_ORDER macro.
-AC_TRY_COMPILE([#include <sys/types.h>
-#include <sys/param.h>], [
-#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN
- bogus endian macros
-#endif], [# It does; now see whether it defined to BIG_ENDIAN or not.
-AC_TRY_COMPILE([#include <sys/types.h>
-#include <sys/param.h>], [
-#if BYTE_ORDER != BIG_ENDIAN
- not big endian
-#endif], ac_cv_c_bigendian=yes, ac_cv_c_bigendian=no)])
-if test $ac_cv_c_bigendian = unknown; then
-AC_TRY_RUN([main () {
- /* Are we little or big endian? From Harbison&Steele. */
- union
- {
- long l;
- char c[sizeof (long)];
- } u;
- u.l = 1;
- exit (u.c[sizeof (long) - 1] == 1);
-}], ac_cv_c_bigendian=no, ac_cv_c_bigendian=yes, ac_cv_c_bigendian=no)
-fi])
-if test $ac_cv_c_bigendian = yes; then
- AC_DEFINE(WORDS_BIGENDIAN,1,Big endian words)
-fi
-])
+AC_WORDS_BIGENDIAN
dnl -------------------------------
dnl check the size in byte of the C
@@ -310,7 +331,7 @@ if test x"$opsys" = x"gnu-linux"; then
if test "${enable_netlink}" = "yes";then
AC_MSG_RESULT(netlink)
RT_METHOD=rt_netlink.o
- AC_DEFINE(HAVE_NETLINK)
+ AC_DEFINE(HAVE_NETLINK,,netlink)
netlink=yes
elif test "${enable_netlink}" = "no"; then
AC_MSG_RESULT(ioctl)
@@ -319,7 +340,7 @@ if test x"$opsys" = x"gnu-linux"; then
else
AC_MSG_RESULT(netlink)
RT_METHOD=rt_netlink.o
- AC_DEFINE(HAVE_NETLINK)
+ AC_DEFINE(HAVE_NETLINK,,netlink)
netlink=yes
fi
else
@@ -341,8 +362,7 @@ main ()
exit (1);
exit (0);
}],
- [AC_DEFINE(HAVE_AF_ROUTE)
- KERNEL_METHOD=kernel_socket.o
+ [KERNEL_METHOD=kernel_socket.o
RT_METHOD=rt_socket.o
AC_MSG_RESULT(socket)],
[RT_METHOD=rt_ioctl.o
@@ -396,7 +416,7 @@ else
elif grep NET_RT_IFLIST /usr/include/sys/socket.h >/dev/null 2>&1; then
AC_MSG_RESULT(sysctl)
IF_METHOD=if_sysctl.o
- AC_DEFINE(HAVE_NET_RT_IFLIST)
+ AC_DEFINE(HAVE_NET_RT_IFLIST,,NET_RT_IFLIST)
else
AC_MSG_RESULT(ioctl)
IF_METHOD=if_ioctl.o
@@ -408,12 +428,12 @@ dnl -----------------------
dnl check proc file system.
dnl -----------------------
if test -r /proc/net/dev; then
- AC_DEFINE(HAVE_PROC_NET_DEV)
+ AC_DEFINE(HAVE_PROC_NET_DEV,,/proc/net/dev)
IF_PROC=if_proc.o
fi
if test -r /proc/net/if_inet6; then
- AC_DEFINE(HAVE_PROC_NET_IF_INET6)
+ AC_DEFINE(HAVE_PROC_NET_IF_INET6,,/proc/net/if_inet6)
IF_PROC=if_proc.o
fi
AC_SUBST(IF_PROC)
@@ -455,8 +475,8 @@ dnl INRIA IPv6
dnl ----------
if grep IPV6_INRIA_VERSION /usr/include/netinet/in.h >/dev/null 2>&1; then
zebra_cv_ipv6=yes
- AC_DEFINE(HAVE_IPV6)
- AC_DEFINE(INRIA_IPV6)
+ AC_DEFINE(HAVE_IPV6,,IPv6)
+ AC_DEFINE(INRIA_IPV6,,Inria IPv6)
RIPNGD="ripngd"
OSPF6D="ospf6d"
LIB_IPV6=""
@@ -467,8 +487,8 @@ dnl KAME IPv6
dnl ---------
if grep WIDE /usr/include/netinet6/in6.h >/dev/null 2>&1; then
zebra_cv_ipv6=yes
- AC_DEFINE(HAVE_IPV6)
- AC_DEFINE(KAME)
+ AC_DEFINE(HAVE_IPV6,,IPv6)
+ AC_DEFINE(KAME,,KAME IPv6)
RIPNGD="ripngd"
OSPF6D="ospf6d"
if test -d /usr/local/v6/lib -a -f /usr/local/v6/lib/libinet6.a; then
@@ -481,12 +501,12 @@ dnl NRL check
dnl ---------
if grep NRL /usr/include/netinet6/in6.h >/dev/null 2>&1; then
zebra_cv_ipv6=yes
- AC_DEFINE(HAVE_IPV6)
- AC_DEFINE(NRL)
+ AC_DEFINE(HAVE_IPV6,,IPv6)
+ AC_DEFINE(NRL,,NRL)
RIPNGD="ripngd"
OSPF6D="ospf6d"
if test x"$opsys" = x"bsdi";then
- AC_DEFINE(BSDI_NRL)
+ AC_DEFINE(BSDI_NRL,,BSDI)
AC_MSG_RESULT(BSDI_NRL)
else
AC_MSG_RESULT(NRL)
@@ -521,7 +541,7 @@ if test "$zebra_cv_linux_ipv6" = "yes";then
#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
yes
#endif], [glibc=yes; AC_MSG_RESULT(yes)], AC_MSG_RESULT(no))
- AC_DEFINE(LINUX_IPV6)
+ AC_DEFINE(LINUX_IPV6,,Linux IPv6)
RIPNGD="ripngd"
OSPF6D="ospf6d"
if test "$glibc" != "yes"; then
@@ -570,6 +590,18 @@ else
OSPFD="ospfd"
fi
+OSPFCLIENT=""
+if test "${enable_opaque_lsa}" = "yes"; then
+ if test "${enable_ospfapi}" != "no";then
+ AC_DEFINE(SUPPORT_OSPF_API,,OSPFAPI)
+
+ if test "${enable_ospfclient}" != "no";then
+ OSPFCLIENT="ospfclient"
+ fi
+ fi
+
+fi
+
case "${enable_ripngd}" in
"yes") RIPNGD="ripngd";;
"no" ) RIPNGD="";;
@@ -583,7 +615,7 @@ case "${enable_ospf6d}" in
esac
if test "${enable_bgp_announce}" = "no";then
- AC_DEFINE(DISABLE_BGP_ANNOUNCE)
+ AC_DEFINE(DISABLE_BGP_ANNOUNCE,,Disable BGP installation to zebra)
fi
AC_SUBST(ZEBRA)
@@ -595,8 +627,10 @@ AC_SUBST(OSPF6D)
AC_SUBST(VTYSH)
AC_SUBST(INCLUDES)
AC_SUBST(CURSES)
-AC_CHECK_LIB(c, inet_ntop, [AC_DEFINE(HAVE_INET_NTOP)])
-AC_CHECK_LIB(c, inet_pton, [AC_DEFINE(HAVE_INET_PTON)])
+AC_SUBST(OSPFCLIENT)
+AC_SUBST(OSPFAPI)
+AC_CHECK_LIB(c, inet_ntop, [AC_DEFINE(HAVE_INET_NTOP,,inet_ntop)])
+AC_CHECK_LIB(c, inet_pton, [AC_DEFINE(HAVE_INET_PTON,,inet_pton)])
AC_CHECK_LIB(crypt, crypt)
AC_CHECK_LIB(resolv, res_init)
AC_CHECK_LIB(m, main)
@@ -613,61 +647,83 @@ dnl check system has GNU regexp
dnl ---------------------------
dnl AC_MSG_CHECKING(whether system has GNU regex)
AC_CHECK_LIB(c, regexec,
-[AC_DEFINE(HAVE_GNU_REGEX)
+[AC_DEFINE(HAVE_GNU_REGEX,,GNU regexp library)
LIB_REGEX=""],
[LIB_REGEX="regex.o"])
AC_SUBST(LIB_REGEX)
-dnl AC_MSG_CHECKING(whether system has GNU regex)
-dnl if grep RE_NO_GNU_OPS /usr/include/regex.h >/dev/null 2>&1; then
-dnl AC_MSG_RESULT(yes)
-dnl AC_DEFINE(HAVE_GNU_REGEX)
-dnl LIB_REGEX=""
-dnl else
-dnl AC_MSG_RESULT(no)
-dnl LIB_REGEX="regex.o"
-dnl fi
-dnl AC_SUBST(LIB_REGEX)
-
dnl ------------------
dnl check SNMP library
dnl ------------------
if test "${enable_snmp}" = "yes";then
dnl AC_CHECK_LIB(snmp, asn_parse_int, HAVE_SNMP=yes)
- old_libs="${LIBS}"
- LIBS="-L/usr/local/lib"
- unset ac_cv_lib_snmp_asn_parse_int
- AC_CHECK_LIB(snmp, asn_parse_int, HAVE_SNMP=yes, )
if test "${HAVE_SNMP}" = ""; then
+ old_libs="${LIBS}"
+ LIBS="-L/usr/lib"
+ unset ac_cv_lib_snmp_asn_parse_int
+ AC_CHECK_LIB(crypto, main, NEED_CRYPTO=yes, )
+ if test "${NEED_CRYPTO}" = ""; then
+ AC_CHECK_LIB(netsnmp, asn_parse_int, [HAVE_NETSNMP=yes; HAVE_SNMP=yes ])
+ else
+ AC_CHECK_LIB(netsnmp, asn_parse_int, [HAVE_NETSNMP=yes; HAVE_SNMP=yes; NEED_CRYPTO=yes;LIBS="$LIBS -lcrypto" ],,"-lcrypto")
+ fi
+ LIBS="${old_libs}"
+ fi
+ if test "${HAVE_SNMP}" = ""; then
+ old_libs="${LIBS}"
+ LIBS="-L/usr/lib"
unset ac_cv_lib_snmp_asn_parse_int
- AC_CHECK_LIB(crypto, main, [NEED_CRYPTO=yes ], )
- if test "${NEED_CRYPTO}" = ""; then
- AC_CHECK_LIB(snmp, asn_parse_int, [HAVE_SNMP=yes; NEED_CRYPTO=yes ],)
- else
- AC_CHECK_LIB(snmp, asn_parse_int, [HAVE_SNMP=yes; NEED_CRYPTO=yes;LIBS="$LIBS -lcrypto" ],,"-lcrypto")
- fi
+ AC_CHECK_LIB(snmp, asn_parse_int, HAVE_SNMP=yes, )
+ if test "${HAVE_SNMP}" = ""; then
+ unset ac_cv_lib_snmp_asn_parse_int
+ AC_CHECK_LIB(crypto, main, NEED_CRYPTO=yes, )
+ if test "${NEED_CRYPTO}" = "yes"; then
+ AC_CHECK_LIB(snmp, asn_parse_int, [HAVE_SNMP=yes; NEED_CRYPTO=yes; LIBS="$LIBS -lcrypto" ],,"-lcrypto")
+ fi
+ fi
+ LIBS="${old_libs}"
fi
- LIBS="${old_libs}"
if test "${HAVE_SNMP}" = ""; then
- old_libs="${LIBS}"
- LIBS="-L/usr/local/lib"
- AC_CHECK_LIB(snmp, asn_parse_int, HAVE_SNMP=yes)
- LIBS="${old_libs}"
+ old_libs="${LIBS}"
+ LIBS="-L/usr/local/lib"
+ unset ac_cv_lib_snmp_asn_parse_int
+ AC_CHECK_LIB(snmp, asn_parse_int, HAVE_SNMP=yes)
+ if test "${HAVE_SNMP}" = ""; then
+ unset ac_cv_lib_snmp_asn_parse_int
+ AC_CHECK_LIB(crypto, main, NEED_CRYPTO=yes, )
+ if test "${NEED_CRYPTO}" = "yes"; then
+ AC_CHECK_LIB(snmp, asn_parse_int, [HAVE_SNMP=yes; NEED_CRYPTO=yes; LIBS="$LIBS -lcrypto" ],,"-lcrypto")
+ fi
+ fi
+ LIBS="${old_libs}"
fi
+
if test "${HAVE_SNMP}" = "yes"; then
- for ac_snmp in /usr/include/ucd-snmp/asn1.h /usr/local/include/ucd-snmp/asn1.h /dev/null
+ for ac_snmp in /usr/include/net-snmp/library/asn1.h /usr/include/ucd-snmp/asn1.h /usr/local/include/ucd-snmp/asn1.h /dev/null
do
test -f "${ac_snmp}" && break
done
+
case ${ac_snmp} in
+ /usr/include/net-snmp/*)
+ AC_DEFINE(HAVE_SNMP,,SNMP)
+ AC_DEFINE(HAVE_NETSNMP,,SNMP)
+ AC_DEFINE(UCD_COMPATIBLE,,SNMP)
+ CFLAGS="${CFLAGS} -I/usr/include/net-snmp -I/usr/include/net-snmp/library"
+ if test "${HAVE_NETSNMP}" = "yes"; then
+ LIBS="${LIBS} -lnetsnmp"
+ else
+ LIBS="${LIBS} -lsnmp"
+ fi
+ ;;
/usr/include/ucd-snmp/*)
- AC_DEFINE(HAVE_SNMP)
+ AC_DEFINE(HAVE_SNMP,,SNMP)
CFLAGS="${CFLAGS} -I/usr/include/ucd-snmp"
LIBS="${LIBS} -lsnmp"
;;
/usr/local/include/ucd-snmp/*)
- AC_DEFINE(HAVE_SNMP)
+ AC_DEFINE(HAVE_SNMP,,SNMP)
CFLAGS="${CFLAGS} -I/usr/local/include/ucd-snmp"
LIBS="${LIBS} -L/usr/local/lib -lsnmp"
;;
@@ -686,7 +742,7 @@ AC_TRY_COMPILE([#include <sys/types.h>
#include <sys/socket.h>
],[static struct sockaddr ac_i;int ac_j = sizeof (ac_i.sa_len);],
[AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_SA_LEN)],
+ AC_DEFINE(HAVE_SA_LEN,,sa_len)],
AC_MSG_RESULT(no))
dnl ----------------------------
@@ -697,7 +753,7 @@ AC_TRY_COMPILE([#include <sys/types.h>
#include <netinet/in.h>
],[static struct sockaddr_in ac_i;int ac_j = sizeof (ac_i.sin_len);],
[AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_SIN_LEN)],
+ AC_DEFINE(HAVE_SIN_LEN,,sin_len)],
AC_MSG_RESULT(no))
dnl ----------------------------
@@ -708,7 +764,7 @@ AC_TRY_COMPILE([#include <sys/types.h>
#include <sys/un.h>
],[static struct sockaddr_un ac_i;int ac_j = sizeof (ac_i.sun_len);],
[AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_SUN_LEN)],
+ AC_DEFINE(HAVE_SUN_LEN,,sun_len)],
AC_MSG_RESULT(no))
dnl -----------------------------------
@@ -720,7 +776,7 @@ if test "$zebra_cv_ipv6" = yes; then
#include <netinet/in.h>
],[static struct sockaddr_in6 ac_i;int ac_j = sizeof (ac_i.sin6_scope_id);],
[AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_SIN6_SCOPE_ID)],
+ AC_DEFINE(HAVE_SIN6_SCOPE_ID,,scope id)],
AC_MSG_RESULT(no))
fi
@@ -733,7 +789,7 @@ AC_TRY_COMPILE([#include <sys/types.h>
#include <netinet/in.h>
],[socklen_t ac_x;],
[AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_SOCKLEN_T)],
+ AC_DEFINE(HAVE_SOCKLEN_T,,socklen_t)],
AC_MSG_RESULT(no))
dnl ------------------------
@@ -743,7 +799,7 @@ AC_MSG_CHECKING(whether struct sockaddr_dl exist)
AC_EGREP_HEADER(sockaddr_dl,
net/if_dl.h,
[AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_SOCKADDR_DL)],
+ AC_DEFINE(HAVE_SOCKADDR_DL,,sockaddr_dl)],
AC_MSG_RESULT(no))
dnl --------------------------
@@ -753,7 +809,7 @@ AC_MSG_CHECKING(whether struct ifaliasreq exist)
AC_EGREP_HEADER(ifaliasreq,
net/if.h,
[AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_IFALIASREQ)],
+ AC_DEFINE(HAVE_IFALIASREQ,,ifaliasreq)],
AC_MSG_RESULT(no))
dnl ----------------------------
@@ -763,7 +819,7 @@ AC_MSG_CHECKING(whether struct if6_aliasreq exist)
AC_EGREP_HEADER(in6_aliasreq,
netinet6/in6_var.h,
[AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_IN6_ALIASREQ)],
+ AC_DEFINE(HAVE_IN6_ALIASREQ,,in6_aliasreq)],
AC_MSG_RESULT(no))
dnl ---------------------------
@@ -773,7 +829,7 @@ AC_MSG_CHECKING(whether struct rt_addrinfo exist)
AC_EGREP_HEADER(rt_addrinfo,
net/route.h,
[AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_RT_ADDRINFO)],
+ AC_DEFINE(HAVE_RT_ADDRINFO,,rt_addrinfo)],
AC_MSG_RESULT(no))
dnl --------------------------
@@ -783,7 +839,7 @@ AC_MSG_CHECKING(whether struct in_pktinfo exist)
AC_TRY_COMPILE([#include <netinet/in.h>
],[struct in_pktinfo ac_x;],
[AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_INPKTINFO)],
+ AC_DEFINE(HAVE_INPKTINFO,,in_pktinfo)],
AC_MSG_RESULT(no))
dnl --------------------------------------
@@ -793,9 +849,31 @@ AC_MSG_CHECKING(whether getrusage is available)
AC_TRY_COMPILE([#include <sys/resource.h>
],[struct rusage ac_x; getrusage (RUSAGE_SELF, &ac_x);],
[AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_RUSAGE)],
+ AC_DEFINE(HAVE_RUSAGE,,rusage)],
AC_MSG_RESULT(no))
+dnl -------------------
+dnl capabilities checks
+dnl -------------------
+AC_MSG_CHECKING(whether prctl PR_SET_KEEPCAPS is available)
+AC_TRY_COMPILE([#include <sys/prctl.h>],[prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);],
+ [AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_PR_SET_KEEPCAPS,,prctl)
+ zebra_ac_keepcaps="yes"],
+ AC_MSG_RESULT(no)
+)
+if test x"${zebra_ac_keepcaps}" = x"yes"; then
+ AC_CHECK_HEADERS(sys/capability.h)
+fi
+if test x"${ac_cv_header_sys_capability_h}" = x"yes"; then
+ AC_CHECK_LIB(cap, cap_init,
+ [AC_DEFINE(HAVE_LCAPS,1,Capabilities)
+ LIBCAP="-lcap"
+ ]
+ )
+fi
+AC_SUBST(LIBCAP)
+
dnl -------------
dnl check version
dnl -------------
@@ -803,28 +881,55 @@ file="${srcdir}/lib/version.h"
VERSION=`sed -ne 's/^#.*ZEBRA_VERSION.*\"\([^\"]*\)\"$/\1/p' $file`
AC_SUBST(VERSION)
+dnl ----------
+dnl configure date
+dnl ----------
+CONFDATE=`date '+%Y%m%d'`
+AC_SUBST(CONFDATE)
+
dnl ------------------------------
-dnl set paths for process id files
+dnl set paths for state directory
dnl ------------------------------
-AC_CACHE_CHECK(pid file directory,ac_piddir,
-[for ZEBRA_PID_DIR in /var/run dnl
- /var/adm dnl
- /etc dnl
- /dev/null;
-do
- test -d $ZEBRA_PID_DIR && break
-done
-ac_piddir=$ZEBRA_PID_DIR
-if test $ZEBRA_PID_DIR = "/dev/null"; then
- echo "PID DIRECTORY NOT FOUND!"
-fi])
-AC_DEFINE_UNQUOTED(PATH_ZEBRA_PID, "$ac_piddir/zebra.pid")
-AC_DEFINE_UNQUOTED(PATH_RIPD_PID, "$ac_piddir/ripd.pid")
-AC_DEFINE_UNQUOTED(PATH_RIPNGD_PID, "$ac_piddir/ripngd.pid")
-AC_DEFINE_UNQUOTED(PATH_BGPD_PID, "$ac_piddir/bgpd.pid")
-AC_DEFINE_UNQUOTED(PATH_OSPFD_PID, "$ac_piddir/ospfd.pid")
-AC_DEFINE_UNQUOTED(PATH_OSPF6D_PID, "$ac_piddir/ospf6d.pid")
+if test "${prefix}" = "NONE"; then
+ zebra_statedir_prefix="";
+else
+ zebra_statedir_prefix=${prefix}
+fi
+if test "${localstatedir}" = '${prefix}/var'; then
+ AC_CACHE_CHECK(state directory,ac_statedir,
+ [for ZEBRA_STATE_DIR in ${zebra_statedir_prefix}/var/run dnl
+ ${zebra_statedir_prefix}/var/adm dnl
+ ${zebra_statedir_prefix}/etc dnl
+ /var/run dnl
+ /var/adm dnl
+ /etc dnl
+ /dev/null;
+ do
+ test -d $ZEBRA_STATE_DIR && break
+ done
+ zebra_statedir=$ZEBRA_STATE_DIR])
+else
+ zebra_statedir=${localstatedir}
+ AC_MSG_CHECKING(directory to use for state file)
+ AC_MSG_RESULT(${zebra_statedir})
+fi
+if test $zebra_statedir = "/dev/null"; then
+ echo "STATE DIRECTORY NOT FOUND!"
+fi
+AC_DEFINE_UNQUOTED(PATH_ZEBRA_PID, "$zebra_statedir/zebra.pid",zebra PID)
+AC_DEFINE_UNQUOTED(PATH_RIPD_PID, "$zebra_statedir/ripd.pid",ripd PID)
+AC_DEFINE_UNQUOTED(PATH_RIPNGD_PID, "$zebra_statedir/ripngd.pid",ripngd PID)
+AC_DEFINE_UNQUOTED(PATH_BGPD_PID, "$zebra_statedir/bgpd.pid",bgpd PID)
+AC_DEFINE_UNQUOTED(PATH_OSPFD_PID, "$zebra_statedir/ospfd.pid",ospfd PID)
+AC_DEFINE_UNQUOTED(PATH_OSPF6D_PID, "$zebra_statedir/ospf6d.pid",ospf6d PID)
+AC_DEFINE_UNQUOTED(ZEBRA_SERV_PATH, "$zebra_statedir/zserv.api",zebra api socket)
+AC_DEFINE_UNQUOTED(ZEBRA_VTYSH_PATH, "$zebra_statedir/zebra.vty",zebra vty socket)
+AC_DEFINE_UNQUOTED(RIP_VTYSH_PATH, "$zebra_statedir/ripd.vty",rip vty socket)
+AC_DEFINE_UNQUOTED(RIPNG_VTYSH_PATH, "$zebra_statedir/ripngd.vty",ripng vty socket)
+AC_DEFINE_UNQUOTED(BGP_VTYSH_PATH, "$zebra_statedir/bgpd.vty",bgpd vty socket)
+AC_DEFINE_UNQUOTED(OSPF_VTYSH_PATH, "$zebra_statedir/ospfd.vty",ospfd vty socket)
+AC_DEFINE_UNQUOTED(OSPF6_VTYSH_PATH, "$zebra_statedir/ospf6d.vty",ospf6d vty socket)
dnl ---------------------------
dnl Check htonl works correctly
@@ -845,7 +950,11 @@ ac_cv_htonl_works=yes,
ac_cv_htonl_works=no)])
AC_MSG_RESULT($ac_cv_htonl_works)
-AC_OUTPUT(Makefile lib/Makefile zebra/Makefile ripd/Makefile ripngd/Makefile bgpd/Makefile ospfd/Makefile ospf6d/Makefile vtysh/Makefile doc/Makefile)
+AC_OUTPUT(Makefile lib/Makefile zebra/Makefile ripd/Makefile
+ ripngd/Makefile bgpd/Makefile ospfd/Makefile
+ ospf6d/Makefile vtysh/Makefile doc/Makefile
+ ospfclient/Makefile
+ redhat/zebra.spec)
echo "
zebra configuration
@@ -855,5 +964,5 @@ host operationg system : ${host_os}
source code location : ${srcdir}
compiler : ${CC}
compiler flags : ${CFLAGS}
-directory for pid files : ${ac_piddir}
-"
+directory for state files : ${zebra_statedir}
+" \ No newline at end of file
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 81f1e41e..dbd105aa 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -3,16 +3,16 @@
INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib
DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\"
-noinst_LIBRARIES = libzebra.a
+lib_LIBRARIES = libzebra.a
libzebra_a_SOURCES = \
version.c network.c pid_output.c getopt.c getopt1.c daemon.c \
print_version.c checksum.c vector.c linklist.c vty.c command.c \
sockunion.c prefix.c thread.c if.c memory.c buffer.c table.c hash.c \
filter.c routemap.c distribute.c stream.c str.c log.c plist.c \
- zclient.c sockopt.c smux.c md5.c if_rmap.c keychain.c
+ zclient.c sockopt.c smux.c md5.c keychain.c privs.c
-libzebra_a_DEPENDENCIES = @LIB_REGEX@
+libzebra_a_DEPENDENCIES = @LIB_REGEX@ @LIBCAP@
libzebra_a_LIBADD = @LIB_REGEX@
@@ -20,7 +20,7 @@ noinst_HEADERS = \
buffer.h command.h filter.h getopt.h hash.h if.h linklist.h log.h \
memory.h network.h prefix.h routemap.h distribute.h sockunion.h \
str.h stream.h table.h thread.h vector.h version.h vty.h zebra.h \
- plist.h zclient.h sockopt.h smux.h md5-gnu.h if_rmap.h keychain.h
+ plist.h zclient.h sockopt.h smux.h md5-gnu.h keychain.h privs.h
EXTRA_DIST = regex.c regex-gnu.h
diff --git a/lib/memory.h b/lib/memory.h
index 52e3bc11..06681bd1 100644
--- a/lib/memory.h
+++ b/lib/memory.h
@@ -184,6 +184,8 @@ enum
MTYPE_VRF,
MTYPE_VRF_NAME,
+
+ MTYPE_PRIVS,
MTYPE_MAX
};
diff --git a/lib/privs.c b/lib/privs.c
new file mode 100644
index 00000000..8932eacc
--- /dev/null
+++ b/lib/privs.c
@@ -0,0 +1,377 @@
+/*
+ * Zebra privileges.
+ *
+ * Copyright (C) 2003 Paul Jakma.
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra 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.
+ *
+ * GNU Zebra 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 "log.h"
+#include "privs.h"
+#include "memory.h"
+
+
+/* internal privileges state */
+static struct _zprivs_t
+{
+#ifdef HAVE_LCAPS
+ cap_t caps; /* caps storage */
+ cap_value_t *syscaps_p; /* system permitted caps */
+ cap_value_t *syscaps_i; /* system inheritable caps */
+ int sys_num_p; /* number of syscaps_p */
+ int sys_num_i; /* number of syscaps_i */
+#endif /* HAVE_LCAPS */
+ uid_t zuid, /* uid to run as */
+ zsuid; /* saved uid */
+ gid_t zgid; /* gid to run as */
+ gid_t vtygrp; /* gid for vty sockets */
+} zprivs_state;
+
+/* externally exported but not directly accessed functions */
+#ifdef HAVE_LCAPS
+int zprivs_change_caps (zebra_privs_ops_t);
+zebra_privs_current_t zprivs_state_caps (void);
+#endif /* HAVE_LCAPS */
+int zprivs_change_uid (zebra_privs_ops_t);
+zebra_privs_current_t zprivs_state_uid (void);
+int zprivs_change_null (zebra_privs_ops_t);
+zebra_privs_current_t zprivs_state_null (void);
+void zprivs_terminate (void);
+
+#ifdef HAVE_LCAPS
+static int
+cap_map [ZCAP_MAX] =
+{
+ [ZCAP_SETGID] = CAP_SETGID,
+ [ZCAP_SETUID] = CAP_SETUID,
+ [ZCAP_BIND] = CAP_NET_BIND_SERVICE,
+ [ZCAP_BROADCAST] = CAP_NET_BROADCAST,
+ [ZCAP_ADMIN] = CAP_NET_ADMIN,
+ [ZCAP_RAW] = CAP_NET_RAW,
+ [ZCAP_CHROOT] = CAP_SYS_CHROOT,
+ [ZCAP_NICE] = CAP_SYS_NICE,
+ [ZCAP_PTRACE] = CAP_SYS_PTRACE,
+ [ZCAP_DAC_OVERRIDE] = CAP_DAC_OVERRIDE,
+ [ZCAP_READ_SEARCH] = CAP_DAC_READ_SEARCH,
+ [ZCAP_SYS_ADMIN] = CAP_SYS_ADMIN,
+ [ZCAP_FOWNER] = ZCAP_FOWNER
+};
+
+/* convert zebras privileges to system capabilities */
+static cap_value_t *
+zcaps2sys (zebra_capabilities_t *zcaps, int num)
+{
+ cap_value_t *syscaps;
+ int i;
+
+ if (!num)
+ return NULL;
+
+ syscaps = (cap_value_t *) XCALLOC ( MTYPE_PRIVS,
+ (sizeof(cap_value_t) * num) );
+ if (!syscaps)
+ {
+ zlog_err ("zcap2sys: could not XCALLOC!");
+ return NULL;
+ }
+
+ for (i=0; i < num; i++)
+ {
+ syscaps[i] = cap_map[zcaps[i]];
+ }
+
+ return syscaps;
+}
+
+/* set or clear the effective capabilities to/from permitted */
+int
+zprivs_change_caps (zebra_privs_ops_t op)
+{
+ cap_flag_value_t cflag;
+
+ if (op == ZPRIVS_RAISE)
+ cflag = CAP_SET;
+ else if (op == ZPRIVS_LOWER)
+ cflag = CAP_CLEAR;
+ else
+ return -1;
+
+ if ( !cap_set_flag (zprivs_state.caps, CAP_EFFECTIVE,
+ zprivs_state.sys_num_p, zprivs_state.syscaps_p, cflag))
+ return cap_set_proc (zprivs_state.caps);
+ return -1;
+}
+
+zebra_privs_current_t
+zprivs_state_caps (void)
+{
+ int i;
+ cap_flag_value_t val;
+
+ for (i=0; i < zprivs_state.sys_num_p; i++)
+ {
+ if ( cap_get_flag (zprivs_state.caps, zprivs_state.syscaps_p[i],
+ CAP_EFFECTIVE, &val) )
+ zlog_warn ("zprivs_state_caps: could not cap_get_flag, %s",
+ strerror (errno) );
+ if (val == CAP_SET)
+ return ZPRIVS_RAISED;
+ }
+ return ZPRIVS_LOWERED;
+}
+
+#endif /* HAVE_LCAPS */
+
+int
+zprivs_change_uid (zebra_privs_ops_t op)
+{
+
+ if (op == ZPRIVS_RAISE)
+ return seteuid (zprivs_state.zsuid);
+ else if (op == ZPRIVS_LOWER)
+ return seteuid (zprivs_state.zuid);
+ else
+ return -1;
+}
+
+zebra_privs_current_t
+zprivs_state_uid (void)
+{
+ return ( (zprivs_state.zuid == geteuid()) ? ZPRIVS_LOWERED : ZPRIVS_RAISED);
+}
+
+int
+zprivs_change_null (zebra_privs_ops_t op)
+{
+ return 0;
+}
+
+zebra_privs_current_t
+zprivs_state_null (void)
+{
+ return ZPRIVS_RAISED;
+}
+
+
+void
+zprivs_init(struct zebra_privs_t *zprivs)
+{
+ struct passwd *pwentry = NULL;
+ struct group *grentry = NULL;
+
+ /* NULL privs */
+ if (! (zprivs->user || zprivs->group
+ || zprivs->cap_num_p || zprivs->cap_num_i) )
+ {
+ zprivs->change = zprivs_change_null;
+ zprivs->current_state = zprivs_state_null;
+ return;
+ }
+
+ if (zprivs->user)
+ {
+ if ( (pwentry = getpwnam (zprivs->user)) )
+ {
+ zprivs_state.zuid = pwentry->pw_uid;
+ }
+ else
+ {
+ zlog_err ("privs_init: could not lookup supplied user");
+ exit (1);
+ }
+ }
+
+
+#ifdef VTY_GROUP
+ /* Add the VTY_GROUP to the supplementary groups so it can be chowned to */
+ if ( (grentry = getgrnam (zprivs->vty_group)) )
+ {
+ if ( setgroups (1, &grentry->gr_gid) )
+ {
+ zlog_err ("privs_init: could not setgroups, %s",
+ strerror (errno) );
+ exit (1);
+ }
+ zprivs_state.vtygrp = grentry->gr_gid;
+ }
+ else
+ {
+ zlog_err ("privs_init: could not lookup supplied user");
+ exit (1);
+ }
+#endif /* VTY_GROUP */
+
+ if (zprivs->group)
+ {
+ if ( (grentry = getgrnam (zprivs->user)) )
+ {
+ zprivs_state.zgid = grentry->gr_gid;
+ }
+ else
+ {
+ zlog_err ("privs_init: could not lookup supplied user");
+ exit (1);
+ }
+
+ /* change group now, forever. uid we do later */
+ if ( setregid (zprivs_state.zgid, zprivs_state.zgid) )
+ {
+ zlog_err ("privs_init: could not setregid");
+ exit (1);
+ }
+ }
+
+#ifdef HAVE_LCAPS
+ zprivs_state.syscaps_p = zcaps2sys (zprivs->caps_p, zprivs->cap_num_p);
+ zprivs_state.sys_num_p = zprivs->cap_num_p;
+ zprivs_state.syscaps_i = zcaps2sys (zprivs->caps_i, zprivs->cap_num_i);
+ zprivs_state.sys_num_i = zprivs->cap_num_i;
+
+ /* Tell kernel we want caps maintained across uid changes */
+ if ( prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1 )
+ {
+ zlog_err("privs_init: could not set PR_SET_KEEPCAPS, %s",
+ strerror (errno) );
+ exit(1);
+ }
+
+ if ( !zprivs_state.syscaps_p )
+ {
+ zlog_warn ("privs_init: capabilities enabled, but no capabilities supplied");
+ }
+
+ if ( !(zprivs_state.caps = cap_init()) )
+ {
+ zlog_err ("privs_init: failed to cap_init, %s", strerror (errno) );
+ exit (1);
+ }
+
+ /* we have caps, we have no need to ever change back the original user */
+ if (zprivs_state.zuid)
+ {
+ if ( setreuid (zprivs_state.zuid, zprivs_state.zuid) )
+ {
+ zlog_err ("privs_init (cap): could not setreuid, %s", strerror (errno) );
+ exit (1);
+ }
+ }
+
+ if ( cap_clear (zprivs_state.caps) )
+ {
+ zlog_err ("privs_init: failed to cap_clear, %s", strerror (errno));
+ exit (1);
+ }
+
+ /* set permitted caps */
+ cap_set_flag(zprivs_state.caps, CAP_PERMITTED,
+ zprivs_state.sys_num_p, zprivs_state.syscaps_p, CAP_SET);
+ cap_set_flag(zprivs_state.caps, CAP_EFFECTIVE,
+ zprivs_state.sys_num_p, zprivs_state.syscaps_p, CAP_SET);
+
+ /* set inheritable caps, if any */
+ if (zprivs_state.sys_num_i)
+ {
+ cap_set_flag(zprivs_state.caps, CAP_INHERITABLE,
+ zprivs_state.sys_num_i, zprivs_state.syscaps_i, CAP_SET);
+ }
+
+ /* apply caps. CAP_EFFECTIVE is cleared. we'll raise the caps as
+ * and when, and only when, they are needed.
+ */
+ if ( cap_set_proc (zprivs_state.caps) )
+ {
+ zlog_err ("privs_init: initial cap_set_proc failed");
+ exit (1);
+ }
+
+ /* set methods for the caller to use */
+ zprivs->change = zprivs_change_caps;
+ zprivs->current_state = zprivs_state_caps;
+
+#elif !defined(HAVE_LCAPS)
+ /* we dont have caps. we'll need to maintain rid and saved uid
+ * and change euid back to saved uid (who we presume has all neccessary
+ * privileges) whenever we are asked to raise our privileges.
+ */
+ zprivs_state.zsuid = geteuid();
+ if ( zprivs_state.zuid )
+ {
+ if ( setreuid (-1, zprivs_state.zuid) )
+ {
+ zlog_err ("privs_init (uid): could not setreuid, %s", strerror (errno));
+ exit (1);
+ }
+ }
+
+ zprivs->change = zprivs_change_uid;
+ zprivs->current_state = zprivs_state_uid;
+#endif /* HAVE_LCAPS */
+}
+
+void
+zprivs_terminate (void)
+{
+
+#ifdef HAVE_LCAPS
+
+ if (zprivs_state.caps)
+ cap_clear (zprivs_state.caps);
+
+ if ( cap_set_proc (zprivs_state.caps) )
+ {
+ zlog_err ("privs_terminate: cap_set_proc failed, %s",
+ strerror (errno) );
+ exit (1);
+ }
+
+ if (zprivs_state.sys_num_p)
+ XFREE (MTYPE_PRIVS, zprivs_state.syscaps_p);
+
+ if (zprivs_state.sys_num_i)
+ XFREE (MTYPE_PRIVS, zprivs_state.syscaps_i);
+
+ cap_free (zprivs_state.caps);
+#else
+ if (zprivs_state.zuid)
+ {
+ if ( setreuid (zprivs_state.zuid, zprivs_state.zuid) )
+ {
+ zlog_err ("privs_terminate: could not setreuid, %s",
+ strerror (errno) );
+ exit (1);
+ }
+ }
+#endif /* HAVE_LCAPS */
+ return;
+}
+
+void
+zprivs_get_ids(struct zprivs_ids_t *ids)
+{
+
+ ids->uid_priv = getuid();
+ (zprivs_state.zuid) ? (ids->uid_normal = zprivs_state.zuid)
+ : (ids->uid_normal = -1);
+ (zprivs_state.zgid) ? (ids->gid_normal = zprivs_state.zgid)
+ : (ids->gid_normal = -1);
+ (zprivs_state.vtygrp) ? (ids->gid_vty = zprivs_state.vtygrp)
+ : (ids->gid_vty = -1);
+
+ return;
+}
diff --git a/lib/privs.h b/lib/privs.h
new file mode 100644
index 00000000..65c9f358
--- /dev/null
+++ b/lib/privs.h
@@ -0,0 +1,91 @@
+/*
+ * Zebra privileges header.
+ *
+ * Copyright (C) 2003 Paul Jakma.
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra 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.
+ *
+ * GNU Zebra 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 _ZEBRA_PRIVS_H
+#define _ZEBRA_PRIVS_H
+
+/* list of zebra capabilities */
+typedef enum
+{
+ ZCAP_SETGID,
+ ZCAP_SETUID,
+ ZCAP_BIND,
+ ZCAP_BROADCAST,
+ ZCAP_ADMIN,
+ ZCAP_SYS_ADMIN,
+ ZCAP_RAW,
+ ZCAP_CHROOT,
+ ZCAP_NICE,
+ ZCAP_PTRACE,
+ ZCAP_DAC_OVERRIDE,
+ ZCAP_READ_SEARCH,
+ ZCAP_FOWNER,
+ ZCAP_MAX
+} zebra_capabilities_t;
+
+typedef enum
+{
+ ZPRIVS_LOWERED,
+ ZPRIVS_RAISED
+} zebra_privs_current_t;
+
+typedef enum
+{
+ ZPRIVS_RAISE,
+ ZPRIVS_LOWER,
+} zebra_privs_ops_t;
+
+struct zebra_privs_t
+{
+ zebra_capabilities_t *caps_p; /* caps required for operation */
+ zebra_capabilities_t *caps_i; /* caps to allow inheritance of */
+ int cap_num_p; /* number of caps in arrays */
+ int cap_num_i;
+ char *user; /* user and group to run as */
+ char *group;
+ char *vty_group; /* group to chown vty socket to */
+ /* methods */
+ int
+ (*change) (zebra_privs_ops_t); /* change privileges, 0 on success */
+ zebra_privs_current_t
+ (*current_state) (void); /* current privilege state */
+};
+
+struct zprivs_ids_t
+{
+ /* -1 is undefined */
+ uid_t uid_priv; /* privileged uid */
+ uid_t uid_normal; /* normal uid */
+ gid_t gid_priv; /* privileged uid */
+ gid_t gid_normal; /* normal uid */
+ gid_t gid_vty; /* vty gid */
+};
+
+ /* initialise zebra privileges */
+void zprivs_init (struct zebra_privs_t *zprivs);
+ /* drop all and terminate privileges */
+void zprivs_terminate (void);
+ /* query for runtime uid's and gid's, eg vty needs this */
+void zprivs_get_ids(struct zprivs_ids_t *);
+
+#endif /* _ZEBRA_PRIVS_H */
diff --git a/lib/vty.c b/lib/vty.c
index d31521cc..b583e443 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -33,6 +33,7 @@
#include "log.h"
#include "prefix.h"
#include "filter.h"
+#include "privs.h"
/* Vty events */
enum event
@@ -1776,14 +1777,37 @@ vty_serv_sock_addrinfo (const char *hostname, unsigned short port)
/* Make vty server socket. */
void
-vty_serv_sock_family (unsigned short port, int family)
+vty_serv_sock_family (const char* addr, unsigned short port, int family)
{
int ret;
union sockunion su;
int accept_sock;
+ void* naddr=NULL;
memset (&su, 0, sizeof (union sockunion));
su.sa.sa_family = family;
+ if(addr)
+ switch(family)
+ {
+ case AF_INET:
+ naddr=&su.sin.sin_addr;
+#ifdef HAVE_IPV6
+ case AF_INET6:
+ naddr=&su.sin6.sin6_addr;
+#endif
+ }
+
+ if(naddr)
+ switch(inet_pton(family,addr,naddr))
+ {
+ case -1:
+ zlog_err("bad address %s",addr);
+ naddr=NULL;
+ break;
+ case 0:
+ zlog_err("error translating address %s: %s",addr,strerror(errno));
+ naddr=NULL;
+ }
/* Make new socket. */
accept_sock = sockunion_stream_socket (&su);
@@ -1795,9 +1819,10 @@ vty_serv_sock_family (unsigned short port, int family)
sockopt_reuseport (accept_sock);
/* Bind socket to universal address and given port. */
- ret = sockunion_bind (accept_sock, &su, port, NULL);
+ ret = sockunion_bind (accept_sock, &su, port, naddr);
if (ret < 0)
{
+ zlog_warn("can't bind socket");
close (accept_sock); /* Avoid sd leak. */
return;
}
@@ -1827,12 +1852,13 @@ vty_serv_un (char *path)
int sock, len;
struct sockaddr_un serv;
mode_t old_mask;
-
+ struct zprivs_ids_t ids;
+
/* First of all, unlink existing socket */
unlink (path);
/* Set umask */
- old_mask = umask (0077);
+ old_mask = umask (0007);
/* Make UNIX domain socket. */
sock = socket (AF_UNIX, SOCK_STREAM, 0);
@@ -1870,6 +1896,18 @@ vty_serv_un (char *path)
umask (old_mask);
+ zprivs_get_ids(&ids);
+
+ if (ids.gid_vty > 0)
+ {
+ /* set group of socket */
+ if ( chown (path, -1, ids.gid_vty) )
+ {
+ zlog_err ("vty_serv_un: could chown socket, %s",
+ strerror (errno) );
+ }
+ }
+
vty_event (VTYSH_SERV, sock, NULL);
}
@@ -1966,7 +2004,7 @@ vtysh_read (struct thread *thread)
/* Determine address family to bind. */
void
-vty_serv_sock (const char *hostname, unsigned short port, char *path)
+vty_serv_sock (const char *addr, unsigned short port, char *path)
{
/* If port is set to 0, do not listen on TCP/IP at all! */
if (port)
@@ -1974,19 +2012,19 @@ vty_serv_sock (const char *hostname, unsigned short port, char *path)
#ifdef HAVE_IPV6
#ifdef NRL
- vty_serv_sock_family (port, AF_INET);
- vty_serv_sock_family (port, AF_INET6);
+ vty_serv_sock_family (addr, port, AF_INET);
+ vty_serv_sock_family (addr, port, AF_INET6);
#else /* ! NRL */
- vty_serv_sock_addrinfo (hostname, port);
+ vty_serv_sock_addrinfo (addr, port);
#endif /* NRL*/
#else /* ! HAVE_IPV6 */
- vty_serv_sock_family (port, AF_INET);
+ vty_serv_sock_family (addr,port, AF_INET);
#endif /* HAVE_IPV6 */
}
#ifdef VTYSH
vty_serv_un (path);
-#endif /* VTYSH */
+#endif /* VTYSH */v
}
/* Close vty interface. */
diff --git a/lib/zebra.h b/lib/zebra.h
index a34f5d4a..c9aaf70d 100644
--- a/lib/zebra.h
+++ b/lib/zebra.h
@@ -45,6 +45,8 @@ typedef int socklen_t;
#include <fcntl.h>
#include <signal.h>
#include <string.h>
+#include <pwd.h>
+#include <grp.h>
#ifdef HAVE_STROPTS_H
#include <stropts.h>
#endif /* HAVE_STROPTS_H */
@@ -73,6 +75,10 @@ typedef int socklen_t;
#ifdef HAVE_RUSAGE
#include <sys/resource.h>
#endif /* HAVE_RUSAGE */
+#ifdef HAVE_LCAPS
+#include <sys/capability.h>
+#include <sys/prctl.h>
+#endif /* HAVE_LCAPS */
/* machine dependent includes */
#ifdef SUNOS_5
diff --git a/ospf6d/Makefile.am b/ospf6d/Makefile.am
index e1b78cbc..b13942be 100644
--- a/ospf6d/Makefile.am
+++ b/ospf6d/Makefile.am
@@ -28,7 +28,7 @@ noinst_HEADERS = \
ospf6d_SOURCES = \
ospf6_main.c $(libospf6_a_SOURCES)
-ospf6d_LDADD = ../lib/libzebra.a
+ospf6d_LDADD = ../lib/libzebra.a @LIBCAP@
sysconf_DATA = ospf6d.conf.sample
diff --git a/ospf6d/ospf6_main.c b/ospf6d/ospf6_main.c
index 5ab517f3..7ed0030e 100644
--- a/ospf6d/ospf6_main.c
+++ b/ospf6d/ospf6_main.c
@@ -27,6 +27,7 @@
#include "command.h"
#include "vty.h"
#include "memory.h"
+#include "privs.h"
#include "ospf6d.h"
#include "ospf6_network.h"
@@ -43,6 +44,26 @@ extern int ospf6_sock;
/* Default port values. */
#define OSPF6_VTY_PORT 2606
+/* ospf6d privileges */
+zebra_capabilities_t _caps_p [] =
+{
+ ZCAP_RAW,
+ ZCAP_BIND
+};
+
+struct zebra_privs_t ospf6d_privs =
+{
+#if defined(ZEBRA_USER)
+ .user = ZEBRA_USER,
+#endif
+#if defined ZEBRA_GROUP
+ .group = ZEBRA_GROUP,
+#endif
+ .caps_p = _caps_p,
+ .cap_num_p = 2,
+ .cap_num_i = 0
+};
+
/* ospf6d options, we use GNU getopt library. */
struct option longopts[] =
{
@@ -51,6 +72,7 @@ struct option longopts[] =
{ "pid_file", required_argument, NULL, 'i'},
{ "vty_addr", required_argument, NULL, 'A'},
{ "vty_port", required_argument, NULL, 'P'},
+ { "user", required_argument, NULL, 'u'},
{ "version", no_argument, NULL, 'v'},
{ "help", no_argument, NULL, 'h'},
{ 0 }
@@ -93,6 +115,7 @@ Daemon which manages OSPF version 3.\n\n\
-i, --pid_file Set process identifier file name\n\
-A, --vty_addr Set vty's bind address\n\
-P, --vty_port Set vty's port number\n\
+-u, --user User and group to run as\n\
-v, --version Print program version\n\
-h, --help Display this help and exit\n\
\n\
@@ -206,7 +229,7 @@ main (int argc, char *argv[], char *envp[])
char *p;
int opt;
char *vty_addr = NULL;
- int vty_port = 0;
+ int vty_port = OSPF6_VTY_PORT;
char *config_file = NULL;
char *progname;
struct thread thread;
@@ -231,7 +254,7 @@ main (int argc, char *argv[], char *envp[])
/* Command line argument treatment. */
while (1)
{
- opt = getopt_long (argc, argv, "df:hp:A:P:v", longopts, 0);
+ opt = getopt_long (argc, argv, "df:hp:A:P:u:v", longopts, 0);
if (opt == EOF)
break;
@@ -253,7 +276,18 @@ main (int argc, char *argv[], char *envp[])
pid_file = optarg;
break;
case 'P':
+ /* Deal with atoi() returning 0 on failure, and ospf6d not
+ listening on ospf6d port... */
+ if (strcmp(optarg, "0") == 0)
+ {
+ vty_port = 0;
+ break;
+ }
vty_port = atoi (optarg);
+ vty_port = (vty_port ? vty_port : OSPF6_VTY_PORT);
+ break;
+ case 'u':
+ ospf6d_privs.user = ospf6d_privs.group = optarg;
break;
case 'v':
print_version (progname);
@@ -280,6 +314,7 @@ main (int argc, char *argv[], char *envp[])
zlog_default = openzlog (progname, flag, ZLOG_OSPF6,
LOG_CONS|LOG_NDELAY|LOG_PERROR|LOG_PID,
LOG_DAEMON);
+ zprivs_init (&ospf6d_privs);
signal_init ();
cmd_init (1);
vty_init ();
@@ -305,8 +340,7 @@ main (int argc, char *argv[], char *envp[])
thread_add_read (master, ospf6_receive, NULL, ospf6_sock);
/* Make ospf vty socket. */
- vty_serv_sock (vty_addr,
- vty_port ? vty_port : OSPF6_VTY_PORT, OSPF6_VTYSH_PATH);
+ vty_serv_sock (vty_addr, vty_port, OSPF6_VTYSH_PATH);
/* Print start message */
zlog_notice ("OSPF6d (Zebra-%s ospf6d-%s) starts",
diff --git a/ospf6d/ospf6_network.c b/ospf6d/ospf6_network.c
index 041d829b..9b98f808 100644
--- a/ospf6d/ospf6_network.c
+++ b/ospf6d/ospf6_network.c
@@ -23,6 +23,7 @@
#include "memory.h"
#include "log.h"
#include "sockunion.h"
+#include "privs.h"
#include "ospf6d.h"
#include "ospf6_proto.h"
@@ -32,6 +33,7 @@ extern struct sockaddr_in6 allspfrouters6;
extern struct sockaddr_in6 alldrouters6;
extern int ospf6_sock;
extern struct thread_master *master;
+extern struct zebra_privs_t ospf6d_privs;
/* iovec functions */
void
@@ -194,6 +196,10 @@ iov_copy_all (struct iovec *dst, struct iovec *src, size_t size)
int
ospf6_serv_sock ()
{
+
+ if (ospf6d_privs.change (ZPRIVS_RAISE))
+ zlog_err ("ospf6_serv_sock: could not raise privs");
+
ospf6_sock = socket (AF_INET6, SOCK_RAW, IPPROTO_OSPFIGP);
if (ospf6_sock < 0)
{
@@ -202,6 +208,9 @@ ospf6_serv_sock ()
}
sockopt_reuseaddr (ospf6_sock);
+ if (ospf6d_privs.change (ZPRIVS_LOWER))
+ zlog_err ("ospf_sock_init: could not lower privs");
+
/* setup global sockaddr_in6, allspf6 & alldr6 for later use */
allspfrouters6.sin6_family = AF_INET6;
alldrouters6.sin6_family = AF_INET6;
diff --git a/ospfclient/Makefile.am b/ospfclient/Makefile.am
new file mode 100644
index 00000000..fb041af9
--- /dev/null
+++ b/ospfclient/Makefile.am
@@ -0,0 +1,21 @@
+## Automake.am for OSPF API client
+
+INCLUDES = -I../lib -I../
+
+lib_LIBRARIES = libospfapiclient.a
+sbin_PROGRAMS = ospfclient
+
+libospfapiclient_a_SOURCES = \
+ ospf_apiclient.c
+
+ospfapiheaderdir = $(includedir)/ospfapi
+
+ospfapiheader_HEADERS = \
+ ospf_apiclient.h
+
+ospfclient_SOURCES = \
+ ospfclient.c $(libospfapiclient_a_SOURCES)
+
+ospfclient_LDADD = ../ospfd/libospf.a ../lib/libzebra.a @LIBCAP@
+
+
diff --git a/ospfclient/ospfclient.c b/ospfclient/ospfclient.c
new file mode 100644
index 00000000..28010872
--- /dev/null
+++ b/ospfclient/ospfclient.c
@@ -0,0 +1,333 @@
+/*
+ * Simple program to demonstrate how OSPF API can be used. This
+ * application retrieves the LSDB from the OSPF daemon and then
+ * originates, updates and finally deletes an application-specific
+ * opaque LSA. You can use this application as a template when writing
+ * your own application.
+ */
+
+/* The following includes are needed in all OSPF API client
+ applications. */
+
+#include <zebra.h>
+#include "prefix.h" /* needed by ospf_asbr.h */
+#include "privs.h"
+
+#include "ospfd/ospfd.h"
+#include "ospfd/ospf_asbr.h"
+#include "ospfd/ospf_lsa.h"
+#include "ospfd/ospf_opaque.h"
+#include "ospfd/ospf_api.h"
+#include "ospf_apiclient.h"
+
+/* privileges struct.
+ * set cap_num_* and uid/gid to nothing to use NULL privs
+ * as ospfapiclient links in libospf.a which uses privs.
+ */
+struct zebra_privs_t ospfd_privs =
+{
+ .user = NULL,
+ .group = NULL,
+ .cap_num_p = 0,
+ .cap_num_i = 0
+};
+
+/* The following includes are specific to this application. For
+ example it uses threads from libzebra, however your application is
+ free to use any thread library (like pthreads). */
+
+#include "ospfd/ospf_dump.h" /* for ospf_lsa_header_dump */
+#include "thread.h"
+#include "log.h"
+
+/* Local portnumber for async channel. Note that OSPF API library will also
+ allocate a sync channel at ASYNCPORT+1. */
+#define ASYNCPORT 4000
+
+/* Master thread */
+struct thread_master *master;
+
+/* Global variables */
+struct ospf_apiclient *oclient;
+char **args;
+
+/* Our opaque LSAs have the following format. */
+struct my_opaque_lsa
+{
+ struct lsa_header hdr; /* include common LSA header */
+ u_char data[4]; /* our own data format then follows here */
+};
+
+
+/* ---------------------------------------------------------
+ * Threads for asynchronous messages and LSA update/delete
+ * ---------------------------------------------------------
+ */
+
+int
+lsa_delete (struct thread *t)
+{
+ struct ospf_apiclient *oclient;
+ struct in_addr area_id;
+ int rc;
+
+ oclient = THREAD_ARG (t);
+
+ inet_aton (args[6], &area_id);
+
+ printf ("Deleting LSA... ");
+ rc = ospf_apiclient_lsa_delete (oclient,
+ area_id,
+ atoi (args[2]), /* lsa type */
+ atoi (args[3]), /* opaque type */
+ atoi (args[4])); /* opaque ID */
+ printf ("done, return code is = %d\n", rc);
+ return rc;
+}
+
+int
+lsa_inject (struct thread *t)
+{
+ struct ospf_apiclient *cl;
+ struct in_addr ifaddr;
+ struct in_addr area_id;
+ u_char lsa_type;
+ u_char opaque_type;
+ u_int32_t opaque_id;
+ void *opaquedata;
+ int opaquelen;
+
+ static u_int32_t counter = 1; /* Incremented each time invoked */
+ int rc;
+
+ cl = THREAD_ARG (t);
+
+ inet_aton (args[5], &ifaddr);
+ inet_aton (args[6], &area_id);
+ lsa_type = atoi (args[2]);
+ opaque_type = atoi (args[3]);
+ opaque_id = atoi (args[4]);
+ opaquedata = &counter;
+ opaquelen = sizeof (u_int32_t);
+
+ printf ("Originating/updating LSA with counter=%d... ", counter);
+ rc = ospf_apiclient_lsa_originate(cl, ifaddr, area_id,
+ lsa_type,
+ opaque_type, opaque_id,
+ opaquedata, opaquelen);
+
+ printf ("done, return code is %d\n", rc);
+
+ counter++;
+
+ return 0;
+};
+
+
+/* This thread handles asynchronous messages coming in from the OSPF
+ API server */
+int
+lsa_read (struct thread *thread)
+{
+ struct ospf_apiclient *oclient;
+ int fd;
+ int ret;
+
+ printf ("lsa_read called\n");
+
+ oclient = THREAD_ARG (thread);
+ fd = THREAD_FD (thread);
+
+ /* Handle asynchronous message */
+ ret = ospf_apiclient_handle_async (oclient);
+ if (ret < 0) {
+ printf ("Connection closed, exiting...");
+ exit(0);
+ }
+
+ /* Reschedule read thread */
+ thread_add_read (master, lsa_read, oclient, fd);
+
+ return 0;
+}
+
+/* ---------------------------------------------------------
+ * Callback functions for asynchronous events
+ * ---------------------------------------------------------
+ */
+
+void
+lsa_update_callback (struct in_addr ifaddr, struct in_addr area_id,
+ u_char is_self_originated,
+ struct lsa_header *lsa)
+{
+ printf ("lsa_update_callback: ");
+ printf ("ifaddr: %s ", inet_ntoa (ifaddr));
+ printf ("area: %s\n", inet_ntoa (area_id));
+ printf ("is_self_origin: %u\n", is_self_originated);
+
+ /* It is important to note that lsa_header does indeed include the
+ header and the LSA payload. To access the payload, first check
+ the LSA type and then typecast lsa into the corresponding type,
+ e.g.:
+
+ if (lsa->type == OSPF_ROUTER_LSA) {
+ struct router_lsa *rl = (struct router_lsa) lsa;
+ ...
+ u_int16_t links = rl->links;
+ ...
+ }
+ */
+
+ ospf_lsa_header_dump (lsa);
+}
+
+void
+lsa_delete_callback (struct in_addr ifaddr, struct in_addr area_id,
+ u_char is_self_originated,
+ struct lsa_header *lsa)
+{
+ printf ("lsa_delete_callback: ");
+ printf ("ifaddr: %s ", inet_ntoa (ifaddr));
+ printf ("area: %s\n", inet_ntoa (area_id));
+ printf ("is_self_origin: %u\n", is_self_originated);
+
+ ospf_lsa_header_dump (lsa);
+}
+
+void
+ready_callback (u_char lsa_type, u_char opaque_type, struct in_addr addr)
+{
+ printf ("ready_callback: lsa_type: %d opaque_type: %d addr=%s\n",
+ lsa_type, opaque_type, inet_ntoa (addr));
+
+ /* Schedule opaque LSA originate in 5 secs */
+ thread_add_timer (master, lsa_inject, oclient, 5);
+
+ /* Schedule opaque LSA update with new value */
+ thread_add_timer (master, lsa_inject, oclient, 10);
+
+ /* Schedule delete */
+ thread_add_timer (master, lsa_delete, oclient, 30);
+}
+
+void
+new_if_callback (struct in_addr ifaddr, struct in_addr area_id)
+{
+ printf ("new_if_callback: ifaddr: %s ", inet_ntoa (ifaddr));
+ printf ("area_id: %s\n", inet_ntoa (area_id));
+}
+
+void
+del_if_callback (struct in_addr ifaddr)
+{
+ printf ("new_if_callback: ifaddr: %s\n ", inet_ntoa (ifaddr));
+}
+
+void
+ism_change_callback (struct in_addr ifaddr, struct in_addr area_id,
+ u_char state)
+{
+ printf ("ism_change: ifaddr: %s ", inet_ntoa (ifaddr));
+ printf ("area_id: %s\n", inet_ntoa (area_id));
+ printf ("state: %d [%s]\n", state, LOOKUP (ospf_ism_state_msg, state));
+}
+
+void
+nsm_change_callback (struct in_addr ifaddr, struct in_addr nbraddr,
+ struct in_addr router_id, u_char state)
+{
+ printf ("nsm_change: ifaddr: %s ", inet_ntoa (ifaddr));
+ printf ("nbraddr: %s\n", inet_ntoa (nbraddr));
+ printf ("router_id: %s\n", inet_ntoa (router_id));
+ printf ("state: %d [%s]\n", state, LOOKUP (ospf_nsm_state_msg, state));
+}
+
+
+/* ---------------------------------------------------------
+ * Main program
+ * ---------------------------------------------------------
+ */
+
+int usage()
+{
+ printf("Usage: ospfclient <ospfd> <lsatype> <opaquetype> <opaqueid> <ifaddr> <areaid>\n");
+ printf("where ospfd : router where API-enabled OSPF daemon is running\n");
+ printf(" lsatype : either 9, 10, or 11 depending on flooding scope\n");
+ printf(" opaquetype: 0-255 (e.g., experimental applications use > 128)\n");
+ printf(" opaqueid : arbitrary application instance (24 bits)\n");
+ printf(" ifaddr : interface IP address (for type 9) otherwise ignored\n");
+ printf(" areaid : area in IP address format (for type 10) otherwise ignored\n");
+
+ exit(1);
+}
+
+int
+main (int argc, char *argv[])
+{
+ struct thread thread;
+
+ args = argv;
+
+ /* ospfclient should be started with the following arguments:
+ *
+ * (1) host (2) lsa_type (3) opaque_type (4) opaque_id (5) if_addr
+ * (6) area_id
+ *
+ * host: name or IP of host where ospfd is running
+ * lsa_type: 9, 10, or 11
+ * opaque_type: 0-255 (e.g., experimental applications use > 128)
+ * opaque_id: arbitrary application instance (24 bits)
+ * if_addr: interface IP address (for type 9) otherwise ignored
+ * area_id: area in IP address format (for type 10) otherwise ignored
+ */
+
+ if (argc != 7)
+ {
+ usage();
+ }
+
+ /* Initialization */
+ zprivs_init (&ospfd_privs);
+ master = thread_master_create ();
+
+ /* Open connection to OSPF daemon */
+ oclient = ospf_apiclient_connect (args[1], ASYNCPORT);
+ if (!oclient)
+ {
+ printf ("Connecting to OSPF daemon on %s failed!\n",
+ args[1]);
+ exit (1);
+ }
+
+ /* Register callback functions. */
+ ospf_apiclient_register_callback (oclient,
+ ready_callback,
+ new_if_callback,
+ del_if_callback,
+ ism_change_callback,
+ nsm_change_callback,
+ lsa_update_callback,
+ lsa_delete_callback);
+
+ /* Register LSA type and opaque type. */
+ ospf_apiclient_register_opaque_type (oclient, atoi (args[2]),
+ atoi (args[3]));
+
+ /* Synchronize database with OSPF daemon. */
+ ospf_apiclient_sync_lsdb (oclient);
+
+ /* Schedule thread that handles asynchronous messages */
+ thread_add_read (master, lsa_read, oclient, oclient->fd_async);
+
+ /* Now connection is established, run loop */
+ while (1)
+ {
+ thread_fetch (master, &thread);
+ thread_call (&thread);
+ }
+
+ /* Never reached */
+ return 0;
+}
+
diff --git a/ospfd/Makefile.am b/ospfd/Makefile.am
index 2b905804..dd0a0922 100644
--- a/ospfd/Makefile.am
+++ b/ospfd/Makefile.am
@@ -4,7 +4,7 @@ INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib
DEFS = @DEFS@ $(LOCAL_OPTS) -DSYSCONFDIR=\"$(sysconfdir)/\"
INSTALL_SDATA=@INSTALL@ -m 600
-noinst_LIBRARIES = libospf.a
+lib_LIBRARIES = libospf.a
sbin_PROGRAMS = ospfd
libospf_a_SOURCES = \
@@ -12,19 +12,23 @@ libospf_a_SOURCES = \
ospf_nsm.c ospf_dump.c ospf_network.c ospf_packet.c ospf_lsa.c \
ospf_spf.c ospf_route.c ospf_ase.c ospf_abr.c ospf_ia.c ospf_flood.c \
ospf_lsdb.c ospf_asbr.c ospf_routemap.c ospf_snmp.c \
- ospf_opaque.c ospf_te.c ospf_vty.c
+ ospf_opaque.c ospf_te.c ospf_vty.c ospf_api.c ospf_apiserver.c
+
+ospfdheaderdir = $(includedir)/ospfd
+
+ospfdheader_HEADERS = \
+ ospf_api.h ospf_asbr.h ospf_dump.h ospf_lsa.h ospf_lsdb.h \
+ ospf_nsm.h ospf_ism.h ospf_opaque.h ospfd.h
noinst_HEADERS = \
- ospf_dump.h ospf_interface.h ospf_ism.h ospf_neighbor.h \
- ospf_network.h ospf_nsm.h ospf_packet.h ospf_zebra.h ospfd.h \
- ospf_lsa.h ospf_spf.h ospf_route.h ospf_ase.h ospf_abr.h ospf_ia.h \
- ospf_flood.h ospf_lsdb.h ospf_asbr.h ospf_snmp.h ospf_opaque.h \
- ospf_te.h ospf_vty.h
+ ospf_interface.h ospf_neighbor.h ospf_network.h ospf_packet.h \
+ ospf_zebra.h ospf_spf.h ospf_route.h ospf_ase.h ospf_abr.h ospf_ia.h \
+ ospf_flood.h ospf_snmp.h ospf_te.h ospf_vty.h ospf_apiserver.h
ospfd_SOURCES = \
ospf_main.c $(libospf_a_SOURCES)
-ospfd_LDADD = ../lib/libzebra.a
+ospfd_LDADD = ../lib/libzebra.a @LIBCAP@
sysconf_DATA = ospfd.conf.sample
diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c
index e649c17b..12415453 100644
--- a/ospfd/ospf_main.c
+++ b/ospfd/ospf_main.c
@@ -36,6 +36,7 @@
#include "stream.h"
#include "log.h"
#include "memory.h"
+#include "privs.h"
#include "ospfd/ospfd.h"
#include "ospfd/ospf_interface.h"
@@ -47,6 +48,28 @@
#include "ospfd/ospf_zebra.h"
#include "ospfd/ospf_vty.h"
+/* ospfd privileges */
+zebra_capabilities_t _caps_p [] =
+{
+ ZCAP_RAW,
+ ZCAP_BIND,
+ ZCAP_BROADCAST,
+ CAP_NET_ADMIN
+};
+
+struct zebra_privs_t ospfd_privs =
+{
+#if defined(ZEBRA_USER)
+ .user = ZEBRA_USER,
+#endif
+#if defined ZEBRA_GROUP
+ .group = ZEBRA_GROUP,
+#endif
+ .caps_p = _caps_p,
+ .cap_num_p = sizeof(_caps_p)/sizeof(_caps_p[0]),
+ .cap_num_i = 0
+};
+
/* Configuration filename and directory. */
char config_current[] = OSPF_DEFAULT_CONFIG;
char config_default[] = SYSCONFDIR OSPF_DEFAULT_CONFIG;
@@ -61,6 +84,7 @@ struct option longopts[] =
{ "help", no_argument, NULL, 'h'},
{ "vty_addr", required_argument, NULL, 'A'},
{ "vty_port", required_argument, NULL, 'P'},
+ { "user", required_argument, NULL, 'u'},
{ "version", no_argument, NULL, 'v'},
{ 0 }
};
@@ -88,6 +112,7 @@ Daemon which manages OSPF.\n\n\
-i, --pid_file Set process identifier file name\n\
-A, --vty_addr Set vty's bind address\n\
-P, --vty_port Set vty's port number\n\
+-u, --user User and group to run as\n\
-v, --version Print program version\n\
-h, --help Display this help and exit\n\
\n\
@@ -170,7 +195,7 @@ main (int argc, char **argv)
{
char *p;
char *vty_addr = NULL;
- int vty_port = 0;
+ int vty_port = OSPF_VTY_PORT;
int daemon_mode = 0;
char *config_file = NULL;
char *progname;
@@ -222,8 +247,19 @@ main (int argc, char **argv)
pid_file = optarg;
break;
case 'P':
- vty_port = atoi (optarg);
- break;
+ /* Deal with atoi() returning 0 on failure, and ospfd not
+ listening on ospfd port... */
+ if (strcmp(optarg, "0") == 0)
+ {
+ vty_port = 0;
+ break;
+ }
+ vty_port = atoi (optarg);
+ vty_port = (vty_port ? vty_port : OSPF_VTY_PORT);
+ break;
+ case 'u':
+ ospfd_privs.group = ospfd_privs.user = optarg;
+ break;
case 'v':
print_version (progname);
exit (0);
@@ -241,6 +277,7 @@ main (int argc, char **argv)
master = om->master;
/* Library inits. */
+ zprivs_init (&ospfd_privs);
signal_init ();
cmd_init (1);
debug_init ();
@@ -280,8 +317,7 @@ main (int argc, char **argv)
pid_output (pid_file);
/* Create VTY socket */
- vty_serv_sock (vty_addr,
- vty_port ? vty_port : OSPF_VTY_PORT, OSPF_VTYSH_PATH);
+ vty_serv_sock (vty_addr, vty_port, OSPF_VTYSH_PATH);
/* Print banner. */
zlog (NULL, LOG_INFO, "OSPFd (%s) starts", ZEBRA_VERSION);
diff --git a/ospfd/ospf_network.c b/ospfd/ospf_network.c
index 56ec8647..9d3bed11 100644
--- a/ospfd/ospf_network.c
+++ b/ospfd/ospf_network.c
@@ -29,6 +29,9 @@
#include "sockunion.h"
#include "log.h"
#include "sockopt.h"
+#include "privs.h"
+
+extern struct zebra_privs_t ospfd_privs;
#include "ospfd/ospfd.h"
#include "ospfd/ospf_network.h"
@@ -39,6 +42,8 @@
#include "ospfd/ospf_neighbor.h"
#include "ospfd/ospf_packet.h"
+
+
/* Join to the OSPF ALL SPF ROUTERS multicast group. */
int
ospf_if_add_allspfrouters (struct ospf *top, struct prefix *p,
@@ -151,12 +156,16 @@ ospf_sock_init (void)
int ospf_sock;
int ret, tos, hincl = 1;
+ if (ospfd_privs.change (ZPRIVS_RAISE))
+ zlog_err ("ospf_sock_init: could not raise privs");
+
ospf_sock = socket (AF_INET, SOCK_RAW, IPPROTO_OSPFIGP);
if (ospf_sock < 0)
{
zlog_warn ("ospf_read_sock_init: socket: %s", strerror (errno));
return -1;
}
+
/* Set precedence field. */
#ifdef IPTOS_PREC_INTERNETCONTROL
@@ -187,6 +196,9 @@ ospf_sock_init (void)
#else
#warning "cannot be able to receive link information on this OS"
#endif
+
+ if (ospfd_privs.change (ZPRIVS_LOWER))
+ zlog_err ("ospf_sock_init: could not lower privs");
return ospf_sock;
}
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index 9b6b4877..a12a0115 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -53,6 +53,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "ospfd/ospf_ase.h"
+
/* OSPF process wide configuration. */
static struct ospf_master ospf_master;
@@ -516,9 +517,6 @@ ospf_area_free (struct ospf_area *area)
ospf_lsdb_delete_all (area->lsdb);
ospf_lsdb_free (area->lsdb);
-#ifdef HAVE_OPAQUE_LSA
- ospf_opaque_type10_lsa_term (area);
-#endif /* HAVE_OPAQUE_LSA */
ospf_lsa_unlock (area->router_lsa_self);
route_table_finish (area->ranges);
@@ -637,7 +635,7 @@ ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p,
struct ospf_area *area;
struct route_node *rn;
struct external_info *ei;
- int ret = OSPF_AREA_ID_FORMAT_DECIMAL;
+ int ret = OSPF_AREA_ID_FORMAT_ADDRESS;
rn = route_node_get (ospf->networks, (struct prefix *)p);
if (rn->info)
@@ -704,7 +702,25 @@ ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p,
return 1;
}
-
+/* Check whether interface matches given network
+ * returns: 1, true. 0, false
+ */
+int
+ospf_network_match_iface(struct connected *co, struct prefix *net)
+{
+ /* Behaviour to match both Cisco where:
+ * iface address lies within network specified -> ospf
+ * and zebra 0.9[2ish-3]:
+ * PtP special case: network specified == iface peer addr -> ospf
+ */
+ return (
+ ((ifc_pointopoint (co) &&
+ IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4)))
+ || prefix_match (net, co->address))
+ ? 1 : 0
+ );
+}
+
void
ospf_network_run (struct ospf *ospf, struct prefix *p, struct ospf_area *area)
{
@@ -736,19 +752,21 @@ ospf_network_run (struct ospf *ospf, struct prefix *p, struct ospf_area *area)
{
struct connected *co = getdata (cn);
struct prefix *addr;
+
+ if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
+ continue;
- if (if_is_pointopoint (ifp))
+ if (ifc_pointopoint (co))
addr = co->destination;
else
addr = co->address;
- if (p->family == co->address->family &&
- ! ospf_if_is_configured (ospf, &(addr->u.prefix4)))
- if ((if_is_pointopoint (ifp) &&
- IPV4_ADDR_SAME (&(addr->u.prefix4), &(p->u.prefix4))) ||
- prefix_match (p, addr))
+ if (p->family == co->address->family
+ && ! ospf_if_is_configured (ospf, &(addr->u.prefix4))
+ && ospf_network_match_iface(co,p))
{
- struct ospf_interface *oi;
+ struct ospf_interface *oi;
+ assert(co);
oi = ospf_if_new (ospf, ifp, co->address);
oi->connected = co;
@@ -799,7 +817,7 @@ ospf_network_run (struct ospf *ospf, struct prefix *p, struct ospf_area *area)
ospf_area_add_if (oi->area, oi);
- if (if_is_up (ifp))
+ if (if_is_operative (ifp))
ospf_if_up (oi);
break;
@@ -873,10 +891,7 @@ ospf_if_update (struct ospf *ospf)
if (rn->info == NULL)
continue;
- if ((oi->type == OSPF_IFTYPE_POINTOPOINT
- && IPV4_ADDR_SAME (&(co->destination->u.prefix4),
- &(rn->p.u.prefix4)))
- || prefix_match (&(rn->p), co->address))
+ if (ospf_network_match_iface(co,&rn->p))
{
found = 1;
route_unlock_node (rn);
@@ -1032,7 +1047,7 @@ int
ospf_area_stub_set (struct ospf *ospf, struct in_addr area_id)
{
struct ospf_area *area;
- int format = OSPF_AREA_ID_FORMAT_DECIMAL;
+ int format = OSPF_AREA_ID_FORMAT_ADDRESS;
area = ospf_area_get (ospf, area_id, format);
if (ospf_area_vlink_count (ospf, area))
@@ -1065,7 +1080,7 @@ int
ospf_area_no_summary_set (struct ospf *ospf, struct in_addr area_id)
{
struct ospf_area *area;
- int format = OSPF_AREA_ID_FORMAT_DECIMAL;
+ int format = OSPF_AREA_ID_FORMAT_ADDRESS;
area = ospf_area_get (ospf, area_id, format);
area->no_summary = 1;
@@ -1092,7 +1107,7 @@ int
ospf_area_nssa_set (struct ospf *ospf, struct in_addr area_id)
{
struct ospf_area *area;
- int format = OSPF_AREA_ID_FORMAT_DECIMAL;
+ int format = OSPF_AREA_ID_FORMAT_ADDRESS;
area = ospf_area_get (ospf, area_id, format);
if (ospf_area_vlink_count (ospf, area))
diff --git a/redhat/zebra.pam b/redhat/zebra.pam
new file mode 100644
index 00000000..1390edf4
--- /dev/null
+++ b/redhat/zebra.pam
@@ -0,0 +1,26 @@
+#%PAM-1.0
+#
+
+##### if running zebra as root:
+# Only allow root (and possibly wheel) to use this because enable access
+# is unrestricted.
+# auth sufficient /lib/security/pam_rootok.so
+
+# Uncomment the following line to implicitly trust users in the "wheel" group.
+#auth sufficient /lib/security/pam_wheel.so trust use_uid
+# Uncomment the following line to require a user to be in the "wheel" group.
+#auth required /lib/security/pam_wheel.so use_uid
+###########################################################
+
+# If using zebra privileges and with a seperate group for vty access, then
+# access can be controlled via the vty access group, and pam can simply
+# check for valid user/password
+#
+# only allow local users.
+auth required /lib/security/pam_securetty.so
+auth required /lib/security/pam_stack.so service=system-auth
+auth required /lib/security/pam_nologin.so
+account required /lib/security/pam_stack.so service=system-auth
+password required /lib/security/pam_stack.so service=system-auth
+session required /lib/security/pam_stack.so service=system-auth
+session optional /lib/security/pam_console.so
diff --git a/redhat/zebra.spec.in b/redhat/zebra.spec.in
new file mode 100644
index 00000000..c6e6cef9
--- /dev/null
+++ b/redhat/zebra.spec.in
@@ -0,0 +1,372 @@
+# configure options
+%define with_snmp 0
+%define with_vtysh 1
+%define with_ospf_te 1
+%define with_nssa 1
+%define with_opaque_lsa 1
+%define with_tcp_zebra 0
+%define with_vtysh 1
+%define with_pam 1
+%define with_ipv6 1
+%define with_ospfclient 1
+%define with_ospfapi 1
+%define with_multipath 64
+%define zebra_user zebra
+%define vty_group zebravty
+
+# path defines
+%define _sysconfdir /etc/zebra
+%define zeb_src %{_builddir}/%{name}-%{version}
+%define zeb_rh_src %{zeb_src}/redhat
+%define zeb_docs %{zeb_src}/doc
+
+# defines for configure
+%define _libexecdir %{_exec_prefix}/libexec/zebra
+%define _includedir %{_prefix}/include/zebra
+%define _libdir %{_exec_prefix}/%{_lib}/zebra
+%define _localstatedir /var/run/zebra
+
+Summary: Routing daemon
+Name: zebra
+Version: @VERSION@
+Release: @CONFDATE@01
+License: GPL
+Group: System Environment/Daemons
+Source0: ftp://ftp.zebra.org/pub/zebra/%{name}-%{version}.tar.gz
+URL: http://www.zebra.org/
+%if %with_snmp
+#BuildRequires: ucd-snmp-devel
+Prereq: ucd-snmp
+%endif
+%if %with_vtysh
+BuildRequires: readline readline-devel ncurses ncurses-devel
+Prereq: readline ncurses
+%endif
+BuildRequires: texinfo tetex autoconf openssl-devel pam-devel patch
+# Initscripts > 5.60 is required for IPv6 support
+Prereq: initscripts >= 5.60
+Prereq: openssl ncurses readline pam
+Prereq: /sbin/install-info
+Provides: routingdaemon
+BuildRoot: %{_tmppath}/%{name}-%{version}-root
+Obsoletes: bird gated mrt
+
+%description
+GNU Zebra is a free software that manages TCP/IP based routing
+protocol. It takes multi-server and multi-thread approach to resolve
+the current complexity of the Internet.
+
+GNU Zebra supports BGP4, BGP4+, OSPFv2, OSPFv3, RIPv1, RIPv2, and RIPng.
+
+GNU Zebra is intended to be used as a Route Server and a Route
+Reflector. It is not a toolkit, it provides full routing power under
+a new architecture. GNU Zebra is unique in design in that it has a
+process for each protocol.
+
+%package contrib
+Summary: contrib tools for zebra
+Group: System Environment/Daemons
+
+%description contrib
+Contributed/3rd party tools which may be of use with zebra.
+
+%package devel
+Summary: Header and object files for zebra development
+Group: System Environment/Daemons
+
+%description devel
+The zebra-devel package contains the header and object files neccessary for
+developing OSPF-API and zebra applications.
+
+%prep
+%setup -q
+
+%build
+%configure \
+%if %with_ipv6
+ --enable-ipv6 \
+%endif
+%if %with_snmp
+ --enable-snmp \
+%endif
+%if %with_multipath
+ --enable-multipath=%with_multipath \
+%endif
+%if %with_tcp_zebra
+ --enable-tcp-zebra \
+%endif
+%if %with_nssa
+ --enable-nssa \
+%endif
+%if %with_opaque_lsa
+ --enable-opaque-lsa \
+%endif
+%if %with_ospf_te
+ --enable-ospf-te \
+%endif
+%if %with_vtysh
+ --enable-vtysh \
+%endif
+%if %with_ospfclient
+ --enable-ospfclient=yes \
+%else
+ --enable-ospfclient=no\
+%endif
+%if %with_ospfapi
+ --enable-ospfapi=yes \
+%else
+ --enable-ospfapi=no \
+%endif
+%if %with_pam
+ --with-libpam \
+%endif
+%if %zebra_user
+ --enable-user=%zebra_user \
+ --enable-group=%zebra_user \
+%endif
+%if %vty_group
+ --enable-vty-group=%vty_group \
+%endif
+--with-cflags="-O2" \
+--enable-netlink
+
+make %{?_smp_mflags} MAKEINFO="makeinfo --no-split"
+
+pushd doc
+texi2html zebra.texi
+popd
+
+%install
+rm -rf $RPM_BUILD_ROOT
+
+install -d $RPM_BUILD_ROOT/etc/{rc.d/init.d,sysconfig,logrotate.d,pam.d} \
+ $RPM_BUILD_ROOT/var/log/zebra $RPM_BUILD_ROOT%{_infodir}
+
+make install \
+ DESTDIR=$RPM_BUILD_ROOT
+
+install %{zeb_rh_src}/zebra.init $RPM_BUILD_ROOT/etc/rc.d/init.d/zebra
+install %{zeb_rh_src}/bgpd.init $RPM_BUILD_ROOT/etc/rc.d/init.d/bgpd
+%if %with_ipv6
+install %{zeb_rh_src}/ospf6d.init $RPM_BUILD_ROOT/etc/rc.d/init.d/ospf6d
+install %{zeb_rh_src}/ripngd.init $RPM_BUILD_ROOT/etc/rc.d/init.d/ripngd
+%endif
+install %{zeb_rh_src}/ospfd.init $RPM_BUILD_ROOT/etc/rc.d/init.d/ospfd
+install %{zeb_rh_src}/ripd.init $RPM_BUILD_ROOT/etc/rc.d/init.d/ripd
+install -m644 %{zeb_rh_src}/zebra.pam $RPM_BUILD_ROOT/etc/pam.d/zebra
+install -m644 %{zeb_rh_src}/zebra.logrotate $RPM_BUILD_ROOT/etc/logrotate.d/zebra
+install -d -m750 $RPM_BUILD_ROOT/var/run/zebra
+
+%pre
+# add vty_group
+%if %vty_group
+groupadd -r %vty_group 2> /dev/null || :
+%endif
+# add zebra user and group
+%if %zebra_user
+/usr/sbin/useradd -M -r -s /bin/false -c "Zebra routing suite" \
+ -d %_localstatedir %zebra_user 2> /dev/null || :
+%endif
+
+%post
+# zebra_spec_add_service <service name> <port/proto> <comment>
+# e.g. zebra_spec_add_service zebrasrv 2600/tcp "zebra service"
+
+zebra_spec_add_service ()
+{
+ # Add port /etc/services entry if it isn't already there
+ if [ -f /etc/services ] && ! grep -q "^$1[^a-zA-Z0-9]" /etc/services ; then
+ echo "$1 $2 # $3" >> /etc/services
+ fi
+}
+
+zebra_spec_add_service zebrasrv 2600/tcp "zebra service"
+zebra_spec_add_service zebra 2601/tcp "zebra vty"
+zebra_spec_add_service ripd 2602/tcp "RIPd vty"
+%if %with_ipv6
+zebra_spec_add_service ripngd 2603/tcp "RIPngd vty"
+%endif
+zebra_spec_add_service ospfd 2604/tcp "OSPFd vty"
+zebra_spec_add_service bgpd 2605/tcp "BGPd vty"
+%if %with_ipv6
+zebra_spec_add_service ospf6d 2606/tcp "OSPF6d vty"
+%endif
+
+/sbin/chkconfig --add zebra
+/sbin/chkconfig --add ripd
+%if %with_ipv6
+/sbin/chkconfig --add ripngd
+/sbin/chkconfig --add ospf6d
+%endif
+/sbin/chkconfig --add ospfd
+/sbin/chkconfig --add bgpd
+
+/sbin/install-info %{_infodir}/zebra.info.gz %{_infodir}/dir
+
+# Create dummy files if they don't exist so basic functions can be used.
+if [ ! -e %{_sysconfdir}/zebra.conf ]; then
+ echo "hostname `hostname`" > %{_sysconfdir}/zebra.conf
+ chmod 640 %{_sysconfdir}/zebra.conf
+fi
+if [ ! -e %{_sysconfdir}/vtysh.conf ]; then
+ touch %{_sysconfdir}/vtysh.conf
+ chmod 640 %{_sysconfdir}/vtysh.conf
+fi
+
+%postun
+if [ "$1" -ge "1" ]; then
+ /etc/rc.d/init.d/zebra condrestart >/dev/null 2>&1
+ /etc/rc.d/init.d/ripd condrestart >/dev/null 2>&1
+%if %with_ipv6
+ /etc/rc.d/init.d/ripngd condrestart >/dev/null 2>&1
+%endif
+ /etc/rc.d/init.d/ospfd condrestart >/dev/null 2>&1
+%if %with_ipv6
+ /etc/rc.d/init.d/ospf6d condrestart >/dev/null 2>&1
+%endif
+ /etc/rc.d/init.d/bgpd condrestart >/dev/null 2>&1
+fi
+/sbin/install-info --delete %{_infodir}/zebra.info.gz %{_infodir}/dir
+
+%preun
+if [ "$1" = "0" ]; then
+ /sbin/chkconfig --del zebra
+ /sbin/chkconfig --del ripd
+%if %with_ipv6
+ /sbin/chkconfig --del ripngd
+%endif
+ /sbin/chkconfig --del ospfd
+%if %with_ipv6
+ /sbin/chkconfig --del ospf6d
+%endif
+ /sbin/chkconfig --del bgpd
+fi
+
+%clean
+#rm -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(-,root,root)
+%doc */*.sample* AUTHORS COPYING
+%doc doc/zebra.html
+%doc doc/mpls
+%doc ChangeLog INSTALL NEWS README REPORTING-BUGS SERVICES TODO
+%if %zebra_user
+%dir %attr(751,%zebra_user,%zebra_user) %{_sysconfdir}
+%dir %attr(750,%zebra_user,%zebra_user) /var/log/zebra
+%dir %attr(751,%zebra_user,%zebra_user) /var/run/zebra
+%else
+%dir %attr(750,root,root) %{_sysconfdir}
+%dir %attr(750,root,root) /var/log/zebra
+%dir %attr(755,root,root) /usr/share/info
+%dir %attr(750,root,root) /var/run/zebra
+%endif
+%if %vty_group
+%attr(750,%zebra_user,%vty_group) %{_sysconfdir}/vtysh.conf
+%endif
+%{_infodir}/*info*
+%{_mandir}/man*/*
+%{_sbindir}/*
+%if %with_vtysh
+%{_bindir}/*
+%endif
+%config /etc/zebra/*.conf
+%config /etc/rc.d/init.d/*
+%config(noreplace) /etc/pam.d/zebra
+%config(noreplace) %attr(640,root,root) /etc/logrotate.d/*
+
+%files contrib
+%defattr(-,root,root)
+%doc tools
+
+%files devel
+%defattr(-,root,root)
+%dir %{_libdir}/*
+%dir %{_includedir}/ospfd/*
+%if %with_ospfapi
+%dir %{_includedir}/ospfapi/*
+%endif
+
+%changelog
+* Tue Mar 20 2003 Paul Jakma <paul@dishone.st>
+- zebra privileges support
+
+* Mon Mar 18 2003 Paul Jakma <paul@dishone.st>
+- Fix mem leak in 'show thread cpu'
+- Ralph Keller's OSPF-API
+- Amir: Fix configure.ac for net-snmp
+
+* Sat Mar 1 2003 Paul Jakma <paul@dishone.st>
+- ospfd IOS prefix to interface matching for 'network' statement
+- temporary fix for PtP and IPv6
+- sync to zebra.org CVS
+
+* Mon Jan 20 2003 Paul Jakma <paul@dishone.st>
+- update to latest cvs
+- Yon's "show thread cpu" patch - 17217
+- walk up tree - 17218
+- ospfd NSSA fixes - 16681
+- ospfd nsm fixes - 16824
+- ospfd OLSA fixes and new feature - 16823
+- KAME and ifindex fixes - 16525
+- spec file changes to allow redhat files to be in tree
+
+* Sat Dec 28 2002 Alexander Hoogerhuis <alexh@ihatent.com>
+- Added conditionals for building with(out) IPv6, vtysh, RIP, BGP
+- Fixed up some build requirements (patch)
+- Added conditional build requirements for vtysh / snmp
+- Added conditional to %files for %_bindir depending on vtysh
+
+* Mon Nov 11 2002 Paul Jakma <paulj@alphyra.ie>
+- update to latest CVS
+- add Greg Troxel's md5 buffer copy/dup fix
+- add RIPv1 fix
+- add Frank's multicast flag fix
+
+* Wed Oct 09 2002 Paul Jakma <paulj@alphyra.ie>
+- update to latest CVS
+- timestamped crypt_seqnum patch
+- oi->on_write_q fix
+
+* Mon Sep 30 2002 Paul Jakma <paulj@alphyra.ie>
+- update to latest CVS
+- add vtysh 'write-config (integrated|daemon)' patch
+- always 'make rebuild' in vtysh/ to catch new commands
+
+* Fri Sep 13 2002 Paul Jakma <paulj@alphyra.ie>
+- update to 0.93b
+
+* Wed Sep 11 2002 Paul Jakma <paulj@alphyra.ie>
+- update to latest CVS
+- add "/sbin/ip route flush proto zebra" to zebra RH init on startup
+
+* Sat Aug 24 2002 Paul Jakma <paulj@alphyra.ie>
+- update to current CVS
+- add OSPF point to multipoint patch
+- add OSPF bugfixes
+- add BGP hash optimisation patch
+
+* Fri Jun 14 2002 Paul Jakma <paulj@alphyra.ie>
+- update to 0.93-pre1 / CVS
+- add link state detection support
+- add generic PtP and RFC3021 support
+- various bug fixes
+
+* Thu Aug 09 2001 Elliot Lee <sopwith@redhat.com> 0.91a-6
+- Fix bug #51336
+
+* Wed Aug 1 2001 Trond Eivind Glomsrød <teg@redhat.com> 0.91a-5
+- Use generic initscript strings instead of initscript specific
+ ( "Starting foo: " -> "Starting $prog:" )
+
+* Fri Jul 27 2001 Elliot Lee <sopwith@redhat.com> 0.91a-4
+- Bump the release when rebuilding into the dist.
+
+* Tue Feb 6 2001 Tim Powers <timp@redhat.com>
+- built for Powertools
+
+* Sun Feb 4 2001 Pekka Savola <pekkas@netcore.fi>
+- Hacked up from PLD Linux 0.90-1, Mandrake 0.90-1mdk and one from zebra.org.
+- Update to 0.91a
+- Very heavy modifications to init.d/*, .spec, pam, i18n, logrotate, etc.
+- Should be quite Red Hat'isque now.
diff --git a/ripd/Makefile.am b/ripd/Makefile.am
index fd254851..138c3a51 100644
--- a/ripd/Makefile.am
+++ b/ripd/Makefile.am
@@ -17,7 +17,7 @@ noinst_HEADERS = \
ripd_SOURCES = \
rip_main.c $(librip_a_SOURCES)
-ripd_LDADD = ../lib/libzebra.a
+ripd_LDADD = ../lib/libzebra.a @LIBCAP@
sysconf_DATA = ripd.conf.sample
diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c
index 06d4416b..d7856341 100644
--- a/ripd/rip_interface.c
+++ b/ripd/rip_interface.c
@@ -34,6 +34,7 @@
#include "zclient.h"
#include "filter.h"
#include "sockopt.h"
+#include "privs.h"
#include "zebra/connected.h"
@@ -52,6 +53,8 @@ struct message ri_version_msg[] =
{0, NULL}
};
+extern struct zebra_privs_t ripd_privs;
+
/* RIP enabled network vector. */
vector rip_enable_interface;
@@ -173,6 +176,9 @@ rip_interface_multicast_set (int sock, struct interface *ifp)
from.sin_len = sizeof (struct sockaddr_in);
#endif /* HAVE_SIN_LEN */
+ if (ripd_privs.change (ZPRIVS_RAISE))
+ zlog_err ("rip_interface_multicast_set: could not raise privs");
+
ret = bind (sock, (struct sockaddr *) & from,
sizeof (struct sockaddr_in));
if (ret < 0)
@@ -181,6 +187,9 @@ rip_interface_multicast_set (int sock, struct interface *ifp)
return;
}
+ if (ripd_privs.change (ZPRIVS_LOWER))
+ zlog_err ("rip_interface_multicast_set: could not lower privs");
+
return;
}
@@ -248,7 +257,7 @@ rip_request_interface (struct interface *ifp)
return;
/* If interface is down, don't send RIP packet. */
- if (! if_is_up (ifp))
+ if (! if_is_operative (ifp))
return;
/* Fetch RIP interface information. */
@@ -311,7 +320,7 @@ rip_multicast_join (struct interface *ifp, int sock)
{
listnode cnode;
- if (if_is_up (ifp) && if_is_multicast (ifp))
+ if (if_is_operative (ifp) && if_is_multicast (ifp))
{
if (IS_RIP_DEBUG_EVENT)
zlog_info ("multicast join at %s", ifp->name);
@@ -391,106 +400,6 @@ rip_if_ipv4_address_check (struct interface *ifp)
return count;
}
-
-
-
-
-/* Does this address belongs to me ? */
-int
-if_check_address (struct in_addr addr)
-{
- listnode node;
-
- for (node = listhead (iflist); node; nextnode (node))
- {
- listnode cnode;
- struct interface *ifp;
-
- ifp = getdata (node);
-
- for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
- {
- struct connected *connected;
- struct prefix_ipv4 *p;
-
- connected = getdata (cnode);
- p = (struct prefix_ipv4 *) connected->address;
-
- if (p->family != AF_INET)
- continue;
-
- if (IPV4_ADDR_CMP (&p->prefix, &addr) == 0)
- return 1;
- }
- }
- return 0;
-}
-
-/* is this address from a valid neighbor? (RFC2453 - Sec. 3.9.2) */
-int
-if_valid_neighbor (struct in_addr addr)
-{
- listnode node;
- struct connected *connected = NULL;
- struct prefix_ipv4 *p;
-
- for (node = listhead (iflist); node; nextnode (node))
- {
- listnode cnode;
- struct interface *ifp;
-
- ifp = getdata (node);
-
- for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
- {
- struct prefix *pxn = NULL; /* Prefix of the neighbor */
- struct prefix *pxc = NULL; /* Prefix of the connected network */
-
- connected = getdata (cnode);
-
- if (if_is_pointopoint (ifp))
- {
- p = (struct prefix_ipv4 *) connected->address;
-
- if (p && p->family == AF_INET)
- {
- if (IPV4_ADDR_SAME (&p->prefix, &addr))
- return 1;
-
- p = (struct prefix_ipv4 *) connected->destination;
- if (p && IPV4_ADDR_SAME (&p->prefix, &addr))
- return 1;
- }
- }
- else
- {
- p = (struct prefix_ipv4 *) connected->address;
-
- if (p->family != AF_INET)
- continue;
-
- pxn = prefix_new();
- pxn->family = AF_INET;
- pxn->prefixlen = 32;
- pxn->u.prefix4 = addr;
-
- pxc = prefix_new();
- prefix_copy(pxc, (struct prefix *) p);
- apply_mask(pxc);
-
- if (prefix_match (pxc, pxn))
- {
- prefix_free (pxn);
- prefix_free (pxc);
- return 1;
- }
- prefix_free(pxc);
- prefix_free(pxn);
- }
- }
- }
- return 0;
-}
/* Inteface link down message processing. */
int
@@ -705,7 +614,7 @@ rip_if_down(struct interface *ifp)
{
/* All redistributed routes but static and system */
if ((rinfo->ifindex == ifp->ifindex) &&
- (rinfo->type != ZEBRA_ROUTE_STATIC) &&
+ /* (rinfo->type != ZEBRA_ROUTE_STATIC) && */
(rinfo->type != ZEBRA_ROUTE_SYSTEM))
rip_redistribute_delete (rinfo->type,rinfo->sub_type,
(struct prefix_ipv4 *)&rp->p,
@@ -1008,7 +917,7 @@ rip_enable_apply (struct interface *ifp)
if (if_is_loopback (ifp))
return;
- if (! if_is_up (ifp))
+ if (! if_is_operative (ifp))
return;
ri = ifp->info;
@@ -1961,6 +1870,7 @@ rip_if_init ()
/* Install commands. */
install_element (CONFIG_NODE, &interface_cmd);
+ install_element (CONFIG_NODE, &no_interface_cmd);
install_default (INTERFACE_NODE);
install_element (INTERFACE_NODE, &interface_desc_cmd);
install_element (INTERFACE_NODE, &no_interface_desc_cmd);
diff --git a/ripd/rip_main.c b/ripd/rip_main.c
index 1070fb45..ef7e119a 100644
--- a/ripd/rip_main.c
+++ b/ripd/rip_main.c
@@ -30,6 +30,7 @@
#include "filter.h"
#include "keychain.h"
#include "log.h"
+#include "privs.h"
#include "ripd/ripd.h"
@@ -43,10 +44,31 @@ static struct option longopts[] =
{ "vty_addr", required_argument, NULL, 'A'},
{ "vty_port", required_argument, NULL, 'P'},
{ "retain", no_argument, NULL, 'r'},
+ { "user", required_argument, NULL, 'u'},
{ "version", no_argument, NULL, 'v'},
{ 0 }
};
+/* ripd privileges */
+zebra_capabilities_t _caps_p [] =
+{
+ ZCAP_RAW,
+ ZCAP_BIND
+};
+
+struct zebra_privs_t ripd_privs =
+{
+#if defined(ZEBRA_USER)
+ .user = ZEBRA_USER,
+#endif
+#if defined ZEBRA_GROUP
+ .group = ZEBRA_GROUP,
+#endif
+ .caps_p = _caps_p,
+ .cap_num_p = 2,
+ .cap_num_i = 0
+};
+
/* Configuration file and directory. */
char config_current[] = RIPD_DEFAULT_CONFIG;
char config_default[] = SYSCONFDIR RIPD_DEFAULT_CONFIG;
@@ -85,6 +107,7 @@ Daemon which manages RIP version 1 and 2.\n\n\
-A, --vty_addr Set vty's bind address\n\
-P, --vty_port Set vty's port number\n\
-r, --retain When program terminates, retain added route by ripd.\n\
+-u, --user User and group to run as\n\
-v, --version Print program version\n\
-h, --help Display this help and exit\n\
\n\
@@ -211,11 +234,22 @@ main (int argc, char **argv)
pid_file = optarg;
break;
case 'P':
- vty_port = atoi (optarg);
+ /* Deal with atoi() returning 0 on failure, and ripd not
+ listening on rip port... */
+ if (strcmp(optarg, "0") == 0)
+ {
+ vty_port = 0;
+ break;
+ }
+ vty_port = atoi (optarg);
+ vty_port = (vty_port ? vty_port : RIP_VTY_PORT);
break;
case 'r':
retain_mode = 1;
break;
+ case 'u':
+ ripd_privs.group = ripd_privs.user = optarg;
+ break;
case 'v':
print_version (progname);
exit (0);
@@ -233,6 +267,7 @@ main (int argc, char **argv)
master = thread_master_create ();
/* Library initialization. */
+ zprivs_init (&ripd_privs);
signal_init ();
cmd_init (1);
vty_init ();
diff --git a/ripd/ripd.c b/ripd/ripd.c
index c017fe56..42974a72 100644
--- a/ripd/ripd.c
+++ b/ripd/ripd.c
@@ -36,10 +36,13 @@
#include "distribute.h"
#include "md5-gnu.h"
#include "keychain.h"
+#include "privs.h"
#include "ripd/ripd.h"
#include "ripd/rip_debug.h"
+extern struct zebra_privs_t ripd_privs;
+
/* RIP Structure. */
struct rip *rip = NULL;
@@ -55,8 +58,8 @@ long rip_global_queries = 0;
/* Prototypes. */
void rip_event (enum rip_event, int);
-void rip_output_process (struct interface *, struct sockaddr_in *,
- int, u_char);
+void rip_output_process (struct interface *, struct prefix *,
+ struct sockaddr_in *, int, u_char);
/* RIP output routes type. */
enum
@@ -955,7 +958,14 @@ rip_response_process (struct rip_packet *packet, int size,
{
caddr_t lim;
struct rte *rte;
+ struct prefix_ipv4 ifaddr;
+ struct prefix_ipv4 ifaddrclass;
+ struct connected *c;
+ int subnetted;
+ /* We don't know yet. */
+ subnetted = -1;
+
/* The Response must be ignored if it is not from the RIP
port. (RFC2453 - Sec. 3.9.2)*/
if (ntohs (from->sin_port) != RIP_PORT_DEFAULT)
@@ -969,7 +979,7 @@ rip_response_process (struct rip_packet *packet, int size,
/* The datagram's IPv4 source address should be checked to see
whether the datagram is from a valid neighbor; the source of the
datagram must be on a directly connected network */
- if (! if_valid_neighbor (from->sin_addr))
+ if (if_lookup_address (from->sin_addr) == NULL)
{
zlog_info ("This datagram doesn't came from a valid neighbor: %s",
inet_ntoa (from->sin_addr));
@@ -1108,23 +1118,51 @@ rip_response_process (struct rip_packet *packet, int size,
{
u_int32_t destination;
- destination = ntohl (rte->prefix.s_addr);
-
- if (destination & 0xff)
+ if (subnetted == -1)
{
- masklen2ip (32, &rte->mask);
+ c = connected_lookup_address (ifp, from->sin_addr);
+ if (c != NULL)
+ {
+ memcpy (&ifaddr, c->address, sizeof (struct prefix_ipv4));
+ memcpy (&ifaddrclass, &ifaddr, sizeof (struct prefix_ipv4));
+ apply_classful_mask_ipv4 (&ifaddrclass);
+ subnetted = 0;
+ if (ifaddr.prefixlen > ifaddrclass.prefixlen)
+ subnetted = 1;
+ }
}
- else if ((destination & 0xff00) || IN_CLASSC (destination))
- {
+
+ destination = ntohl (rte->prefix.s_addr);
+
+ if (IN_CLASSA (destination))
+ masklen2ip (8, &rte->mask);
+ else if (IN_CLASSB (destination))
+ masklen2ip (16, &rte->mask);
+ else if (IN_CLASSC (destination))
masklen2ip (24, &rte->mask);
+
+ if (subnetted == 1)
+ masklen2ip (ifaddrclass.prefixlen,
+ (struct in_addr *) &destination);
+ if ((subnetted == 1) && ((rte->prefix.s_addr & destination) ==
+ ifaddrclass.prefix.s_addr))
+ {
+ masklen2ip (ifaddr.prefixlen, &rte->mask);
+ if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
+ masklen2ip (32, &rte->mask);
+ if (IS_RIP_DEBUG_EVENT)
+ zlog_info ("Subnetted route %s", inet_ntoa (rte->prefix));
}
- else if ((destination & 0xff0000) || IN_CLASSB (destination))
+ else
{
- masklen2ip (16, &rte->mask);
+ if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
+ continue;
}
- else
+
+ if (IS_RIP_DEBUG_EVENT)
{
- masklen2ip (8, &rte->mask);
+ zlog_info ("Resultant route %s", inet_ntoa (rte->prefix));
+ zlog_info ("Resultant mask %s", inet_ntoa (rte->mask));
}
}
@@ -1353,7 +1391,7 @@ rip_request_process (struct rip_packet *packet, int size,
ntohl (rte->metric) == RIP_METRIC_INFINITY)
{
/* All route with split horizon */
- rip_output_process (ifp, from, rip_all_route, packet->version);
+ rip_output_process (ifp, NULL, from, rip_all_route, packet->version);
}
else
{
@@ -1500,7 +1538,7 @@ rip_read (struct thread *t)
}
/* Check is this packet comming from myself? */
- if (if_check_address (from.sin_addr))
+ if (if_lookup_exact_address (from.sin_addr))
{
if (IS_RIP_DEBUG_PACKET)
zlog_warn ("ignore packet comes from myself");
@@ -1785,13 +1823,17 @@ rip_create_socket ()
setsockopt_pktinfo (sock);
#endif /* RIP_RECVMSG */
+ if (ripd_privs.change (ZPRIVS_RAISE))
+ zlog_err ("rip_create_socket: could not raise privs");
ret = bind (sock, (struct sockaddr *) & addr, sizeof (addr));
if (ret < 0)
{
perror ("bind");
return ret;
}
-
+ if (ripd_privs.change (ZPRIVS_LOWER))
+ zlog_err ("rip_create_socket: could not lower privs");
+
return sock;
}
@@ -1884,8 +1926,8 @@ rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,
/* Send update to the ifp or spcified neighbor. */
void
-rip_output_process (struct interface *ifp, struct sockaddr_in *to,
- int route_type, u_char version)
+rip_output_process (struct interface *ifp, struct prefix *ifaddr,
+ struct sockaddr_in *to, int route_type, u_char version)
{
int ret;
struct stream *s;
@@ -1894,8 +1936,11 @@ rip_output_process (struct interface *ifp, struct sockaddr_in *to,
struct rip_interface *ri;
struct prefix_ipv4 *p;
struct prefix_ipv4 classfull;
+ struct prefix_ipv4 ifaddrclass;
+ struct connected *c;
int num;
int rtemax;
+ int subnetted;
/* Logging output event. */
if (IS_RIP_DEBUG_EVENT)
@@ -1946,29 +1991,60 @@ rip_output_process (struct interface *ifp, struct sockaddr_in *to,
rtemax -=1;
}
+ if (version == RIPv1)
+ {
+ if (ifaddr == NULL)
+ {
+ c = connected_lookup_address (ifp, to->sin_addr);
+ if (c != NULL)
+ ifaddr = c->address;
+ }
+ if (ifaddr == NULL)
+ {
+ zlog_warn ("cannot find source address for packets to neighbor %s",
+ inet_ntoa (to->sin_addr));
+ return;
+ }
+ memcpy (&ifaddrclass, ifaddr, sizeof (struct prefix_ipv4));
+ apply_classful_mask_ipv4 (&ifaddrclass);
+ subnetted = 0;
+ if (ifaddr->prefixlen > ifaddrclass.prefixlen)
+ subnetted = 1;
+ }
+
for (rp = route_top (rip->table); rp; rp = route_next (rp))
if ((rinfo = rp->info) != NULL)
{
- /* Some inheritance stuff: */
- /* Before we process with ipv4 prefix we should mask it */
- /* with Classful mask if we send RIPv1 packet.That's because */
- /* user could set non-classful mask or we could get it by RIPv2 */
- /* or other protocol. checked with Cisco's way of life :) */
+ /* For RIPv1, if we are subnetted, output subnets in our network */
+ /* that have the same mask as the output "interface". For other */
+ /* networks, only the classfull version is output. */
if (version == RIPv1)
{
- memcpy (&classfull, &rp->p, sizeof (struct prefix_ipv4));
+ p = (struct prefix_ipv4 *) &rp->p;
if (IS_RIP_DEBUG_PACKET)
- zlog_info("%s/%d before RIPv1 mask check ",
- inet_ntoa (classfull.prefix), classfull.prefixlen);
-
- apply_classful_mask_ipv4 (&classfull);
- p = &classfull;
+ zlog_info("RIPv1 mask check, %s/%d considered for output",
+ inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
+ if (subnetted &&
+ prefix_match ((struct prefix *) &ifaddrclass, &rp->p))
+ {
+ if ((ifaddr->prefixlen != rp->p.prefixlen) &&
+ (rp->p.prefixlen != 32))
+ continue;
+ }
+ else
+ {
+ memcpy (&classfull, &rp->p, sizeof(struct prefix_ipv4));
+ apply_classful_mask_ipv4(&classfull);
+ if (rp->p.u.prefix4.s_addr != 0 &&
+ classfull.prefixlen != rp->p.prefixlen)
+ continue;
+ }
if (IS_RIP_DEBUG_PACKET)
- zlog_info("%s/%d after RIPv1 mask check",
- inet_ntoa (p->prefix), p->prefixlen);
+ zlog_info("RIPv1 mask check, %s/%d made it through",
+ inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
}
else
p = (struct prefix_ipv4 *) &rp->p;
@@ -2109,7 +2185,7 @@ rip_update_interface (struct interface *ifp, u_char version, int route_type)
if (IS_RIP_DEBUG_EVENT)
zlog_info ("multicast announce on %s ", ifp->name);
- rip_output_process (ifp, NULL, route_type, version);
+ rip_output_process (ifp, NULL, NULL, route_type, version);
return;
}
@@ -2136,7 +2212,8 @@ rip_update_interface (struct interface *ifp, u_char version, int route_type)
if_is_pointopoint (ifp) ? "unicast" : "broadcast",
inet_ntoa (to.sin_addr), ifp->name);
- rip_output_process (ifp, &to, route_type, version);
+ rip_output_process (ifp, connected->address, &to, route_type,
+ version);
}
}
}
@@ -2161,7 +2238,7 @@ rip_update_process (int route_type)
if (if_is_loopback (ifp))
continue;
- if (! if_is_up (ifp))
+ if (! if_is_operative (ifp))
continue;
/* Fetch RIP interface information. */
@@ -2224,7 +2301,7 @@ rip_update_process (int route_type)
to.sin_port = htons (RIP_PORT_DEFAULT);
/* RIP version is rip's configuration. */
- rip_output_process (ifp, &to, route_type, rip->version);
+ rip_output_process (ifp, NULL, &to, route_type, rip->version);
}
}
diff --git a/ripngd/Makefile.am b/ripngd/Makefile.am
index 2835aa24..a54b1159 100644
--- a/ripngd/Makefile.am
+++ b/ripngd/Makefile.am
@@ -9,15 +9,15 @@ sbin_PROGRAMS = ripngd
libripng_a_SOURCES = \
ripng_interface.c ripngd.c ripng_zebra.c ripng_route.c ripng_debug.c \
- ripng_routemap.c
+ ripng_routemap.c ripng_ifrmap.c
noinst_HEADERS = \
- ripng_debug.h ripng_route.h ripngd.h
+ ripng_debug.h ripng_route.h ripngd.h ripng_ifrmap.h
ripngd_SOURCES = \
ripng_main.c $(libripng_a_SOURCES)
-ripngd_LDADD = ../lib/libzebra.a
+ripngd_LDADD = ../lib/libzebra.a @LIBCAP@
sysconf_DATA = ripngd.conf.sample
diff --git a/ripngd/ripng_main.c b/ripngd/ripng_main.c
index aec74bb4..0d5fe78c 100644
--- a/ripngd/ripng_main.c
+++ b/ripngd/ripng_main.c
@@ -31,6 +31,7 @@
#include "log.h"
#include "prefix.h"
#include "if.h"
+#include "privs.h"
#include "ripngd/ripngd.h"
@@ -49,10 +50,32 @@ struct option longopts[] =
{ "vty_addr", required_argument, NULL, 'A'},
{ "vty_port", required_argument, NULL, 'P'},
{ "retain", no_argument, NULL, 'r'},
+ { "user", required_argument, NULL, 'u'},
{ "version", no_argument, NULL, 'v'},
{ 0 }
};
+/* ripngd privileges */
+zebra_capabilities_t _caps_p [] =
+{
+ ZCAP_RAW,
+ ZCAP_BIND
+};
+
+struct zebra_privs_t ripngd_privs =
+{
+#if defined(ZEBRA_USER)
+ .user = ZEBRA_USER,
+#endif
+#if defined ZEBRA_GROUP
+ .group = ZEBRA_GROUP,
+#endif
+ .caps_p = _caps_p,
+ .cap_num_p = 2,
+ .cap_num_i = 0
+};
+
+
/* RIPngd program name */
/* Route retain mode flag. */
@@ -81,6 +104,7 @@ Daemon which manages RIPng.\n\n\
-A, --vty_addr Set vty's bind address\n\
-P, --vty_port Set vty's port number\n\
-r, --retain When program terminates, retain added route by ripngd.\n\
+-u, --user User and group to run as\n\
-v, --version Print program version\n\
-h, --help Display this help and exit\n\
\n\
@@ -155,7 +179,7 @@ main (int argc, char **argv)
{
char *p;
char *vty_addr = NULL;
- int vty_port = 0;
+ int vty_port = RIPNG_VTY_PORT;
int daemon_mode = 0;
char *config_file = NULL;
char *progname;
@@ -197,13 +221,24 @@ main (int argc, char **argv)
break;
case 'i':
pid_file = optarg;
- break;
+ break;
case 'P':
- vty_port = atoi (optarg);
- break;
+ /* Deal with atoi() returning 0 on failure, and ripngd not
+ listening on ripngd port... */
+ if (strcmp(optarg, "0") == 0)
+ {
+ vty_port = 0;
+ break;
+ }
+ vty_port = atoi (optarg);
+ vty_port = (vty_port ? vty_port : RIPNG_VTY_PORT);
+ break;
case 'r':
retain_mode = 1;
break;
+ case 'u':
+ ripngd_privs.group = ripngd_privs.user = optarg;
+ break;
case 'v':
print_version (progname);
exit (0);
@@ -220,6 +255,7 @@ main (int argc, char **argv)
master = thread_master_create ();
/* Library inits. */
+ zprivs_init (&ripngd_privs);
signal_init ();
cmd_init (1);
vty_init ();
@@ -237,8 +273,7 @@ main (int argc, char **argv)
daemon (0, 0);
/* Create VTY socket */
- vty_serv_sock (vty_addr,
- vty_port ? vty_port : RIPNG_VTY_PORT, RIPNG_VTYSH_PATH);
+ vty_serv_sock (vty_addr, vty_port, RIPNG_VTYSH_PATH);
/* Process id file create. */
pid_output (pid_file);
diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c
index 98d4bb70..677f7bbc 100644
--- a/ripngd/ripngd.c
+++ b/ripngd/ripngd.c
@@ -37,11 +37,12 @@
#include "distribute.h"
#include "plist.h"
#include "routemap.h"
-#include "if_rmap.h"
+#include "privs.c"
#include "ripngd/ripngd.h"
#include "ripngd/ripng_route.h"
#include "ripngd/ripng_debug.h"
+#include "ripngd/ripng_ifrmap.h"
#define min(a, b) ((a) < (b) ? (a) : (b))
@@ -58,6 +59,8 @@ enum
ripng_no_split_horizon
};
+extern struct zebra_privs_t ripngd_privs;
+
/* Prototypes. */
void
ripng_output_process (struct interface *, struct sockaddr_in6 *, int, int);
@@ -153,12 +156,19 @@ ripng_make_socket (void)
#endif /* SIN6_LEN */
ripaddr.sin6_port = htons (RIPNG_PORT_DEFAULT);
+ if (ripngd_privs.change (ZPRIVS_RAISE))
+ zlog_err ("ripng_make_socket: could not raise privs");
+
ret = bind (sock, (struct sockaddr *) &ripaddr, sizeof (ripaddr));
if (ret < 0)
{
zlog (NULL, LOG_ERR, "Can't bind ripng socket: %s.", strerror (errno));
return ret;
}
+
+ if (ripngd_privs.change (ZPRIVS_LOWER))
+ zlog_err ("ripng_make_socket: could not lower privs");
+
return sock;
}
@@ -2178,8 +2188,8 @@ DEFUN (show_ipv6_protocols, show_ipv6_protocols_cmd,
}
/* Please be carefull to use this command. */
-DEFUN (default_information_originate,
- default_information_originate_cmd,
+DEFUN (ripng_default_information_originate,
+ ripng_default_information_originate_cmd,
"default-information originate",
"Default route information\n"
"Distribute default route\n")
@@ -2194,8 +2204,8 @@ DEFUN (default_information_originate,
return CMD_SUCCESS;
}
-DEFUN (no_default_information_originate,
- no_default_information_originate_cmd,
+DEFUN (no_ripng_default_information_originate,
+ no_ripng_default_information_originate_cmd,
"no default-information originate",
NO_STR
"Default route information\n"
@@ -2494,8 +2504,8 @@ ripng_init ()
install_element (RIPNG_NODE, &no_ripng_garbage_timer_cmd);
#endif /* 0 */
- install_element (RIPNG_NODE, &default_information_originate_cmd);
- install_element (RIPNG_NODE, &no_default_information_originate_cmd);
+ install_element (RIPNG_NODE, &ripng_default_information_originate_cmd);
+ install_element (RIPNG_NODE, &no_ripng_default_information_originate_cmd);
ripng_if_init ();
ripng_debug_init ();
@@ -2520,7 +2530,7 @@ ripng_init ()
route_map_add_hook (ripng_routemap_update);
route_map_delete_hook (ripng_routemap_update);
- if_rmap_init (RIPNG_NODE);
+ if_rmap_init ();
if_rmap_hook_add (ripng_if_rmap_update);
if_rmap_hook_delete (ripng_if_rmap_update);
}
diff --git a/vtysh/Makefile.am b/vtysh/Makefile.am
index 4327379b..39b7cee0 100644
--- a/vtysh/Makefile.am
+++ b/vtysh/Makefile.am
@@ -9,14 +9,16 @@ bin_PROGRAMS = vtysh
vtysh_SOURCES = vtysh_main.c vtysh.c vtysh_cmd.c vtysh_user.c vtysh_config.c
noinst_HEADERS = vtysh.h vtysh_user.h
-vtysh_LDADD = ../lib/libzebra.a
+vtysh_LDADD = ../lib/libzebra.a @LIBCAP@
sysconf_DATA = vtysh.conf.sample
EXTRA_DIST = extract.pl vtysh.conf.sample
rebuild4:
- ./extract.pl ../zebra/*.c ../ripd/*.c ../ospfd/*.c ../bgpd/*.c ../lib/keychain.c ../lib/routemap.c ../lib/filter.c ../lib/plist.c >vtysh_cmd.c
+ ./extract.pl ../zebra/*.c ../ripd/*.c ../ospfd/*.c ../bgpd/*.c ../lib/keychain.c ../lib/routemap.c ../lib/filter.c ../lib/plist.c ../lib/distribute.c > vtysh_cmd.c
rebuild:
- ./extract.pl ../zebra/*.c ../ripd/*.c ../ripngd/*.c ../ospfd/*.c ../ospf6d/*.c ../bgpd/*.c ../lib/keychain.c ../lib/routemap.c ../lib/filter.c ../lib/plist.c >vtysh_cmd.c
+ ./extract.pl ../zebra/*.c ../ripd/*.c ../ripngd/*.c ../ospfd/*.c ../ospf6d/*.c ../bgpd/*.c ../lib/keychain.c ../lib/routemap.c ../lib/filter.c ../lib/plist.c ../lib/distribute.c > vtysh_cmd.c
+
+vtysh_cmd.c: rebuild
diff --git a/zebra/Makefile.am b/zebra/Makefile.am
index a83543ee..ce564672 100644
--- a/zebra/Makefile.am
+++ b/zebra/Makefile.am
@@ -13,9 +13,10 @@ rt_method = @RT_METHOD@
rtread_method = @RTREAD_METHOD@
kernel_method = @KERNEL_METHOD@
other_method = @OTHER_METHOD@
+libcap = @LIBCAP@
otherobj = $(ipforward) $(if_method) $(if_proc) $(rt_method) \
- $(rtread_method) $(kernel_method) $(other_method)
+ $(rtread_method) $(kernel_method) $(other_method) $(libcap)
sbin_PROGRAMS = zebra
diff --git a/zebra/ioctl.c b/zebra/ioctl.c
index 13afba29..4c341e8b 100644
--- a/zebra/ioctl.c
+++ b/zebra/ioctl.c
@@ -27,10 +27,13 @@
#include "prefix.h"
#include "ioctl.h"
#include "log.h"
+#include "privs.h"
#include "zebra/rib.h"
#include "zebra/rt.h"
+extern struct zebra_privs_t zserv_privs;
+
/* clear and set interface name string */
void
ifreq_set_name (struct ifreq *ifreq, struct interface *ifp)
@@ -46,14 +49,19 @@ if_ioctl (u_long request, caddr_t buffer)
int ret = 0;
int err = 0;
+ if (zserv_privs.change(ZPRIVS_RAISE))
+ zlog (NULL, LOG_ERR, "Can't raise privileges");
sock = socket (AF_INET, SOCK_DGRAM, 0);
if (sock < 0)
{
+ if (zserv_privs.change(ZPRIVS_LOWER))
+ zlog (NULL, LOG_ERR, "Can't lower privileges");
perror ("socket");
exit (1);
}
-
ret = ioctl (sock, request, buffer);
+ if (zserv_privs.change(ZPRIVS_LOWER))
+ zlog (NULL, LOG_ERR, "Can't lower privileges");
if (ret < 0)
{
err = errno;
@@ -76,14 +84,21 @@ if_ioctl_ipv6 (u_long request, caddr_t buffer)
int ret = 0;
int err = 0;
+ if (zserv_privs.change(ZPRIVS_RAISE))
+ zlog (NULL, LOG_ERR, "Can't raise privileges");
sock = socket (AF_INET6, SOCK_DGRAM, 0);
if (sock < 0)
{
+ if (zserv_privs.change(ZPRIVS_LOWER))
+ zlog (NULL, LOG_ERR, "Can't lower privileges");
perror ("socket");
exit (1);
}
ret = ioctl (sock, request, buffer);
+ if (zserv_privs.change(ZPRIVS_LOWER))
+ zlog (NULL, LOG_ERR, "Can't lower privileges");
+
if (ret < 0)
{
err = errno;
diff --git a/zebra/ipforward_proc.c b/zebra/ipforward_proc.c
index eb8cef01..e9d6b9fc 100644
--- a/zebra/ipforward_proc.c
+++ b/zebra/ipforward_proc.c
@@ -22,6 +22,11 @@
#include <zebra.h>
+#include "log.h"
+#include "privs.h"
+
+extern struct zebra_privs_t zserv_privs;
+
char proc_net_snmp[] = "/proc/net/snmp";
static void
@@ -68,9 +73,15 @@ int
ipforward_on ()
{
FILE *fp;
+
+ if ( zserv_privs.change(ZPRIVS_RAISE) )
+ zlog_err ("Can't raise privileges, %s", strerror (errno) );
fp = fopen (proc_ipv4_forwarding, "w");
-
+
+ if ( zserv_privs.change(ZPRIVS_LOWER) )
+ zlog_err ("Can't lower privileges, %s", strerror (errno));
+
if (fp == NULL)
return -1;
@@ -86,7 +97,15 @@ ipforward_off ()
{
FILE *fp;
+ if ( zserv_privs.change(ZPRIVS_RAISE) )
+ zlog_err ("Can't raise privileges, %s", strerror (errno));
+
+
fp = fopen (proc_ipv4_forwarding, "w");
+
+ if ( zserv_privs.change(ZPRIVS_LOWER) )
+ zlog_err ("Can't lower privileges, %s", strerror (errno));
+
if (fp == NULL)
return -1;
@@ -124,7 +143,14 @@ ipforward_ipv6_on ()
{
FILE *fp;
+ if ( zserv_privs.change(ZPRIVS_RAISE) )
+ zlog_err ("Can't raise privileges, %s", strerror (errno));
+
fp = fopen (proc_ipv6_forwarding, "w");
+
+ if ( zserv_privs.change(ZPRIVS_LOWER) )
+ zlog_err ("Can't lower privileges, %s", strerror (errno));
+
if (fp == NULL)
return -1;
@@ -141,7 +167,13 @@ ipforward_ipv6_off ()
{
FILE *fp;
+ if ( zserv_privs.change(ZPRIVS_RAISE) )
+ zlog_err ("Can't raise privileges, %s", strerror (errno));
+
fp = fopen (proc_ipv6_forwarding, "w");
+
+ if ( zserv_privs.change(ZPRIVS_LOWER) )
+ zlog_err ("Can't lower privileges, %s", strerror (errno));
if (fp == NULL)
return -1;
diff --git a/zebra/ipforward_sysctl.c b/zebra/ipforward_sysctl.c
index 828eb865..53b6c6f0 100644
--- a/zebra/ipforward_sysctl.c
+++ b/zebra/ipforward_sysctl.c
@@ -20,6 +20,7 @@
*/
#include <zebra.h>
+#include "privs.h"
#ifdef NRL
#include <netinet6/in6.h>
@@ -29,6 +30,8 @@
#define MIB_SIZ 4
+extern struct zebra_privs_t zserv_privs;
+
/* IPv4 forwarding control MIB. */
int mib[MIB_SIZ] =
{
@@ -60,11 +63,17 @@ ipforward_on ()
int ipforwarding = 1;
len = sizeof ipforwarding;
- if (sysctl (mib, MIB_SIZ, NULL, NULL, &ipforwarding, len) < 0)
+ if (zserv_privs.change(ZPRIVS_RAISE))
+ zlog (NULL, LOG_ERR, "Can't raise privileges");
+ if (sysctl (mib, MIB_SIZ, NULL, NULL, &ipforwarding, len) < 0)
{
+ if (zserv_privs.change(ZPRIVS_LOWER))
+ zlog (NULL, LOG_ERR, "Can't lower privileges");
zlog_warn ("Can't set ipforwarding on");
return -1;
}
+ if (zserv_privs.change(ZPRIVS_LOWER))
+ zlog (NULL, LOG_ERR, "Can't lower privileges");
return ipforwarding;
}
@@ -75,11 +84,17 @@ ipforward_off ()
int ipforwarding = 0;
len = sizeof ipforwarding;
- if (sysctl (mib, MIB_SIZ, NULL, NULL, &ipforwarding, len) < 0)
+ if (zserv_privs.change(ZPRIVS_RAISE))
+ zlog (NULL, LOG_ERR, "Can't raise privileges");
+ if (sysctl (mib, MIB_SIZ, NULL, NULL, &ipforwarding, len) < 0)
{
+ if (zserv_privs.change(ZPRIVS_LOWER))
+ zlog (NULL, LOG_ERR, "Can't lower privileges");
zlog_warn ("Can't set ipforwarding on");
return -1;
}
+ if (zserv_privs.change(ZPRIVS_LOWER))
+ zlog (NULL, LOG_ERR, "Can't lower privileges");
return ipforwarding;
}
@@ -106,11 +121,17 @@ ipforward_ipv6 ()
int ip6forwarding = 0;
len = sizeof ip6forwarding;
- if (sysctl (mib_ipv6, MIB_SIZ, &ip6forwarding, &len, 0, 0) < 0)
+ if (zserv_privs.change(ZPRIVS_RAISE))
+ zlog (NULL, LOG_ERR, "Can't raise privileges");
+ if (sysctl (mib_ipv6, MIB_SIZ, &ip6forwarding, &len, 0, 0) < 0)
{
+ if (zserv_privs.change(ZPRIVS_LOWER))
+ zlog (NULL, LOG_ERR, "Can't lower privileges");
zlog_warn ("can't get ip6forwarding value");
return -1;
}
+ if (zserv_privs.change(ZPRIVS_LOWER))
+ zlog (NULL, LOG_ERR, "Can't lower privileges");
return ip6forwarding;
}
@@ -121,11 +142,17 @@ ipforward_ipv6_on ()
int ip6forwarding = 1;
len = sizeof ip6forwarding;
- if (sysctl (mib_ipv6, MIB_SIZ, NULL, NULL, &ip6forwarding, len) < 0)
+ if (zserv_privs.change(ZPRIVS_RAISE))
+ zlog (NULL, LOG_ERR, "Can't raise privileges");
+ if (sysctl (mib_ipv6, MIB_SIZ, NULL, NULL, &ip6forwarding, len) < 0)
{
+ if (zserv_privs.change(ZPRIVS_LOWER))
+ zlog (NULL, LOG_ERR, "Can't lower privileges");
zlog_warn ("can't get ip6forwarding value");
return -1;
}
+ if (zserv_privs.change(ZPRIVS_LOWER))
+ zlog (NULL, LOG_ERR, "Can't lower privileges");
return ip6forwarding;
}
@@ -136,11 +163,17 @@ ipforward_ipv6_off ()
int ip6forwarding = 0;
len = sizeof ip6forwarding;
- if (sysctl (mib_ipv6, MIB_SIZ, NULL, NULL, &ip6forwarding, len) < 0)
+ if (zserv_privs.change(ZPRIVS_RAISE))
+ zlog (NULL, LOG_ERR, "Can't raise privileges");
+ if (sysctl (mib_ipv6, MIB_SIZ, NULL, NULL, &ip6forwarding, len) < 0)
{
+ if (zserv_privs.change(ZPRIVS_LOWER))
+ zlog (NULL, LOG_ERR, "Can't lower privileges");
zlog_warn ("can't get ip6forwarding value");
return -1;
}
+ if (zserv_privs.change(ZPRIVS_LOWER))
+ zlog (NULL, LOG_ERR, "Can't lower privileges");
return ip6forwarding;
}
#endif /* HAVE_IPV6 */
diff --git a/zebra/main.c b/zebra/main.c
index 25d8b6de..1c9269d5 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -1,5 +1,4 @@
-/*
- * zebra daemon main routine.
+/* zebra daemon main routine.
* Copyright (C) 1997, 98 Kunihiro Ishiguro
*
* This file is part of GNU Zebra.
@@ -30,6 +29,7 @@
#include "memory.h"
#include "prefix.h"
#include "log.h"
+#include "privs.h"
#include "zebra/rib.h"
#include "zebra/zserv.h"
@@ -62,10 +62,35 @@ struct option longopts[] =
{ "vty_addr", required_argument, NULL, 'A'},
{ "vty_port", required_argument, NULL, 'P'},
{ "retain", no_argument, NULL, 'r'},
+ { "user", required_argument, NULL, 'u'},
{ "version", no_argument, NULL, 'v'},
{ 0 }
};
+zebra_capabilities_t _caps_p [] =
+{
+ ZCAP_ADMIN,
+ ZCAP_RAW,
+ ZCAP_BIND,
+ ZCAP_SYS_ADMIN,
+ ZCAP_FOWNER,
+};
+
+/* zebra privileges to run with */
+struct zebra_privs_t zserv_privs =
+{
+#if defined(ZEBRA_USER) && defined(ZEBRA_GROUP)
+ .user = ZEBRA_USER,
+ .group = ZEBRA_GROUP,
+#endif
+#ifdef VTY_GROUP
+ .vty_group = VTY_GROUP,
+#endif
+ .caps_p = _caps_p,
+ .cap_num_p = sizeof(_caps_p)/sizeof(_caps_p[0]),
+ .cap_num_i = 0
+};
+
/* Default configuration file path. */
char config_current[] = DEFAULT_CONFIG_FILE;
char config_default[] = SYSCONFDIR DEFAULT_CONFIG_FILE;
@@ -93,6 +118,7 @@ redistribution between different routing protocols.\n\n\
-A, --vty_addr Set vty's bind address\n\
-P, --vty_port Set vty's port number\n\
-r, --retain When program terminates, retain added route by zebra.\n\
+-u, --user User and group to run as\n\
-v, --version Print program version\n\
-h, --help Display this help and exit\n\
\n\
@@ -174,7 +200,7 @@ main (int argc, char **argv)
{
char *p;
char *vty_addr = NULL;
- int vty_port = 0;
+ int vty_port = ZEBRA_VTY_PORT;
int batch_mode = 0;
int daemon_mode = 0;
char *config_file = NULL;
@@ -196,7 +222,7 @@ main (int argc, char **argv)
{
int opt;
- opt = getopt_long (argc, argv, "bdklf:hA:P:rv", longopts, 0);
+ opt = getopt_long (argc, argv, "bdklf:hA:P:ru:v", longopts, 0);
if (opt == EOF)
break;
@@ -226,11 +252,22 @@ main (int argc, char **argv)
pid_file = optarg;
break;
case 'P':
+ /* Deal with atoi() returning 0 on failure, and zebra not
+ listening on zebra port... */
+ if (strcmp(optarg, "0") == 0)
+ {
+ vty_port = 0;
+ break;
+ }
vty_port = atoi (optarg);
+ vty_port = (vty_port ? vty_port : ZEBRA_VTY_PORT);
break;
case 'r':
retain_mode = 1;
break;
+ case 'u':
+ zserv_privs.user = zserv_privs.group = optarg;
+ break;
case 'v':
print_version (progname);
exit (0);
@@ -247,6 +284,9 @@ main (int argc, char **argv)
/* Make master thread emulator. */
master = thread_master_create ();
+ /* privs initialise */
+ zprivs_init (&zserv_privs);
+
/* Vty related initialize. */
signal_init ();
cmd_init (1);
@@ -305,8 +345,7 @@ main (int argc, char **argv)
pid = getpid ();
/* Make vty server socket. */
- vty_serv_sock (vty_addr,
- vty_port ? vty_port : ZEBRA_VTY_PORT, ZEBRA_VTYSH_PATH);
+ vty_serv_sock (vty_addr, vty_port, ZEBRA_VTYSH_PATH);
while (thread_fetch (master, &thread))
thread_call (&thread);
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 7a8073c2..f4f51034 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -33,6 +33,8 @@
#include "connected.h"
#include "table.h"
#include "rib.h"
+#include "thread.h"
+#include "privs.h"
#include "zebra/zserv.h"
#include "zebra/redistribute.h"
@@ -66,6 +68,8 @@ struct message nlmsg_str[] =
extern int rtm_table_default;
+extern struct zebra_privs_t zserv_privs;
+
/* Make socket for Linux netlink interface. */
static int
netlink_socket (struct nlsock *nl, unsigned long groups)
@@ -97,6 +101,9 @@ netlink_socket (struct nlsock *nl, unsigned long groups)
snl.nl_groups = groups;
/* Bind the socket to the netlink structure for anything. */
+ if ( zserv_privs.change(ZPRIVS_RAISE) )
+ zlog (NULL, LOG_ERR, "Can't raise privileges");
+
ret = bind (sock, (struct sockaddr *) &snl, sizeof snl);
if (ret < 0)
{
@@ -105,6 +112,9 @@ netlink_socket (struct nlsock *nl, unsigned long groups)
close (sock);
return -1;
}
+
+ if ( zserv_privs.change(ZPRIVS_LOWER) )
+ zlog (NULL, LOG_ERR, "Can't lower privileges");
/* multiple netlink sockets will have different nl_pid */
namelen = sizeof snl;
@@ -122,6 +132,39 @@ netlink_socket (struct nlsock *nl, unsigned long groups)
return ret;
}
+int set_netlink_blocking(struct nlsock *nl, int *flags)
+{
+
+ /* Change socket flags for blocking I/O. */
+ if((*flags = fcntl(nl->sock, F_GETFL, 0)) < 0)
+ {
+ zlog (NULL, LOG_ERR, "%s:%i F_GETFL error: %s",
+ __FUNCTION__, __LINE__, strerror (errno));
+ return -1;
+ }
+ *flags &= ~O_NONBLOCK;
+ if(fcntl(nl->sock, F_SETFL, *flags) < 0)
+ {
+ zlog (NULL, LOG_ERR, "%s:%i F_SETFL error: %s",
+ __FUNCTION__, __LINE__, strerror (errno));
+ return -1;
+ }
+ return 0;
+}
+
+int set_netlink_nonblocking(struct nlsock *nl, int *flags)
+{
+ /* Restore socket flags for nonblocking I/O */
+ *flags |= O_NONBLOCK;
+ if(fcntl(nl->sock, F_SETFL, *flags) < 0)
+ {
+ zlog (NULL, LOG_ERR, "%s:%i F_SETFL error: %s",
+ __FUNCTION__, __LINE__, strerror (errno));
+ return -1;
+ }
+ return 0;
+}
+
/* Get type specified information from netlink. */
static int
netlink_request (int family, int type, struct nlsock *nl)
@@ -152,6 +195,12 @@ netlink_request (int family, int type, struct nlsock *nl)
req.nlh.nlmsg_pid = 0;
req.nlh.nlmsg_seq = ++nl->seq;
req.g.rtgen_family = family;
+
+ /* linux appears to check capabilities on every message
+ * have to raise caps for every message sent
+ */
+ if ( zserv_privs.change(ZPRIVS_RAISE) )
+ zlog (NULL, LOG_ERR, "Can't raise privileges");
ret = sendto (nl->sock, (void*) &req, sizeof req, 0,
(struct sockaddr*) &snl, sizeof snl);
@@ -160,6 +209,10 @@ netlink_request (int family, int type, struct nlsock *nl)
zlog (NULL, LOG_ERR, "%s sendto failed: %s", nl->name, strerror (errno));
return -1;
}
+
+ if ( zserv_privs.change(ZPRIVS_LOWER) )
+ zlog (NULL, LOG_ERR, "Can't lower privileges");
+
return 0;
}
@@ -181,7 +234,13 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *),
struct msghdr msg = { (void*)&snl, sizeof snl, &iov, 1, NULL, 0, 0};
struct nlmsghdr *h;
+ if ( zserv_privs.change(ZPRIVS_RAISE) )
+ zlog (NULL, LOG_ERR, "Can't raise privileges");
+
status = recvmsg (nl->sock, &msg, 0);
+
+ if ( zserv_privs.change(ZPRIVS_LOWER) )
+ zlog (NULL, LOG_ERR, "Can't lower privileges");
if (status < 0)
{
@@ -244,11 +303,26 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *),
nl->name);
return -1;
}
- zlog (NULL, LOG_ERR, "%s error: %s, type=%s(%u), seq=%u, pid=%d",
- nl->name, strerror (-err->error),
- lookup (nlmsg_str, err->msg.nlmsg_type),
- err->msg.nlmsg_type, err->msg.nlmsg_seq,
+
+ /* Deal with Error Noise - MAG*/
+ {
+ int loglvl = LOG_ERR;
+ int errnum = err->error;
+ int msg_type = err->msg.nlmsg_type;
+
+ if (nl == &netlink_cmd
+ && (-errnum == ENODEV || -errnum == ESRCH)
+ && (msg_type == RTM_NEWROUTE
+ || msg_type == RTM_DELROUTE))
+ loglvl = LOG_DEBUG;
+
+ zlog (NULL, loglvl, "%s error: %s, type=%s(%u), "
+ "seq=%u, pid=%d",
+ nl->name, strerror (-errnum),
+ lookup (nlmsg_str, msg_type),
+ msg_type, err->msg.nlmsg_seq,
err->msg.nlmsg_pid);
+ }
/*
ret = -1;
continue;
@@ -388,6 +462,7 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h)
void *broad = NULL;
u_char flags = 0;
char *label = NULL;
+ int peeronly = 0;
ifa = NLMSG_DATA (h);
@@ -416,40 +491,56 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h)
return -1;
}
- if (tb[IFA_ADDRESS] == NULL)
- tb[IFA_ADDRESS] = tb[IFA_LOCAL];
-
- if (ifp->flags & IFF_POINTOPOINT)
+ if (IS_ZEBRA_DEBUG_KERNEL) /* remove this line to see initial ifcfg */
{
+ char buf[BUFSIZ];
+ zlog_info ("netlink_interface_addr %s %s/%d:",
+ lookup (nlmsg_str, h->nlmsg_type),
+ ifp->name, ifa->ifa_prefixlen);
if (tb[IFA_LOCAL])
- {
- addr = RTA_DATA (tb[IFA_LOCAL]);
- if (tb[IFA_ADDRESS])
- broad = RTA_DATA (tb[IFA_ADDRESS]);
- else
- broad = NULL;
- }
- else
- {
- if (tb[IFA_ADDRESS])
- addr = RTA_DATA (tb[IFA_ADDRESS]);
- else
- addr = NULL;
- }
- }
- else
- {
+ zlog_info (" IFA_LOCAL %s", inet_ntop (ifa->ifa_family,
+ RTA_DATA (tb[IFA_LOCAL]), buf, BUFSIZ));
if (tb[IFA_ADDRESS])
- addr = RTA_DATA (tb[IFA_ADDRESS]);
- else
- addr = NULL;
-
+ zlog_info (" IFA_ADDRESS %s", inet_ntop (ifa->ifa_family,
+ RTA_DATA (tb[IFA_ADDRESS]), buf, BUFSIZ));
if (tb[IFA_BROADCAST])
- broad = RTA_DATA(tb[IFA_BROADCAST]);
- else
- broad = NULL;
+ zlog_info (" IFA_BROADCAST %s", inet_ntop (ifa->ifa_family,
+ RTA_DATA (tb[IFA_BROADCAST]), buf, BUFSIZ));
+ if (tb[IFA_LABEL] && strcmp (ifp->name, RTA_DATA (tb[IFA_LABEL])))
+ zlog_info (" IFA_LABEL %s", RTA_DATA (tb[IFA_LABEL]));
}
+ /* peer or broadcast network? */
+ if (ifa->ifa_family == AF_INET)
+ peeronly = if_is_pointopoint (ifp) ||
+ ifa->ifa_prefixlen >= IPV4_MAX_PREFIXLEN - 1;
+#ifdef HAVE_IPV6
+ if (ifa->ifa_family == AF_INET6) {
+ peeronly = if_is_pointopoint (ifp) ||
+ ifa->ifa_prefixlen >= IPV6_MAX_PREFIXLEN - 1;
+ }
+#endif /* HAVE_IPV6*/
+ if (!(tb[IFA_LOCAL] && tb[IFA_ADDRESS])) {
+ /* FIXME: IPv6 Appears to have only IFA_ADDRESS */
+ peeronly=0;
+ }
+
+ /* network. prefixlen applies to IFA_ADDRESS rather than IFA_LOCAL */
+ if (tb[IFA_ADDRESS] && !peeronly)
+ addr = RTA_DATA (tb[IFA_ADDRESS]);
+ else if (tb[IFA_LOCAL])
+ addr = RTA_DATA (tb[IFA_LOCAL]);
+ else
+ addr = NULL;
+
+ /* broadcast/peer */
+ if (tb[IFA_BROADCAST])
+ broad = RTA_DATA (tb[IFA_BROADCAST]);
+ else if (tb[IFA_ADDRESS] && peeronly)
+ broad = RTA_DATA (tb[IFA_ADDRESS]); /* peer address specified */
+ else
+ broad = NULL;
+
/* Flags. */
if (ifa->ifa_flags & IFA_F_SECONDARY)
SET_FLAG (flags, ZEBRA_IFA_SECONDARY);
@@ -787,16 +878,16 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
ifp->mtu = *(int *)RTA_DATA (tb[IFLA_MTU]);
ifp->metric = 1;
- if (if_is_up (ifp))
+ if (if_is_operative (ifp))
{
ifp->flags = ifi->ifi_flags & 0x0000fffff;
- if (! if_is_up (ifp))
+ if (! if_is_operative (ifp))
if_down (ifp);
}
else
{
ifp->flags = ifi->ifi_flags & 0x0000fffff;
- if (if_is_up (ifp))
+ if (if_is_operative (ifp))
if_up (ifp);
}
}
@@ -854,7 +945,19 @@ int
interface_lookup_netlink ()
{
int ret;
-
+ int flags;
+ int snb_ret;
+
+ /*
+ * Change netlink socket flags to blocking to ensure we get
+ * a reply via nelink_parse_info
+ */
+ snb_ret = set_netlink_blocking(&netlink_cmd, &flags);
+ if(snb_ret < 0)
+ zlog (NULL, LOG_WARNING,
+ "%s:%i Warning: Could not set netlink socket to blocking.",
+ __FUNCTION__, __LINE__);
+
/* Get interface information. */
ret = netlink_request (AF_PACKET, RTM_GETLINK, &netlink_cmd);
if (ret < 0)
@@ -881,6 +984,9 @@ interface_lookup_netlink ()
return ret;
#endif /* HAVE_IPV6 */
+ /* restore socket flags */
+ if(snb_ret == 0)
+ set_netlink_nonblocking(&netlink_cmd, &flags);
return 0;
}
@@ -890,7 +996,19 @@ int
netlink_route_read ()
{
int ret;
-
+ int flags;
+ int snb_ret;
+
+ /*
+ * Change netlink socket flags to blocking to ensure we get
+ * a reply via nelink_parse_info
+ */
+ snb_ret = set_netlink_blocking(&netlink_cmd, &flags);
+ if(snb_ret < 0)
+ zlog (NULL, LOG_WARNING,
+ "%s:%i Warning: Could not set netlink socket to blocking.",
+ __FUNCTION__, __LINE__);
+
/* Get IPv4 routing table. */
ret = netlink_request (AF_INET, RTM_GETROUTE, &netlink_cmd);
if (ret < 0)
@@ -909,6 +1027,9 @@ netlink_route_read ()
return ret;
#endif /* HAVE_IPV6 */
+ /* restore flags */
+ if(snb_ret == 0)
+ set_netlink_nonblocking(&netlink_cmd, &flags);
return 0;
}
@@ -992,6 +1113,7 @@ netlink_talk (struct nlmsghdr *n, struct nlsock *nl)
struct iovec iov = { (void*) n, n->nlmsg_len };
struct msghdr msg = {(void*) &snl, sizeof snl, &iov, 1, NULL, 0, 0};
int flags = 0;
+ int snb_ret;
memset (&snl, 0, sizeof snl);
snl.nl_family = AF_NETLINK;
@@ -1007,7 +1129,12 @@ netlink_talk (struct nlmsghdr *n, struct nlsock *nl)
n->nlmsg_seq);
/* Send message to netlink interface. */
+ if ( zserv_privs.change(ZPRIVS_RAISE) )
+ zlog (NULL, LOG_ERR, "Can't raise privileges");
status = sendmsg (nl->sock, &msg, 0);
+ if ( zserv_privs.change(ZPRIVS_LOWER) )
+ zlog (NULL, LOG_ERR, "Can't lower privileges");
+
if (status < 0)
{
zlog (NULL, LOG_ERR, "netlink_talk sendmsg() error: %s",
@@ -1019,17 +1146,11 @@ netlink_talk (struct nlmsghdr *n, struct nlsock *nl)
* Change socket flags for blocking I/O.
* This ensures we wait for a reply in netlink_parse_info().
*/
- if((flags = fcntl(nl->sock, F_GETFL, 0)) < 0)
- {
- zlog (NULL, LOG_ERR, "%s:%i F_GETFL error: %s",
- __FUNCTION__, __LINE__, strerror (errno));
- }
- flags &= ~O_NONBLOCK;
- if(fcntl(nl->sock, F_SETFL, flags) < 0)
- {
- zlog (NULL, LOG_ERR, "%s:%i F_SETFL error: %s",
- __FUNCTION__, __LINE__, strerror (errno));
- }
+ snb_ret = set_netlink_blocking(nl, &flags);
+ if(snb_ret < 0)
+ zlog (NULL, LOG_WARNING,
+ "%s:%i Warning: Could not set netlink socket to blocking.",
+ __FUNCTION__, __LINE__);
/*
* Get reply from netlink socket.
@@ -1038,12 +1159,8 @@ netlink_talk (struct nlmsghdr *n, struct nlsock *nl)
status = netlink_parse_info (netlink_talk_filter, nl);
/* Restore socket flags for nonblocking I/O */
- flags |= O_NONBLOCK;
- if(fcntl(nl->sock, F_SETFL, flags) < 0)
- {
- zlog (NULL, LOG_ERR, "%s:%i F_SETFL error: %s",
- __FUNCTION__, __LINE__, strerror (errno));
- }
+ if(snb_ret == 0)
+ set_netlink_nonblocking(nl, &flags);
return status;
}
@@ -1448,7 +1565,6 @@ kernel_address_delete_ipv4 (struct interface *ifp, struct connected *ifc)
return netlink_address (RTM_DELADDR, AF_INET, ifp, ifc);
}
-#include "thread.h"
extern struct thread_master *master;
diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c
index fe88be81..363363f7 100644
--- a/zebra/rt_socket.c
+++ b/zebra/rt_socket.c
@@ -27,10 +27,13 @@
#include "sockunion.h"
#include "log.h"
#include "str.h"
+#include "privs.h"
#include "zebra/debug.h"
#include "zebra/rib.h"
+extern struct zebra_privs_t zserv_privs;
+
int
rtm_write (int message,
union sockunion *dest,
@@ -188,13 +191,29 @@ kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib *rib, int family)
int
kernel_add_ipv4 (struct prefix *p, struct rib *rib)
{
- return kernel_rtm_ipv4 (RTM_ADD, p, rib, AF_INET);
+ int route;
+
+ if (zserv_privs.change(ZPRIVS_RAISE))
+ zlog (NULL, LOG_ERR, "Can't raise privileges");
+ route = kernel_rtm_ipv4 (RTM_ADD, p, rib, AF_INET);
+ if (zserv_privs.change(ZPRIVS_LOWER))
+ zlog (NULL, LOG_ERR, "Can't lower privileges");
+
+ return route;
}
int
kernel_delete_ipv4 (struct prefix *p, struct rib *rib)
{
- return kernel_rtm_ipv4 (RTM_DELETE, p, rib, AF_INET);
+ int route;
+
+ if (zserv_privs.change(ZPRIVS_RAISE))
+ zlog (NULL, LOG_ERR, "Can't raise privileges");
+ route = kernel_rtm_ipv4 (RTM_DELETE, p, rib, AF_INET);
+ if (zserv_privs.change(ZPRIVS_LOWER))
+ zlog (NULL, LOG_ERR, "Can't lower privileges");
+
+ return route;
}
#ifdef HAVE_IPV6
@@ -422,13 +441,29 @@ kernel_rtm_ipv6_multipath (int cmd, struct prefix *p, struct rib *rib,
int
kernel_add_ipv6 (struct prefix *p, struct rib *rib)
{
- return kernel_rtm_ipv6_multipath (RTM_ADD, p, rib, AF_INET6);
+ int route;
+
+ if (zserv_privs.change(ZPRIVS_RAISE))
+ zlog (NULL, LOG_ERR, "Can't raise privileges");
+ route = kernel_rtm_ipv6_multipath (RTM_ADD, p, rib, AF_INET6);
+ if (zserv_privs.change(ZPRIVS_LOWER))
+ zlog (NULL, LOG_ERR, "Can't lower privileges");
+
+ return route;
}
int
kernel_delete_ipv6 (struct prefix *p, struct rib *rib)
{
- return kernel_rtm_ipv6_multipath (RTM_DELETE, p, rib, AF_INET6);
+ int route;
+
+ if (zserv_privs.change(ZPRIVS_RAISE))
+ zlog (NULL, LOG_ERR, "Can't raise privileges");
+ route = kernel_rtm_ipv6_multipath (RTM_DELETE, p, rib, AF_INET6);
+ if (zserv_privs.change(ZPRIVS_LOWER))
+ zlog (NULL, LOG_ERR, "Can't lower privileges");
+
+ return route;
}
/* Delete IPv6 route from the kernel. */
@@ -436,6 +471,14 @@ int
kernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate,
int index, int flags, int table)
{
- return kernel_rtm_ipv6 (RTM_DELETE, dest, gate, index, flags);
+ int route;
+
+ if (zserv_privs.change(ZPRIVS_RAISE))
+ zlog (NULL, LOG_ERR, "Can't raise privileges");
+ route = kernel_rtm_ipv6 (RTM_DELETE, dest, gate, index, flags);
+ if (zserv_privs.change(ZPRIVS_LOWER))
+ zlog (NULL, LOG_ERR, "Can't lower privileges");
+
+ return route;
}
#endif /* HAVE_IPV6 */
diff --git a/zebra/rtadv.c b/zebra/rtadv.c
index 4d244197..9dcee8ea 100644
--- a/zebra/rtadv.c
+++ b/zebra/rtadv.c
@@ -29,11 +29,14 @@
#include "prefix.h"
#include "linklist.h"
#include "command.h"
+#include "privs.h"
#include "zebra/interface.h"
#include "zebra/rtadv.h"
#include "zebra/debug.h"
+extern struct zebra_privs_t zserv_privs;
+
#if defined (HAVE_IPV6) && defined (RTADV)
/* If RFC2133 definition is used. */
@@ -409,8 +412,16 @@ rtadv_make_socket (void)
int ret;
struct icmp6_filter filter;
+ if ( zserv_privs.change (ZPRIVS_RAISE) )
+ zlog_err ("rtadv_make_socket: could not raise privs, %s",
+ strerror (errno) );
+
sock = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+ if ( zserv_privs.change (ZPRIVS_LOWER) )
+ zlog_err ("rtadv_make_socket: could not lower privs, %s",
+ strerror (errno) );
+
/* When we can't make ICMPV6 socket simply back. Router
advertisement feature will not be supported. */
if (sock < 0)
diff --git a/zebra/zserv.c b/zebra/zserv.c
index aa1c8342..0508f905 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -33,6 +33,7 @@
#include "sockunion.h"
#include "log.h"
#include "zclient.h"
+#include "privs.h"
#include "zebra/zserv.h"
#include "zebra/redistribute.h"
@@ -50,6 +51,8 @@ int rtm_table_default = 0;
void zebra_event (enum event event, int sock, struct zserv *client);
+extern struct zebra_privs_t zserv_privs;
+
extern struct thread_master *master;
/* For logging of zebra meesages. */
@@ -195,6 +198,7 @@ zsend_interface_add (struct zserv *client, struct interface *ifp)
/* Interface information. */
stream_put (s, ifp->name, INTERFACE_NAMSIZ);
stream_putl (s, ifp->ifindex);
+ stream_putc (s, ifp->status);
stream_putl (s, ifp->flags);
stream_putl (s, ifp->metric);
stream_putl (s, ifp->mtu);
@@ -235,6 +239,7 @@ zsend_interface_delete (struct zserv *client, struct interface *ifp)
stream_putc (s, ZEBRA_INTERFACE_DELETE);
stream_put (s, ifp->name, INTERFACE_NAMSIZ);
stream_putl (s, ifp->ifindex);
+ stream_putc (s, ifp->status);
stream_putl (s, ifp->flags);
stream_putl (s, ifp->metric);
stream_putl (s, ifp->mtu);
@@ -363,6 +368,7 @@ zsend_interface_up (struct zserv *client, struct interface *ifp)
/* Interface information. */
stream_put (s, ifp->name, INTERFACE_NAMSIZ);
stream_putl (s, ifp->ifindex);
+ stream_putc (s, ifp->status);
stream_putl (s, ifp->flags);
stream_putl (s, ifp->metric);
stream_putl (s, ifp->mtu);
@@ -397,6 +403,7 @@ zsend_interface_down (struct zserv *client, struct interface *ifp)
/* Interface information. */
stream_put (s, ifp->name, INTERFACE_NAMSIZ);
stream_putl (s, ifp->ifindex);
+ stream_putc (s, ifp->status);
stream_putl (s, ifp->flags);
stream_putl (s, ifp->metric);
stream_putl (s, ifp->mtu);
@@ -1622,6 +1629,9 @@ zebra_serv ()
sockopt_reuseaddr (accept_sock);
sockopt_reuseport (accept_sock);
+ if ( zserv_privs.change(ZPRIVS_RAISE) )
+ zlog (NULL, LOG_ERR, "Can't raise privileges");
+
ret = bind (accept_sock, (struct sockaddr *)&addr,
sizeof (struct sockaddr_in));
if (ret < 0)
@@ -1631,6 +1641,9 @@ zebra_serv ()
close (accept_sock); /* Avoid sd leak. */
return;
}
+
+ if ( zserv_privs.change(ZPRIVS_LOWER) )
+ zlog (NULL, LOG_ERR, "Can't lower privileges");
ret = listen (accept_sock, 1);
if (ret < 0)