quagga: option "-z" ("--socket <path>") added

All daemons modified to support custom path to zserv
socket.

lib: generalize a zclient connection

zclient_socket_connect added. zclient_socket and
zclient_socket_un were hidden under static expression.
"zclient_serv_path_set" modified.
diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c
index 822805c..8dede58 100644
--- a/bgpd/bgp_main.c
+++ b/bgpd/bgp_main.c
@@ -54,6 +54,7 @@
   { "daemon",      no_argument,       NULL, 'd'},
   { "config_file", required_argument, NULL, 'f'},
   { "pid_file",    required_argument, NULL, 'i'},
+  { "socket",      required_argument, NULL, 'z'},
   { "bgp_port",    required_argument, NULL, 'p'},
   { "listenon",    required_argument, NULL, 'l'},
   { "vty_addr",    required_argument, NULL, 'A'},
@@ -150,6 +151,7 @@
 -d, --daemon       Runs in daemon mode\n\
 -f, --config_file  Set configuration file name\n\
 -i, --pid_file     Set process identifier file name\n\
+-z, --socket       Set path of zebra socket\n\
 -p, --bgp_port     Set bgp protocol's port number\n\
 -l, --listenon     Listen on specified address (implies -n)\n\
 -A, --vty_addr     Set vty's bind address\n\
@@ -337,7 +339,7 @@
   /* Command line argument treatment. */
   while (1) 
     {
-      opt = getopt_long (argc, argv, "df:i:hp:l:A:P:rnu:g:vC", longopts, 0);
+      opt = getopt_long (argc, argv, "df:i:z:hp:l:A:P:rnu:g:vC", longopts, 0);
     
       if (opt == EOF)
 	break;
@@ -355,6 +357,9 @@
         case 'i':
           pid_file = optarg;
           break;
+	case 'z':
+	  zclient_serv_path_set (optarg);
+	  break;
 	case 'p':
 	  tmp_port = atoi (optarg);
 	  if (tmp_port <= 0 || tmp_port > 0xffff)
diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c
index 719cb96..60efa19 100644
--- a/bgpd/bgp_nexthop.c
+++ b/bgpd/bgp_nexthop.c
@@ -1098,12 +1098,7 @@
   if (zlookup->sock != -1)
     return 0;
 
-#ifdef HAVE_TCP_ZEBRA
-  zlookup->sock = zclient_socket ();
-#else
-  zlookup->sock = zclient_socket_un (ZEBRA_SERV_PATH);
-#endif /* HAVE_TCP_ZEBRA */
-  if (zlookup->sock < 0)
+  if (zclient_socket_connect (zlookup) < 0)
     return -1;
 
   return 0;
diff --git a/isisd/isis_main.c b/isisd/isis_main.c
index 45e9408..15d85d6 100644
--- a/isisd/isis_main.c
+++ b/isisd/isis_main.c
@@ -34,6 +34,7 @@
 #include "privs.h"
 #include "sigevent.h"
 #include "filter.h"
+#include "zclient.h"
 
 #include "isisd/dict.h"
 #include "include-netbsd/iso.h"
@@ -75,6 +76,7 @@
   {"daemon",      no_argument,       NULL, 'd'},
   {"config_file", required_argument, NULL, 'f'},
   {"pid_file",    required_argument, NULL, 'i'},
+  {"socket",      required_argument, NULL, 'z'},
   {"vty_addr",    required_argument, NULL, 'A'},
   {"vty_port",    required_argument, NULL, 'P'},
   {"user",        required_argument, NULL, 'u'},
@@ -130,6 +132,7 @@
 -d, --daemon       Runs in daemon mode\n\
 -f, --config_file  Set configuration file name\n\
 -i, --pid_file     Set process identifier file name\n\
+-z, --socket       Set path of zebra socket\n\
 -A, --vty_addr     Set vty's bind address\n\
 -P, --vty_port     Set vty's port number\n\
 -u, --user         User to run as\n\
@@ -246,7 +249,7 @@
   /* Command line argument treatment. */
   while (1)
     {
-      opt = getopt_long (argc, argv, "df:i:hA:p:P:u:g:vC", longopts, 0);
+      opt = getopt_long (argc, argv, "df:i:z:hA:p:P:u:g:vC", longopts, 0);
 
       if (opt == EOF)
 	break;
@@ -264,6 +267,9 @@
 	case 'i':
 	  pid_file = optarg;
 	  break;
+	case 'z':
+	  zclient_serv_path_set (optarg);
+	  break;
 	case 'A':
 	  vty_addr = optarg;
 	  break;
diff --git a/lib/zclient.c b/lib/zclient.c
index 52a3627..3d5be91 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -41,6 +41,8 @@
 
 extern struct thread_master *master;
 
+char *zclient_serv_path = NULL;
+
 /* This file local debug flag. */
 int zclient_debug = 0;
 
@@ -143,8 +145,10 @@
   zclient_init (zclient, zclient->redist_default);
 }
 
+#ifdef HAVE_TCP_ZEBRA
+
 /* Make socket to zebra daemon. Return zebra socket. */
-int
+static int
 zclient_socket(void)
 {
   int sock;
@@ -175,10 +179,12 @@
   return sock;
 }
 
+#endif /* HAVE_TCP_ZEBRA */
+
 /* For sockaddr_un. */
 #include <sys/un.h>
 
-int
+static int
 zclient_socket_un (const char *path)
 {
   int ret;
@@ -208,6 +214,24 @@
   return sock;
 }
 
+/**
+ * Connect to zebra daemon.
+ * @param zclient a pointer to zclient structure
+ * @return socket fd just to make sure that connection established
+ * @see zclient_init
+ * @see zclient_new
+ */
+int
+zclient_socket_connect (struct zclient *zclient)
+{
+#ifdef HAVE_TCP_ZEBRA
+  zclient->sock = zclient_socket ();
+#else
+  zclient->sock = zclient_socket_un (zclient_serv_path ? zclient_serv_path : ZEBRA_SERV_PATH);
+#endif
+  return zclient->sock;
+}
+
 static int
 zclient_failed(struct zclient *zclient)
 {
@@ -313,13 +337,7 @@
   if (zclient->t_connect)
     return 0;
 
-  /* Make socket. */
-#ifdef HAVE_TCP_ZEBRA
-  zclient->sock = zclient_socket ();
-#else
-  zclient->sock = zclient_socket_un (ZEBRA_SERV_PATH);
-#endif /* HAVE_TCP_ZEBRA */
-  if (zclient->sock < 0)
+  if (zclient_socket_connect(zclient) < 0)
     {
       if (zclient_debug)
 	zlog_debug ("zclient connection fail");
@@ -1018,3 +1036,29 @@
       break;
     }
 }
+
+void
+zclient_serv_path_set (char *path)
+{
+  struct stat sb;
+
+  /* reset */
+  zclient_serv_path = NULL;
+
+  /* test if `path' is socket. don't set it otherwise. */
+  if (stat(path, &sb) == -1)
+    {
+      zlog_warn ("%s: zebra socket `%s' does not exist", __func__, path);
+      return;
+    }
+
+  if ((sb.st_mode & S_IFMT) != S_IFSOCK)
+    {
+      zlog_warn ("%s: `%s' is not unix socket, sir", __func__, path);
+      return;
+    }
+
+  /* it seems that path is unix socket */
+  zclient_serv_path = path;
+}
+
diff --git a/lib/zclient.h b/lib/zclient.h
index 21786ab..5c3db38 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -127,11 +127,8 @@
 extern void zclient_reset (struct zclient *);
 extern void zclient_free (struct zclient *);
 
-/* Get TCP socket connection to zebra daemon at loopback address. */
-extern int zclient_socket (void);
-
-/* Get unix stream socket connection to zebra daemon at given path. */
-extern int zclient_socket_un (const char *);
+extern int  zclient_socket_connect (struct zclient *);
+extern void zclient_serv_path_set  (char *path);
 
 /* Send redistribute command to zebra daemon. Do not update zclient state. */
 extern int zebra_redistribute_send (int command, struct zclient *, int type);
diff --git a/ospf6d/ospf6_main.c b/ospf6d/ospf6_main.c
index 6f7717c..c4b9124 100644
--- a/ospf6d/ospf6_main.c
+++ b/ospf6d/ospf6_main.c
@@ -77,6 +77,7 @@
   { "daemon",      no_argument,       NULL, 'd'},
   { "config_file", required_argument, NULL, 'f'},
   { "pid_file",    required_argument, NULL, 'i'},
+  { "socket",      required_argument, NULL, 'z'},
   { "vty_addr",    required_argument, NULL, 'A'},
   { "vty_port",    required_argument, NULL, 'P'},
   { "user",        required_argument, NULL, 'u'},
@@ -115,6 +116,7 @@
 -d, --daemon       Runs in daemon mode\n\
 -f, --config_file  Set configuration file name\n\
 -i, --pid_file     Set process identifier file name\n\
+-z, --socket       Set path of zebra socket\n\
 -A, --vty_addr     Set vty's bind address\n\
 -P, --vty_port     Set vty's port number\n\
 -u, --user         User to run as\n\
@@ -231,7 +233,7 @@
   /* Command line argument treatment. */
   while (1) 
     {
-      opt = getopt_long (argc, argv, "df:i:hp:A:P:u:g:vC", longopts, 0);
+      opt = getopt_long (argc, argv, "df:i:z:hp:A:P:u:g:vC", longopts, 0);
     
       if (opt == EOF)
         break;
@@ -252,6 +254,9 @@
         case 'i':
           pid_file = optarg;
           break;
+        case 'z':
+          zclient_serv_path_set (optarg);
+          break;
         case 'P':
          /* Deal with atoi() returning 0 on failure, and ospf6d not
              listening on ospf6d port... */
diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c
index 8b9a345..bad674b 100644
--- a/ospfd/ospf_main.c
+++ b/ospfd/ospf_main.c
@@ -38,6 +38,7 @@
 #include "memory.h"
 #include "privs.h"
 #include "sigevent.h"
+#include "zclient.h"
 
 #include "ospfd/ospfd.h"
 #include "ospfd/ospf_interface.h"
@@ -80,6 +81,7 @@
   { "daemon",      no_argument,       NULL, 'd'},
   { "config_file", required_argument, NULL, 'f'},
   { "pid_file",    required_argument, NULL, 'i'},
+  { "socket",      required_argument, NULL, 'z'},
   { "dryrun",      no_argument,       NULL, 'C'},
   { "help",        no_argument,       NULL, 'h'},
   { "vty_addr",    required_argument, NULL, 'A'},
@@ -116,6 +118,7 @@
 -d, --daemon       Runs in daemon mode\n\
 -f, --config_file  Set configuration file name\n\
 -i, --pid_file     Set process identifier file name\n\
+-z, --socket       Set path of zebra socket\n\
 -A, --vty_addr     Set vty's bind address\n\
 -P, --vty_port     Set vty's port number\n\
 -u, --user         User to run as\n\
@@ -191,30 +194,11 @@
   /* get program name */
   progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]);
 
-  /* Invoked by a priviledged user? -- endo. */
-  if (geteuid () != 0)
-    {
-      errno = EPERM;
-      perror (progname);
-      exit (1);
-    }
-
-  zlog_default = openzlog (progname, ZLOG_OSPF,
-			   LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
-
-  /* OSPF master init. */
-  ospf_master_init ();
-
-#ifdef SUPPORT_OSPF_API
-  /* OSPF apiserver is disabled by default. */
-  ospf_apiserver_enable = 0;
-#endif /* SUPPORT_OSPF_API */
-
   while (1) 
     {
       int opt;
 
-      opt = getopt_long (argc, argv, "df:i:hA:P:u:g:avC", longopts, 0);
+      opt = getopt_long (argc, argv, "df:i:z:hA:P:u:g:avC", longopts, 0);
     
       if (opt == EOF)
 	break;
@@ -235,6 +219,9 @@
         case 'i':
           pid_file = optarg;
           break;
+	case 'z':
+	  zclient_serv_path_set (optarg);
+	  break;
 	case 'P':
           /* Deal with atoi() returning 0 on failure, and ospfd not
              listening on ospfd port... */
@@ -274,6 +261,25 @@
 	}
     }
 
+  /* Invoked by a priviledged user? -- endo. */
+  if (geteuid () != 0)
+    {
+      errno = EPERM;
+      perror (progname);
+      exit (1);
+    }
+
+  zlog_default = openzlog (progname, ZLOG_OSPF,
+			   LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
+
+  /* OSPF master init. */
+  ospf_master_init ();
+
+#ifdef SUPPORT_OSPF_API
+  /* OSPF apiserver is disabled by default. */
+  ospf_apiserver_enable = 0;
+#endif /* SUPPORT_OSPF_API */
+
   /* Initializations. */
   master = om->master;
 
diff --git a/ripd/rip_main.c b/ripd/rip_main.c
index 57b5f3a..ccb5fa0 100644
--- a/ripd/rip_main.c
+++ b/ripd/rip_main.c
@@ -32,6 +32,7 @@
 #include "log.h"
 #include "privs.h"
 #include "sigevent.h"
+#include "zclient.h"
 
 #include "ripd/ripd.h"
 
@@ -41,6 +42,7 @@
   { "daemon",      no_argument,       NULL, 'd'},
   { "config_file", required_argument, NULL, 'f'},
   { "pid_file",    required_argument, NULL, 'i'},
+  { "socket",      required_argument, NULL, 'z'},
   { "help",        no_argument,       NULL, 'h'},
   { "dryrun",      no_argument,       NULL, 'C'},
   { "vty_addr",    required_argument, NULL, 'A'},
@@ -109,6 +111,7 @@
 -d, --daemon       Runs in daemon mode\n\
 -f, --config_file  Set configuration file name\n\
 -i, --pid_file     Set process identifier file name\n\
+-z, --socket       Set path of zebra socket\n\
 -A, --vty_addr     Set vty's bind address\n\
 -P, --vty_port     Set vty's port number\n\
 -C, --dryrun       Check configuration for validity and exit\n\
@@ -206,7 +209,7 @@
     {
       int opt;
 
-      opt = getopt_long (argc, argv, "df:i:hA:P:u:g:rvC", longopts, 0);
+      opt = getopt_long (argc, argv, "df:i:z:hA:P:u:g:rvC", longopts, 0);
     
       if (opt == EOF)
 	break;
@@ -227,6 +230,9 @@
         case 'i':
           pid_file = optarg;
           break;
+	case 'z':
+	  zclient_serv_path_set (optarg);
+	  break;
 	case 'P':
           /* Deal with atoi() returning 0 on failure, and ripd not
              listening on rip port... */
diff --git a/ripngd/ripng_main.c b/ripngd/ripng_main.c
index 85209a1..f4a6244 100644
--- a/ripngd/ripng_main.c
+++ b/ripngd/ripng_main.c
@@ -47,6 +47,7 @@
   { "daemon",      no_argument,       NULL, 'd'},
   { "config_file", required_argument, NULL, 'f'},
   { "pid_file",    required_argument, NULL, 'i'},
+  { "socket",      required_argument, NULL, 'z'},
   { "dryrun",      no_argument,       NULL, 'C'},
   { "help",        no_argument,       NULL, 'h'},
   { "vty_addr",    required_argument, NULL, 'A'},
@@ -112,6 +113,7 @@
 -d, --daemon       Runs in daemon mode\n\
 -f, --config_file  Set configuration file name\n\
 -i, --pid_file     Set process identifier file name\n\
+-z, --socket       Set path of zebra socket\n\
 -A, --vty_addr     Set vty's bind address\n\
 -P, --vty_port     Set vty's port number\n\
 -r, --retain       When program terminates, retain added route by ripngd.\n\
@@ -205,7 +207,7 @@
     {
       int opt;
 
-      opt = getopt_long (argc, argv, "df:i:hA:P:u:g:vC", longopts, 0);
+      opt = getopt_long (argc, argv, "df:i:z:hA:P:u:g:vC", longopts, 0);
     
       if (opt == EOF)
 	break;
@@ -225,7 +227,10 @@
 	  break;
         case 'i':
           pid_file = optarg;
-          break; 
+          break;
+	case 'z':
+	  zclient_serv_path_set (optarg);
+	  break;
 	case 'P':
           /* Deal with atoi() returning 0 on failure, and ripngd not
              listening on ripngd port... */
diff --git a/zebra/main.c b/zebra/main.c
index d829c04..5f26ce2 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -71,6 +71,7 @@
   { "keep_kernel", no_argument,       NULL, 'k'},
   { "config_file", required_argument, NULL, 'f'},
   { "pid_file",    required_argument, NULL, 'i'},
+  { "socket",      required_argument, NULL, 'z'},
   { "help",        no_argument,       NULL, 'h'},
   { "vty_addr",    required_argument, NULL, 'A'},
   { "vty_port",    required_argument, NULL, 'P'},
@@ -128,6 +129,7 @@
 	      "-d, --daemon       Runs in daemon mode\n"\
 	      "-f, --config_file  Set configuration file name\n"\
 	      "-i, --pid_file     Set process identifier file name\n"\
+	      "-z, --socket       Set path of zebra socket\n"\
 	      "-k, --keep_kernel  Don't delete old routes which installed by "\
 				  "zebra.\n"\
 	      "-C, --dryrun       Check configuration for validity and exit\n"\
@@ -214,6 +216,7 @@
   char *config_file = NULL;
   char *progname;
   struct thread thread;
+  char *zserv_path = NULL;
 
   /* Set umask before anything for security */
   umask (0027);
@@ -229,9 +232,9 @@
       int opt;
   
 #ifdef HAVE_NETLINK  
-      opt = getopt_long (argc, argv, "bdkf:i:hA:P:ru:g:vs:C", longopts, 0);
+      opt = getopt_long (argc, argv, "bdkf:i:z:hA:P:ru:g:vs:C", longopts, 0);
 #else
-      opt = getopt_long (argc, argv, "bdkf:i:hA:P:ru:g:vC", longopts, 0);
+      opt = getopt_long (argc, argv, "bdkf:i:z:hA:P:ru:g:vC", longopts, 0);
 #endif /* HAVE_NETLINK */
 
       if (opt == EOF)
@@ -261,6 +264,9 @@
         case 'i':
           pid_file = optarg;
           break;
+	case 'z':
+	  zserv_path = optarg;
+	  break;
 	case 'P':
 	  /* Deal with atoi() returning 0 on failure, and zebra not
 	     listening on zebra port... */
@@ -386,7 +392,7 @@
   pid = getpid ();
 
   /* This must be done only after locking pidfile (bug #403). */
-  zebra_zserv_socket_init ();
+  zebra_zserv_socket_init (zserv_path);
 
   /* Make vty server socket. */
   vty_serv_sock (vty_addr, vty_port, ZEBRA_VTYSH_PATH);
diff --git a/zebra/zserv.c b/zebra/zserv.c
index dc3d432..d558b2d 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -1733,11 +1733,11 @@
 
 /* Make zebra server socket, wiping any existing one (see bug #403). */
 void
-zebra_zserv_socket_init (void)
+zebra_zserv_socket_init (char *path)
 {
 #ifdef HAVE_TCP_ZEBRA
   zebra_serv ();
 #else
-  zebra_serv_un (ZEBRA_SERV_PATH);
+  zebra_serv_un (path ? path : ZEBRA_SERV_PATH);
 #endif /* HAVE_TCP_ZEBRA */
 }
diff --git a/zebra/zserv.h b/zebra/zserv.h
index a737183..5e8bcca 100644
--- a/zebra/zserv.h
+++ b/zebra/zserv.h
@@ -89,7 +89,7 @@
 /* Prototypes. */
 extern void zebra_init (void);
 extern void zebra_if_init (void);
-extern void zebra_zserv_socket_init (void);
+extern void zebra_zserv_socket_init (char *path);
 extern void hostinfo_get (void);
 extern void rib_init (void);
 extern void interface_list (void);