2003-06-04 Paul Jakma <paul@dishone.st>

	* Merge of zebra privileges
diff --git a/zebra/Makefile.am b/zebra/Makefile.am
index 6214767..ce56467 100644
--- a/zebra/Makefile.am
+++ b/zebra/Makefile.am
@@ -13,9 +13,10 @@
 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
 
@@ -25,7 +26,7 @@
 
 noinst_HEADERS = \
 	connected.h ioctl.h rib.h rt.h zserv.h redistribute.h debug.h rtadv.h \
-	interface.h ipforward.h irdp.h
+	interface.h ipforward.h
 
 zebra_LDADD = ../lib/libzebra.a $(otherobj) $(LIB_IPV6)
 
@@ -38,7 +39,7 @@
 	ipforward_solaris.c ipforward_sysctl.c rt_ioctl.c rt_netlink.c \
 	rt_socket.c rtread_netlink.c rtread_proc.c rtread_sysctl.c \
 	rtread_getmsg.c kernel_socket.c kernel_netlink.c mtu_kvm.c \
-	GNOME-SMI GNOME-PRODUCT-ZEBRA-MIB irdp.c
+	GNOME-SMI GNOME-PRODUCT-ZEBRA-MIB
 
 #client : client_main.o ../lib/libzebra.a
 #	$(CC) -g -o client client_main.o ../lib/libzebra.a $(LIBS) $(LIB_IPV6)
diff --git a/zebra/ioctl.c b/zebra/ioctl.c
index 3e5d1d2..f8e7f22 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 @@
   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 @@
   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 eb8cef0..a31ec84 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 @@
 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,14 @@
 {
   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 +142,13 @@
 {
   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 +165,13 @@
 {
   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_solaris.c b/zebra/ipforward_solaris.c
index 63d1110..fe06e74 100644
--- a/zebra/ipforward_solaris.c
+++ b/zebra/ipforward_solaris.c
@@ -22,6 +22,7 @@
 
 #include <zebra.h>
 #include "log.h"
+#include "prefix.h"
 
 /*
 ** Solaris should define IP_DEV_NAME in <inet/ip.h>, but we'll save
@@ -33,6 +34,9 @@
 #define IP_DEV_NAME "/dev/ip"
 #endif
 /*
+
+extern struct zebra_privs_t zserv_privs;
+
 ** This is a limited ndd style function that operates one integer
 ** value only.  Errors return -1. ND_SET commands return 0 on
 ** success. ND_GET commands return the value on success (which could
@@ -63,30 +67,48 @@
     zlog_err("internal error - inappropriate command given to solaris_nd()%s:%d", __FILE__, __LINE__);
     return -1;
   }
+
   strioctl.ic_cmd = cmd;
   strioctl.ic_timout = 0;
   strioctl.ic_len = ND_BUFFER_SIZE;
   strioctl.ic_dp = nd_buf;
-  if ((fd = open (device, O_RDWR)) < 0) {
-    zlog_warn("failed to open device %s - %s", device, strerror(errno));
-    return -1;
-  }
-  if (ioctl (fd, I_STR, &strioctl) < 0) {
-    close (fd);
-    zlog_warn("ioctl I_STR failed on device %s - %s", device,strerror(errno));
-    return -1;
-  }
-  close(fd);
-  if (cmd == ND_GET) {
-    errno = 0;
-    retval = atoi(nd_buf);
-    if (errno) {
-      zlog_warn("failed to convert returned value to integer - %s",strerror(errno));
-      retval = -1;
+  
+  if ( zserv_privs.change (ZPRIVS_RAISE) )
+       zlog_err ("solaris_nd: Can't raise privileges");
+  if ((fd = open (device, O_RDWR)) < 0) 
+    {
+      zlog_warn("failed to open device %s - %s", device, strerror(errno));
+      if ( zserv_privs.change (ZPRIVS_LOWER) )
+        zlog_err ("solaris_nd: Can't lower privileges");
+      return -1;
     }
-  } else {
-    retval = 0;
-  }
+  if (ioctl (fd, I_STR, &strioctl) < 0) 
+    {
+      if ( zserv_privs.change (ZPRIVS_LOWER) )
+        zlog_err ("solaris_nd: Can't lower privileges");
+      close (fd);
+      zlog_warn("ioctl I_STR failed on device %s - %s", device,strerror(errno));
+      return -1;
+    }
+  close(fd);
+  if ( zserv_privs.change (ZPRIVS_LOWER) )
+         zlog_err ("solaris_nd: Can't lower privileges");
+  
+  if (cmd == ND_GET) 
+    {
+      errno = 0;
+      retval = atoi(nd_buf);
+      if (errno) 
+        {
+          zlog_warn("failed to convert returned value to integer - %s",
+                    strerror(errno));
+          retval = -1;
+        }
+    } 
+  else 
+    {
+      retval = 0;
+    }
   return retval;
 }
 
diff --git a/zebra/ipforward_sysctl.c b/zebra/ipforward_sysctl.c
index 828eb86..53b6c6f 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 @@
   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 @@
   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 @@
   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 @@
   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 @@
   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/kernel_socket.c b/zebra/kernel_socket.c
index 17893a8..30e0fb1 100644
--- a/zebra/kernel_socket.c
+++ b/zebra/kernel_socket.c
@@ -31,11 +31,14 @@
 #include "str.h"
 #include "table.h"
 #include "rib.h"
+#include "privs.h"
 
 #include "zebra/interface.h"
 #include "zebra/zserv.h"
 #include "zebra/debug.h"
 
+extern struct zebra_privs_t zserv_privs;
+
 /* Socket length roundup function. */
 #define ROUNDUP(a) \
   ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
@@ -798,16 +801,23 @@
 void
 routing_socket ()
 {
+  if ( zserv_privs.change (ZPRIVS_RAISE) )
+    zlog_err ("routing_socket: Can't raise privileges");
+
   routing_sock = socket (AF_ROUTE, SOCK_RAW, 0);
 
   if (routing_sock < 0) 
     {
+      if ( zserv_privs.change (ZPRIVS_LOWER) )
+        zlog_err ("routing_socket: Can't lower privileges");
       zlog_warn ("Can't init kernel routing socket");
       return;
     }
 
   if (fcntl (routing_sock, F_SETFL, O_NONBLOCK) < 0) 
     zlog_warn ("Can't set O_NONBLOCK to routing socket");
+  if ( zserv_privs.change (ZPRIVS_LOWER) )
+    zlog_err ("routing_socket: Can't lower privileges");
 
   /* kernel_read needs rewrite. */
   thread_add_read (master, kernel_read, NULL, routing_sock);
diff --git a/zebra/main.c b/zebra/main.c
index 66469a2..72b1fc4 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,32 @@
   { "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_SYS_ADMIN,
+};
+
+/* 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 +115,7 @@
 -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\
@@ -196,7 +219,7 @@
     {
       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;
@@ -239,6 +262,9 @@
 	case 'r':
 	  retain_mode = 1;
 	  break;
+  case 'u':
+    zserv_privs.user = zserv_privs.group = optarg;
+    break;
 	case 'v':
 	  print_version (progname);
 	  exit (0);
@@ -255,6 +281,9 @@
   /* Make master thread emulator. */
   master = thread_master_create ();
 
+  /* privs initialise */
+  zprivs_init (&zserv_privs);
+
   /* Vty related initialize. */
   signal_init ();
   cmd_init (1);
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 87062dc..e151462 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -34,6 +34,7 @@
 #include "table.h"
 #include "rib.h"
 #include "thread.h"
+#include "privs.h"
 
 #include "zebra/zserv.h"
 #include "zebra/redistribute.h"
@@ -67,6 +68,8 @@
 
 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)
@@ -98,14 +101,25 @@
   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");
+     return -1;
+   } 
+
   ret = bind (sock, (struct sockaddr *) &snl, sizeof snl);
   if (ret < 0)
     {
+      if ( zserv_privs.change(ZPRIVS_LOWER) )
+        zlog (NULL, LOG_ERR, "Can't lower privileges");
       zlog (NULL, LOG_ERR, "Can't bind %s socket to group 0x%x: %s", 
 	    nl->name, snl.nl_groups, strerror (errno));
       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;
@@ -186,14 +200,28 @@
   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");
+      return -1;
+    }
  
   ret = sendto (nl->sock, (void*) &req, sizeof req, 0, 
 		(struct sockaddr*) &snl, sizeof snl);
+		
+  if ( zserv_privs.change(ZPRIVS_LOWER) )
+        zlog (NULL, LOG_ERR, "Can't lower privileges");
+        
   if (ret < 0)
-    {
+    {      
       zlog (NULL, LOG_ERR, "%s sendto failed: %s", nl->name, strerror (errno));
       return -1;
     }
+
   return 0;
 }
 
@@ -215,7 +243,13 @@
       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)
 	{
@@ -1104,7 +1138,12 @@
 	      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",
diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c
index 19b2fc2..d603c60 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,
@@ -187,13 +190,29 @@
 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
@@ -421,13 +440,29 @@
 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. */
@@ -435,6 +470,14 @@
 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 8f4b377..9dcee8e 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. */
@@ -143,7 +146,7 @@
   struct cmsghdr  *cmsgptr;
   struct in6_pktinfo *pkt;
   struct sockaddr_in6 addr;
-#if HAVE_SOCKADDR_DL
+#ifdef HAVE_SOCKADDR_DL
   struct sockaddr_dl *sdl;
 #endif /* HAVE_SOCKADDR_DL */
   char adata [sizeof (struct cmsghdr) + sizeof (struct in6_pktinfo)];
@@ -409,8 +412,16 @@
   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 70e7672..975574a 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 @@
 
 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. */
@@ -1638,6 +1641,9 @@
   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)
@@ -1647,6 +1653,9 @@
       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)