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

	* Merge of zebra privileges
diff --git a/ospfd/Makefile.am b/ospfd/Makefile.am
index 81315da..81f212c 100644
--- a/ospfd/Makefile.am
+++ b/ospfd/Makefile.am
@@ -28,7 +28,7 @@
 ospfd_SOURCES = \
 	ospf_main.c $(libospf_a_SOURCES)
 
-ospfd_LDADD = -L../lib -lzebra
+ospfd_LDADD = -L../lib -lzebra @LIBCAP@
 
 sysconf_DATA = ospfd.conf.sample
 
diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c
index 0ac82a6..b1d1fd4 100644
--- a/ospfd/ospf_main.c
+++ b/ospfd/ospf_main.c
@@ -36,6 +36,8 @@
 #include "stream.h"
 #include "log.h"
 #include "memory.h"
+#include "privs.h"
+#include "debug.h"
 
 #include "ospfd/ospfd.h"
 #include "ospfd/ospf_interface.h"
@@ -47,6 +49,29 @@
 #include "ospfd/ospf_zebra.h"
 #include "ospfd/ospf_vty.h"
 
+/* ospfd privileges */
+zebra_capabilities_t _caps_p [] = 
+{
+  ZCAP_RAW,
+  ZCAP_BIND,
+  ZCAP_BROADCAST,
+  ZCAP_ADMIN,
+};
+
+struct zebra_privs_t ospfd_privs =
+{
+#if defined(ZEBRA_USER) && defined(ZEBRA_GROUP)
+  .user = ZEBRA_USER,
+  .group = ZEBRA_GROUP,
+#endif
+#if defined(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
+};
+
 /* Configuration filename and directory. */
 char config_current[] = OSPF_DEFAULT_CONFIG;
 char config_default[] = SYSCONFDIR OSPF_DEFAULT_CONFIG;
@@ -61,6 +86,7 @@
   { "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 +114,7 @@
 -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\
@@ -162,6 +189,11 @@
   signal_set (SIGTTOU, SIG_IGN);
 #endif
   signal_set (SIGUSR1, sigusr1);
+#ifdef HAVE_GLIBC_BACKTRACE
+  signal_set (SIGBUS, debug_print_trace);
+  signal_set (SIGSEGV, debug_print_trace);
+  signal_set (SIGILL, debug_print_trace); 
+#endif /* HAVE_GLIBC_BACKTRACE */
 }
 
 /* OSPFd main routine. */
@@ -200,7 +232,7 @@
     {
       int opt;
 
-      opt = getopt_long (argc, argv, "dlf:hA:P:v", longopts, 0);
+      opt = getopt_long (argc, argv, "dlf:hA:P:u:v", longopts, 0);
     
       if (opt == EOF)
 	break;
@@ -232,6 +264,9 @@
           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);
@@ -249,6 +284,7 @@
   master = om->master;
 
   /* Library inits. */
+  zprivs_init (&ospfd_privs);
   signal_init ();
   cmd_init (1);
   debug_init ();
diff --git a/ospfd/ospf_network.c b/ospfd/ospf_network.c
index 56ec864..87aec1e 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,20 @@
   int ospf_sock;
   int ret, tos, hincl = 1;
 
+  if ( ospfd_privs.change (ZPRIVS_RAISE) )
+    zlog_err ("ospf_sock_init: could not raise privs, %s",
+               strerror (errno) );
+    
   ospf_sock = socket (AF_INET, SOCK_RAW, IPPROTO_OSPFIGP);
   if (ospf_sock < 0)
     {
+      if ( ospfd_privs.change (ZPRIVS_LOWER) )
+        zlog_err ("ospf_sock_init: could not lower privs, %s",
+                   strerror (errno) );
       zlog_warn ("ospf_read_sock_init: socket: %s", strerror (errno));
       return -1;
     }
+    
 
   /* Set precedence field. */
 #ifdef IPTOS_PREC_INTERNETCONTROL
@@ -165,6 +178,9 @@
 		    (char *) &tos, sizeof (int));
   if (ret < 0)
     {
+      if ( ospfd_privs.change (ZPRIVS_LOWER) )
+        zlog_err ("ospf_sock_init: could not lower privs, %s",
+                   strerror (errno) );
       zlog_warn ("can't set sockopt IP_TOS %d to socket %d", tos, ospf_sock);
       close (ospf_sock);	/* Prevent sd leak. */
       return ret;
@@ -174,19 +190,40 @@
   /* we will include IP header with packet */
   ret = setsockopt (ospf_sock, IPPROTO_IP, IP_HDRINCL, &hincl, sizeof (hincl));
   if (ret < 0)
-    zlog_warn ("Can't set IP_HDRINCL option");
+    {
+      if ( ospfd_privs.change (ZPRIVS_LOWER) )
+        zlog_err ("ospf_sock_init: could not lower privs, %s",
+                   strerror (errno) );
+      zlog_warn ("Can't set IP_HDRINCL option");
+    }
 
 #if defined (IP_PKTINFO)
   ret = setsockopt (ospf_sock, IPPROTO_IP, IP_PKTINFO, &hincl, sizeof (hincl));
    if (ret < 0)
-    zlog_warn ("Can't set IP_PKTINFO option");
+     {
+       if ( ospfd_privs.change (ZPRIVS_LOWER) )
+         zlog_err ("ospf_sock_init: could not lower privs, %s",
+                   strerror (errno) );
+       zlog_warn ("Can't set IP_PKTINFO option");
+     }
 #elif defined (IP_RECVIF)
   ret = setsockopt (ospf_sock, IPPROTO_IP, IP_RECVIF, &hincl, sizeof (hincl));
    if (ret < 0)
-    zlog_warn ("Can't set IP_RECVIF option");
+     {
+       if ( ospfd_privs.change (ZPRIVS_LOWER) )
+         zlog_err ("ospf_sock_init: could not lower privs, %s",
+                   strerror (errno) );
+       zlog_warn ("Can't set IP_RECVIF option");
+     }
 #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, %s",
+               strerror (errno) );
+    }
  
   return ospf_sock;
 }
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index d8646f0..a12a011 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -53,6 +53,7 @@
 #include "ospfd/ospf_ase.h"
 
 
+
 /* OSPF process wide configuration. */
 static struct ospf_master ospf_master;