#endif
/* bgpd options, we use GNU getopt library. */
+#define OPTION_VTYSOCK 1000
static const struct option longopts[] =
{
{ "daemon", no_argument, NULL, 'd'},
{ "listenon", required_argument, NULL, 'l'},
{ "vty_addr", required_argument, NULL, 'A'},
{ "vty_port", required_argument, NULL, 'P'},
+ { "vty_socket", required_argument, NULL, OPTION_VTYSOCK },
{ "retain", no_argument, NULL, 'r'},
{ "no_kernel", no_argument, NULL, 'n'},
{ "user", required_argument, NULL, 'u'},
/* Configuration file and directory. */
char config_default[] = SYSCONFDIR BGP_DEFAULT_CONFIG;
+/* VTY Socket prefix */
+char vty_sock_path[MAXPATHLEN] = BGP_VTYSH_PATH;
+
/* Route retain mode flag. */
static int retain_mode = 0;
/* VTY port number and address. */
int vty_port = BGP_VTY_PORT;
char *vty_addr = NULL;
+char *vty_sock_name;
/* privileges */
static zebra_capabilities_t _caps_p [] =
-l, --listenon Listen on specified address (implies -n)\n\
-A, --vty_addr Set vty's bind address\n\
-P, --vty_port Set vty's port number\n\
+ --vty_socket Override vty socket path\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 to run as\n\
vty_read_config (config_file, config_default);
/* Create VTY's socket */
- vty_serv_sock (vty_addr, vty_port, BGP_VTYSH_PATH);
+ vty_serv_sock (vty_addr, vty_port, vty_sock_path);
/* Try to return to normal operation. */
}
if (vty_port <= 0 || vty_port > 0xffff)
vty_port = BGP_VTY_PORT;
break;
+ case OPTION_VTYSOCK:
+ set_socket_path(vty_sock_path, BGP_VTYSH_PATH, optarg, sizeof (vty_sock_path));
+ break;
case 'r':
retain_mode = 1;
break;
pid_output (pid_file);
/* Make bgp vty socket. */
- vty_serv_sock (vty_addr, vty_port, BGP_VTYSH_PATH);
+ vty_serv_sock (vty_addr, vty_port, vty_sock_path);
/* Print banner. */
zlog_notice ("BGPd %s starting: vty@%d, bgp@%s:%d", FRR_COPYRIGHT,
};
/* isisd options */
+#define OPTION_VTYSOCK 1000
struct option longopts[] = {
{"daemon", no_argument, NULL, 'd'},
{"config_file", required_argument, NULL, 'f'},
{"socket", required_argument, NULL, 'z'},
{"vty_addr", required_argument, NULL, 'A'},
{"vty_port", required_argument, NULL, 'P'},
+ {"vty_socket", required_argument, NULL, OPTION_VTYSOCK},
{"user", required_argument, NULL, 'u'},
{"group", required_argument, NULL, 'g'},
{"version", no_argument, NULL, 'v'},
/* isisd program name. */
char *progname;
+/* VTY Socket prefix */
+char vty_sock_path[MAXPATHLEN] = ISIS_VTYSH_PATH;
+
int daemon_mode = 0;
/* Master of threads. */
-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\
+ --vty_socket Override vty socket path\n\
-u, --user User to run as\n\
-g, --group Group to run as\n\
-v, --version Print program version\n\
struct thread thread;
char *config_file = NULL;
char *vty_addr = NULL;
+ char *vty_sock_name;
int dryrun = 0;
/* Get the programname without the preceding path. */
vty_port = atoi (optarg);
vty_port = (vty_port ? vty_port : ISISD_VTY_PORT);
break;
+ case OPTION_VTYSOCK:
+ set_socket_path(vty_sock_path, ISIS_VTYSH_PATH, optarg, sizeof (vty_sock_path));
+ break;
case 'u':
isisd_privs.user = optarg;
break;
pid_output (pid_file);
/* Make isis vty socket. */
- vty_serv_sock (vty_addr, vty_port, ISIS_VTYSH_PATH);
+ vty_serv_sock (vty_addr, vty_port, vty_sock_path);
/* Print banner. */
zlog_notice ("Quagga-ISISd %s starting: vty@%d", FRR_VERSION, vty_port);
memset(&s_un, 0, sizeof(s_un));
s_un.sun_family = AF_UNIX;
- strlcpy(s_un.sun_path, LDPD_SOCKET, sizeof(s_un.sun_path));
+ strlcpy(s_un.sun_path, ctl_sock_path, sizeof(s_un.sun_path));
- if (unlink(LDPD_SOCKET) == -1)
+ if (unlink(ctl_sock_path) == -1)
if (errno != ENOENT) {
- log_warn("%s: unlink %s", __func__, LDPD_SOCKET);
+ log_warn("%s: unlink %s", __func__, ctl_sock_path);
close(fd);
return (-1);
}
old_umask = umask(S_IXUSR|S_IXGRP|S_IWOTH|S_IROTH|S_IXOTH);
if (bind(fd, (struct sockaddr *)&s_un, sizeof(s_un)) == -1) {
- log_warn("%s: bind: %s", __func__, LDPD_SOCKET);
+ log_warn("%s: bind: %s", __func__, ctl_sock_path);
close(fd);
umask(old_umask);
return (-1);
}
umask(old_umask);
- if (chmod(LDPD_SOCKET, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) == -1) {
+ if (chmod(ctl_sock_path, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) == -1) {
log_warn("%s: chmod", __func__);
close(fd);
- (void)unlink(LDPD_SOCKET);
+ (void)unlink(ctl_sock_path);
return (-1);
}
{
accept_del(control_fd);
close(control_fd);
- unlink(LDPD_SOCKET);
+ unlink(ctl_sock_path);
}
/* ARGSUSED */
memset(&s_un, 0, sizeof(s_un));
s_un.sun_family = AF_UNIX;
- strlcpy(s_un.sun_path, LDPD_SOCKET, sizeof(s_un.sun_path));
+ strlcpy(s_un.sun_path, ctl_sock_path, sizeof(s_un.sun_path));
if (connect(ctl_sock, (struct sockaddr *)&s_un, sizeof(s_un)) == -1) {
- log_warn("%s: connect: %s", __func__, LDPD_SOCKET);
+ log_warn("%s: connect: %s", __func__, ctl_sock_path);
close(ctl_sock);
return (-1);
}
static void ldpd_shutdown(void);
static pid_t start_child(enum ldpd_process, char *, int,
- const char *, const char *);
+ const char *, const char *, const char *);
static int main_dispatch_ldpe(struct thread *);
static int main_dispatch_lde(struct thread *);
static int main_imsg_send_ipc_sockets(struct imsgbuf *,
.cap_num_i = 0
};
+/* VTY Socket prefix */
+char vty_sock_path[MAXPATHLEN] = LDP_VTYSH_PATH;
+
+/* CTL Socket path */
+char ctl_sock_path[MAXPATHLEN] = LDPD_SOCKET;
+
/* LDPd options. */
+#define OPTION_VTYSOCK 1000
+#define OPTION_CTLSOCK 1001
static struct option longopts[] =
{
{ "daemon", no_argument, NULL, 'd'},
{ "help", no_argument, NULL, 'h'},
{ "vty_addr", required_argument, NULL, 'A'},
{ "vty_port", required_argument, NULL, 'P'},
+ { "vty_socket", required_argument, NULL, OPTION_VTYSOCK},
+ { "ctl_socket", required_argument, NULL, OPTION_CTLSOCK},
{ "user", required_argument, NULL, 'u'},
{ "group", required_argument, NULL, 'g'},
{ "version", no_argument, NULL, 'v'},
-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\
+ --vty_socket Override vty socket path\n\
+ --ctl_socket Override ctl socket path\n\
-u, --user User to run as\n\
-g, --group Group to run as\n\
-v, --version Print program version\n\
char *p;
char *vty_addr = NULL;
int vty_port = LDP_VTY_PORT;
+ char *vty_sock_name;
+ char *ctl_sock_custom_path = NULL;
+ char *ctl_sock_name;
int daemon_mode = 0;
const char *user = NULL;
const char *group = NULL;
if (vty_port <= 0 || vty_port > 0xffff)
vty_port = LDP_VTY_PORT;
break;
+ case OPTION_VTYSOCK:
+ set_socket_path(vty_sock_path, LDP_VTYSH_PATH, optarg, sizeof (vty_sock_path));
+ break;
+ case OPTION_CTLSOCK:
+ ctl_sock_name = strrchr(LDPD_SOCKET, '/');
+ if (ctl_sock_name)
+ /* skip '/' */
+ ctl_sock_name++;
+ else
+ /*
+ * LDPD_SOCKET configured as relative path
+ * during config? Should really never happen for
+ * sensible config
+ */
+ ctl_sock_name = (char *)LDPD_SOCKET;
+ ctl_sock_custom_path = optarg;
+ strlcpy(ctl_sock_path, ctl_sock_custom_path,
+ sizeof(ctl_sock_path));
+ strlcat(ctl_sock_path, "/", sizeof(ctl_sock_path));
+ strlcat(ctl_sock_path, ctl_sock_name,
+ sizeof(ctl_sock_path));
+ break;
case 'u':
user = optarg;
break;
if (lflag)
lde(user, group);
else if (eflag)
- ldpe(user, group);
+ ldpe(user, group, ctl_sock_path);
master = thread_master_create();
/* start children */
lde_pid = start_child(PROC_LDE_ENGINE, saved_argv0,
- pipe_parent2lde[1], user, group);
+ pipe_parent2lde[1], user, group, ctl_sock_custom_path);
ldpe_pid = start_child(PROC_LDP_ENGINE, saved_argv0,
- pipe_parent2ldpe[1], user, group);
+ pipe_parent2ldpe[1], user, group, ctl_sock_custom_path);
/* drop privileges */
if (user)
pid_output(pid_file);
/* Create VTY socket */
- vty_serv_sock(vty_addr, vty_port, LDP_VTYSH_PATH);
+ vty_serv_sock(vty_addr, vty_port, vty_sock_path);
/* Print banner. */
log_notice("LDPd %s starting: vty@%d", FRR_VERSION, vty_port);
static pid_t
start_child(enum ldpd_process p, char *argv0, int fd, const char *user,
- const char *group)
+ const char *group, const char *ctl_sock_custom_path)
{
- char *argv[7];
+ char *argv[9];
int argc = 0;
pid_t pid;
argv[argc++] = (char *)"-g";
argv[argc++] = (char *)group;
}
+ if (ctl_sock_custom_path) {
+ argv[argc++] = (char *)"--ctl_socket";
+ argv[argc++] = (char *)ctl_sock_custom_path;
+ }
argv[argc++] = NULL;
execvp(argv0, argv);
/* quagga */
extern struct thread_master *master;
+extern char ctl_sock_path[MAXPATHLEN];
/* ldp_zebra.c */
void ldp_zebra_init(struct thread_master *);
/* label distribution protocol engine */
void
-ldpe(const char *user, const char *group)
+ldpe(const char *user, const char *group, const char *ctl_path)
{
struct thread thread;
ldpe_privs.group = group;
zprivs_init(&ldpe_privs);
+ strlcpy(ctl_sock_path, ctl_path, sizeof(ctl_sock_path));
if (control_init() == -1)
fatalx("control socket setup failed");
uint16_t, struct map *);
/* ldpe.c */
-void ldpe(const char *, const char *);
+void ldpe(const char *, const char *, const char *);
int ldpe_imsg_compose_parent(int, pid_t, void *,
uint16_t);
int ldpe_imsg_compose_lde(int, uint32_t, pid_t, void *,
}
/* we have caps, we have no need to ever change back the original user */
- if (zprivs_state.zuid)
+ /* only change uid if we don't have the correct one */
+ if ((zprivs_state.zuid) && (zprivs_state.zsuid != zprivs_state.zuid))
{
if ( setreuid (zprivs_state.zuid, zprivs_state.zuid) )
{
/* we have caps, we have no need to ever change back the original user
* change real, effective and saved to the specified user.
*/
- if (zprivs_state.zuid)
+ /* only change uid if we don't have the correct one */
+ if ((zprivs_state.zuid) && (zprivs_state.zsuid != zprivs_state.zuid))
{
if ( setreuid (zprivs_state.zuid, zprivs_state.zuid) )
{
int
zprivs_change_uid (zebra_privs_ops_t op)
{
-
+ if (zprivs_state.zsuid == zprivs_state.zuid)
+ return 0;
if (op == ZPRIVS_RAISE)
return seteuid (zprivs_state.zsuid);
else if (op == ZPRIVS_LOWER)
}
}
- if (ngroups)
+ /* add groups only if we changed uid - otherwise skip */
+ if ((ngroups) && (zprivs_state.zsuid != zprivs_state.zuid))
{
if ( setgroups (ngroups, groups) )
{
}
}
- if (zprivs_state.zgid)
+ /* change gid only if we changed uid - otherwise skip */
+ if ((zprivs_state.zgid) && (zprivs_state.zsuid != zprivs_state.zuid))
{
/* change group now, forever. uid we do later */
if ( setregid (zprivs_state.zgid, zprivs_state.zgid) )
* This is not worth that much security wise, but all we can do.
*/
zprivs_state.zsuid = geteuid();
- if ( zprivs_state.zuid )
+ /* only change uid if we don't have the correct one */
+ if (( zprivs_state.zuid ) && (zprivs_state.zsuid != zprivs_state.zuid))
{
if ( setreuid (-1, zprivs_state.zuid) )
{
#ifdef HAVE_CAPABILITIES
zprivs_caps_terminate();
#else /* !HAVE_CAPABILITIES */
- if (zprivs_state.zuid)
+ /* only change uid if we don't have the correct one */
+ if ((zprivs_state.zuid) && (zprivs_state.zsuid != zprivs_state.zuid))
{
if ( setreuid (zprivs_state.zuid, zprivs_state.zuid) )
{
#include "sockopt.h"
#include "sockunion.h"
+/* Replace the path of given defaultpath with newpath, but keep filename */
+void
+set_socket_path (char *path, char *defaultpath, char *newpath, int maxsize)
+{
+ char *sock_name;
+
+ sock_name = strrchr(defaultpath, '/');
+ if (sock_name)
+ /* skip '/' */
+ sock_name++;
+ else
+ /*
+ * VTYSH_PATH configured as relative path
+ * during config? Should really never happen for
+ * sensible config
+ */
+ sock_name = defaultpath;
+
+ strlcpy (path, newpath, maxsize);
+ strlcat (path, "/", maxsize);
+ strlcat (path, sock_name, maxsize);
+}
+
void
setsockopt_so_recvbuf (int sock, int size)
{
#include "sockunion.h"
+/* Override (vty) socket paths, but keep the filename */
+extern void set_socket_path (char *path, char *defaultpath, char *newpath, int maxsize);
+
extern void setsockopt_so_recvbuf (int sock, int size);
extern void setsockopt_so_sendbuf (const int sock, int size);
extern int getsockopt_so_sendbuf (const int sock);
umask (old_mask);
zprivs_get_ids(&ids);
-
- if (ids.gid_vty > 0)
+
+ /* Hack: ids.gid_vty is actually a uint, but we stored -1 in it
+ earlier for the case when we don't need to chown the file
+ type casting it here to make a compare */
+ if ((int)ids.gid_vty > 0)
{
/* set group of socket */
if ( chown (path, -1, ids.gid_vty) )
/* Default configuration file name for ospf6d. */
#define OSPF6_DEFAULT_CONFIG "ospf6d.conf"
+/* VTY Socket prefix */
+char vty_sock_path[MAXPATHLEN] = OSPF6_VTYSH_PATH;
+
/* Default port values. */
#define OSPF6_VTY_PORT 2606
};
/* ospf6d options, we use GNU getopt library. */
+#define OPTION_VTYSOCK 1000
struct option longopts[] =
{
{ "daemon", no_argument, NULL, 'd'},
{ "socket", required_argument, NULL, 'z'},
{ "vty_addr", required_argument, NULL, 'A'},
{ "vty_port", required_argument, NULL, 'P'},
+ { "vty_socket", required_argument, NULL, OPTION_VTYSOCK},
{ "user", required_argument, NULL, 'u'},
{ "group", required_argument, NULL, 'g'},
{ "version", no_argument, NULL, 'v'},
-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\
+ --vty_socket Override vty socket path\n\
-u, --user User to run as\n\
-g, --group Group to run as\n\
-v, --version Print program version\n\
int opt;
char *vty_addr = NULL;
int vty_port = 0;
+ char *vty_sock_name;
char *config_file = NULL;
struct thread thread;
int dryrun = 0;
if (vty_port <= 0 || vty_port > 0xffff)
vty_port = OSPF6_VTY_PORT;
break;
+ case OPTION_VTYSOCK:
+ set_socket_path(vty_sock_path, OSPF6_VTYSH_PATH, optarg, sizeof (vty_sock_path));
+ break;
case 'u':
ospf6d_privs.user = optarg;
break;
/* Make ospf6 vty socket. */
if (!vty_port)
vty_port = OSPF6_VTY_PORT;
- vty_serv_sock (vty_addr, vty_port, OSPF6_VTYSH_PATH);
+ vty_serv_sock (vty_addr, vty_port, vty_sock_path);
/* Print start message */
zlog_notice ("OSPF6d (Quagga-%s ospf6d-%s) starts: vty@%d",
char config_default[100];
/* OSPFd options. */
+#define OPTION_VTYSOCK 1000
struct option longopts[] =
{
{ "daemon", no_argument, NULL, 'd'},
{ "help", no_argument, NULL, 'h'},
{ "vty_addr", required_argument, NULL, 'A'},
{ "vty_port", required_argument, NULL, 'P'},
+ { "vty_socket", required_argument, NULL, OPTION_VTYSOCK},
{ "user", required_argument, NULL, 'u'},
{ "group", required_argument, NULL, 'g'},
{ "apiserver", no_argument, NULL, 'a'},
/* OSPFd program name */
+/* VTY Socket prefix */
+char vty_sock_path[MAXPATHLEN] = OSPF_VTYSH_PATH;
+
/* Master of threads. */
struct thread_master *master;
-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\
+ --vty_socket Override vty socket path\n\
-u, --user User to run as\n\
-g, --group Group to run as\n\
-a. --apiserver Enable OSPF apiserver\n\
char *vty_addr = NULL;
int vty_port = OSPF_VTY_PORT;
char vty_path[100];
+ char *vty_sock_name;
int daemon_mode = 0;
char *config_file = NULL;
char *progname;
if (vty_port <= 0 || vty_port > 0xffff)
vty_port = OSPF_VTY_PORT;
break;
+ case OPTION_VTYSOCK:
+ set_socket_path(vty_sock_path, OSPF_VTYSH_PATH, optarg, sizeof (vty_sock_path));
+ break;
case 'u':
ospfd_privs.user = optarg;
break;
exit (1);
}
+ /* Create PID file */
+ if (instance)
+ {
+ char pidfile_temp[100];
+
+ /* Override the single file with file including instance
+ number in case of multi-instance */
+ if (strrchr(pid_file, '/') != NULL)
+ /* cut of pid_file at last / char * to get directory */
+ *strrchr(pid_file, '/') = '\0';
+ else
+ /* pid_file contains no directory - should never happen, but deal with it anyway */
+ /* throw-away all pid_file and assume it's only the filename */
+ pid_file[0] = '\0';
+
+ snprintf(pidfile_temp, sizeof(pidfile_temp), "%s/ospfd-%d.pid", pid_file, instance );
+ strncpy(pid_file, pidfile_temp, sizeof(pid_file));
+ }
+ /* Process id file create. */
+ pid_output (pid_file);
+
/* Create VTY socket */
if (instance)
{
- sprintf(pid_file, "%s/ospfd-%d.pid", DAEMON_VTY_DIR, instance);
- sprintf(vty_path, "%s/ospfd-%d.vty", DAEMON_VTY_DIR, instance);
+ /* Multi-Instance. Use only path section of vty_sock_path with new file incl instance */
+ if (strrchr(vty_sock_path, '/') != NULL)
+ {
+ /* cut of pid_file at last / char * to get directory */
+ *strrchr(vty_sock_path, '/') = '\0';
+ }
+ else
+ {
+ /* pid_file contains no directory - should never happen, but deal with it anyway */
+ /* throw-away all pid_file and assume it's only the filename */
+ vty_sock_path[0] = '\0';
+ }
+ snprintf(vty_path, sizeof(vty_path), "%s/ospfd-%d.vty", vty_sock_path, instance );
}
else
{
- strcpy(vty_path, OSPF_VTYSH_PATH);
+ strcpy(vty_path, vty_sock_path);
}
- /* Process id file create. */
- pid_output (pid_file);
-
vty_serv_sock (vty_addr, vty_port, vty_path);
/* Print banner. */
char config_default[] = SYSCONFDIR PIMD_DEFAULT_CONFIG;
+/* pimd options */
+#define OPTION_VTYSOCK 1000
struct option longopts[] = {
{ "daemon", no_argument, NULL, 'd'},
{ "config_file", required_argument, NULL, 'f'},
{ "pid_file", required_argument, NULL, 'i'},
+ { "socket", required_argument, NULL, 'z'},
{ "vty_addr", required_argument, NULL, 'A'},
{ "vty_port", required_argument, NULL, 'P'},
+ { "vty_socket", required_argument, NULL, OPTION_VTYSOCK},
{ "version", no_argument, NULL, 'v'},
{ "debug_zclient", no_argument, NULL, 'Z'},
{ "help", no_argument, NULL, 'h'},
{ 0 }
};
+/* VTY Socket prefix */
+char vty_sock_path[MAXPATHLEN] = PIM_VTYSH_PATH;
+
/* pimd privileges */
zebra_capabilities_t _caps_p [] =
{
-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\
+ --vty_socket Override vty socket path\n\
-v, --version Print program version\n\
"
int main(int argc, char** argv, char** envp) {
char *p;
char *vty_addr = NULL;
+ char *vty_sock_name;
int vty_port = -1;
int daemon_mode = 0;
char *config_file = NULL;
case 'P':
vty_port = atoi (optarg);
break;
+ case OPTION_VTYSOCK:
+ set_socket_path(vty_sock_path, PIM_VTYSH_PATH, optarg, sizeof (vty_sock_path));
+ break;
case 'v':
printf(PIMD_PROGNAME " version %s\n", PIMD_VERSION);
print_version(progname);
/* Create pimd VTY socket */
if (vty_port < 0)
vty_port = PIMD_VTY_PORT;
- vty_serv_sock(vty_addr, vty_port, PIM_VTYSH_PATH);
+ vty_serv_sock(vty_addr, vty_port, vty_sock_path);
zlog_notice("Quagga %s " PIMD_PROGNAME " %s starting, VTY interface at port TCP %d",
FRR_VERSION, PIMD_VERSION, vty_port);
#include "ripd/ripd.h"
/* ripd options. */
+#define OPTION_VTYSOCK 1000
static struct option longopts[] =
{
{ "daemon", no_argument, NULL, 'd'},
{ "dryrun", no_argument, NULL, 'C'},
{ "vty_addr", required_argument, NULL, 'A'},
{ "vty_port", required_argument, NULL, 'P'},
+ { "vty_socket", required_argument, NULL, OPTION_VTYSOCK},
{ "retain", no_argument, NULL, 'r'},
{ "user", required_argument, NULL, 'u'},
{ "group", required_argument, NULL, 'g'},
/* ripd program name */
+/* VTY Socket prefix */
+char vty_sock_path[MAXPATHLEN] = RIP_VTYSH_PATH;
+
/* Route retain mode flag. */
int retain_mode = 0;
-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\
+ --vty_socket Override vty socket path\n\
-C, --dryrun Check configuration for validity and exit\n\
-r, --retain When program terminates, retain added route by ripd.\n\
-u, --user User to run as\n\
vty_read_config (config_file, config_default);
/* Create VTY's socket */
- vty_serv_sock (vty_addr, vty_port, RIP_VTYSH_PATH);
+ vty_serv_sock (vty_addr, vty_port, vty_sock_path);
/* Try to return to normal operation. */
}
int dryrun = 0;
char *progname;
struct thread thread;
+ char *vty_sock_name;
/* Set umask before anything for security */
umask (0027);
if (vty_port <= 0 || vty_port > 0xffff)
vty_port = RIP_VTY_PORT;
break;
+ case OPTION_VTYSOCK:
+ set_socket_path(vty_sock_path, RIP_VTYSH_PATH, optarg, sizeof (vty_sock_path));
+ break;
case 'r':
retain_mode = 1;
break;
pid_output (pid_file);
/* Create VTY's socket */
- vty_serv_sock (vty_addr, vty_port, RIP_VTYSH_PATH);
+ vty_serv_sock (vty_addr, vty_port, vty_sock_path);
/* Print banner. */
zlog_notice ("RIPd %s starting: vty@%d", FRR_VERSION, vty_port);
char *config_file = NULL;
/* RIPngd options. */
+#define OPTION_VTYSOCK 1000
struct option longopts[] =
{
{ "daemon", no_argument, NULL, 'd'},
{ "help", no_argument, NULL, 'h'},
{ "vty_addr", required_argument, NULL, 'A'},
{ "vty_port", required_argument, NULL, 'P'},
+ { "vty_socket", required_argument, NULL, OPTION_VTYSOCK},
{ "retain", no_argument, NULL, 'r'},
{ "user", required_argument, NULL, 'u'},
{ "group", required_argument, NULL, 'g'},
/* RIPngd program name */
+/* VTY Socket prefix */
+char vty_sock_path[MAXPATHLEN] = RIPNG_VTYSH_PATH;
+
/* Route retain mode flag. */
int retain_mode = 0;
-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\
+ --vty_socket Override vty socket path\n\
-r, --retain When program terminates, retain added route by ripngd.\n\
-u, --user User to run as\n\
-g, --group Group to run as\n\
/* Reload config file. */
vty_read_config (config_file, config_default);
/* Create VTY's socket */
- vty_serv_sock (vty_addr, vty_port, RIPNG_VTYSH_PATH);
+ vty_serv_sock (vty_addr, vty_port, vty_sock_path);
/* Try to return to normal operation. */
}
char *progname;
struct thread thread;
int dryrun = 0;
+ char *vty_sock_name;
/* Set umask before anything for security */
umask (0027);
if (vty_port <= 0 || vty_port > 0xffff)
vty_port = RIPNG_VTY_PORT;
break;
+ case OPTION_VTYSOCK:
+ set_socket_path(vty_sock_path, RIPNG_VTYSH_PATH, optarg, sizeof (vty_sock_path));
+ break;
case 'r':
retain_mode = 1;
break;
}
/* Create VTY socket */
- vty_serv_sock (vty_addr, vty_port, RIPNG_VTYSH_PATH);
+ vty_serv_sock (vty_addr, vty_port, vty_sock_path);
/* Process id file create. */
pid_output (pid_file);
int sock, len;
struct sockaddr_un addr;
struct stat s_stat;
+ char path[MAXPATHLEN];
+
+ if (vty_sock_path == NULL)
+ strlcpy (path, vclient->path, sizeof (path));
+ else {
+ /* Different path for VTY Socket specified
+ overriding the default path, but keep the filename */
+ strlcpy (path, vty_sock_path, sizeof (path));
+
+ if (strrchr (vclient->path, '/') != NULL)
+ strlcat (path, strrchr (vclient->path, '/'), sizeof (path));
+ else {
+ /*
+ * vclient->path configured as relative path during config? Should
+ * really never happen for sensible config
+ */
+ strlcat (path, "/", sizeof (path));
+ strlcat (path, vclient->path, sizeof (path));
+ }
+ }
+ path[sizeof(path)-1] = '\0';
/* Stat socket to see if we have permission to access it. */
- ret = stat (vclient->path, &s_stat);
+ ret = stat (path, &s_stat);
if (ret < 0 && errno != ENOENT)
{
fprintf (stderr, "vtysh_connect(%s): stat = %s\n",
- vclient->path, safe_strerror(errno));
+ path, safe_strerror(errno));
exit(1);
}
if (! S_ISSOCK(s_stat.st_mode))
{
fprintf (stderr, "vtysh_connect(%s): Not a socket\n",
- vclient->path);
+ path);
exit (1);
}
if (sock < 0)
{
#ifdef DEBUG
- fprintf(stderr, "vtysh_connect(%s): socket = %s\n", vclient->path,
+ fprintf(stderr, "vtysh_connect(%s): socket = %s\n", path,
safe_strerror(errno));
#endif /* DEBUG */
return -1;
memset (&addr, 0, sizeof (struct sockaddr_un));
addr.sun_family = AF_UNIX;
- strncpy (addr.sun_path, vclient->path, strlen (vclient->path));
+ strncpy (addr.sun_path, path, strlen (path));
#ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
len = addr.sun_len = SUN_LEN(&addr);
#else
if (ret < 0)
{
#ifdef DEBUG
- fprintf(stderr, "vtysh_connect(%s): connect = %s\n", vclient->path,
+ fprintf(stderr, "vtysh_connect(%s): connect = %s\n", path,
safe_strerror(errno));
#endif /* DEBUG */
close (sock);
{
struct vtysh_client *client;
char *ptr;
+ char vty_dir[MAXPATHLEN];
DIR *dir;
struct dirent *file;
int n = 0;
if (head_client->flag != VTYSH_OSPFD) return;
- /* ls DAEMON_VTY_DIR and look for all files ending in .vty */
- dir = opendir(DAEMON_VTY_DIR "/");
+ if (vty_sock_path == NULL)
+ /* ls DAEMON_VTY_DIR and look for all files ending in .vty */
+ strlcpy(vty_dir, DAEMON_VTY_DIR "/", MAXPATHLEN);
+ else
+ {
+ /* ls vty_sock_dir and look for all files ending in .vty */
+ strlcpy(vty_dir, vty_sock_path, MAXPATHLEN);
+ strlcat(vty_dir, "/", MAXPATHLEN);
+ }
+ dir = opendir(vty_dir);
if (dir)
{
while ((file = readdir(dir)) != NULL)
if (n == MAXIMUM_INSTANCES)
{
fprintf(stderr,
- "Parsing %s/, client limit(%d) reached!\n",
- DAEMON_VTY_DIR, n);
+ "Parsing %s, client limit(%d) reached!\n",
+ vty_dir, n);
break;
}
client = (struct vtysh_client *) malloc(sizeof(struct vtysh_client));
client->name = "ospfd";
client->flag = VTYSH_OSPFD;
ptr = (char *) malloc(100);
- sprintf(ptr, "%s/%s", DAEMON_VTY_DIR, file->d_name);
+ sprintf(ptr, "%s%s", vty_dir, file->d_name);
client->path = (const char *)ptr;
client->next = NULL;
vtysh_client_sorted_insert(head_client, client);
extern struct vty *vty;
+extern char * vty_sock_path;
+
#endif /* VTYSH_H */
char *progname;
/* Configuration file name and directory. */
-static char vtysh_config_always[] = SYSCONFDIR VTYSH_DEFAULT_CONFIG;
-static char quagga_config_default[] = SYSCONFDIR QUAGGA_DEFAULT_CONFIG;
+static char vtysh_config_always[MAXPATHLEN] = SYSCONFDIR VTYSH_DEFAULT_CONFIG;
+static char quagga_config_default[MAXPATHLEN] = SYSCONFDIR QUAGGA_DEFAULT_CONFIG;
char *quagga_config = quagga_config_default;
char history_file[MAXPATHLEN];
/* Flag for indicate executing child command. */
int execute_flag = 0;
+/* VTY Socket prefix */
+char * vty_sock_path = NULL;
+
/* For sigsetjmp() & siglongjmp(). */
static sigjmp_buf jmpbuf;
"-f, --inputfile Execute commands from specific file and exit\n" \
"-E, --echo Echo prompt and command in -c mode\n" \
"-C, --dryrun Check configuration for validity and exit\n" \
- "-m, --markfile Mark input file with context end\n"
- "-w, --writeconfig Write integrated config (Quagga.conf) and exit\n"
+ " --vty_socket Override vty socket path\n" \
+ "-m, --markfile Mark input file with context end\n" \
+ " --vty_socket Override vty socket path\n" \
+ " --config_dir Override config directory path\n" \
+ "-w, --writeconfig Write integrated config (Quagga.conf) and exit\n" \
"-h, --help Display this help and exit\n\n" \
"Note that multiple commands may be executed from the command\n" \
"line by passing multiple -c args, or by embedding linefeed\n" \
}
/* VTY shell options, we use GNU getopt library. */
+#define OPTION_VTYSOCK 1000
+#define OPTION_CONFDIR 1001
struct option longopts[] =
{
{ "boot", no_argument, NULL, 'b'},
{ "eval", required_argument, NULL, 'e'},
{ "command", required_argument, NULL, 'c'},
{ "daemon", required_argument, NULL, 'd'},
+ { "vty_socket", required_argument, NULL, OPTION_VTYSOCK},
+ { "config_dir", required_argument, NULL, OPTION_CONFDIR},
{ "inputfile", required_argument, NULL, 'f'},
{ "echo", no_argument, NULL, 'E'},
{ "dryrun", no_argument, NULL, 'C'},
int boot_flag = 0;
const char *daemon_name = NULL;
const char *inputfile = NULL;
+ char *vtysh_configfile_name;
struct cmd_rec {
const char *line;
struct cmd_rec *next;
int ret = 0;
char *homedir = NULL;
+ /* check for restricted functionality if vtysh is run setuid */
+ int restricted = (getuid() != geteuid()) || (getgid() != getegid());
+
/* Preserve name of myself. */
progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]);
tail = cr;
}
break;
+ case OPTION_VTYSOCK:
+ vty_sock_path = optarg;
+ break;
+ case OPTION_CONFDIR:
+ /*
+ * Skip option for Config Directory if setuid
+ */
+ if (restricted)
+ {
+ fprintf (stderr, "Overriding of Config Directory blocked for vtysh with setuid");
+ return 1;
+ }
+ /*
+ * Overwrite location for vtysh.conf
+ */
+ vtysh_configfile_name = strrchr(VTYSH_DEFAULT_CONFIG, '/');
+ if (vtysh_configfile_name)
+ /* skip '/' */
+ vtysh_configfile_name++;
+ else
+ /*
+ * VTYSH_DEFAULT_CONFIG configured with relative path
+ * during config? Should really never happen for
+ * sensible config
+ */
+ vtysh_configfile_name = (char *) VTYSH_DEFAULT_CONFIG;
+ strlcpy(vtysh_config_always, optarg, sizeof(vtysh_config_always));
+ strlcat(vtysh_config_always, "/", sizeof(vtysh_config_always));
+ strlcat(vtysh_config_always, vtysh_configfile_name,
+ sizeof(vtysh_config_always));
+ /*
+ * Overwrite location for Quagga.conf
+ */
+ vtysh_configfile_name = strrchr(QUAGGA_DEFAULT_CONFIG, '/');
+ if (vtysh_configfile_name)
+ /* skip '/' */
+ vtysh_configfile_name++;
+ else
+ /*
+ * QUAGGA_DEFAULT_CONFIG configured with relative path
+ * during config? Should really never happen for
+ * sensible config
+ */
+ vtysh_configfile_name = (char *) QUAGGA_DEFAULT_CONFIG;
+ strlcpy(quagga_config_default, optarg, sizeof(vtysh_config_always));
+ strlcat(quagga_config_default, "/", sizeof(vtysh_config_always));
+ strlcat(quagga_config_default, vtysh_configfile_name,
+ sizeof(quagga_config_default));
+ break;
case 'd':
daemon_name = optarg;
break;
vtysh_get_home (void)
{
struct passwd *passwd;
+ char * homedir;
+ if ((homedir = getenv("HOME")) != 0)
+ return homedir;
+
+ /* Fallback if HOME is undefined */
passwd = getpwuid (getuid ());
return passwd ? passwd->pw_dir : NULL;
/* process id. */
pid_t pid;
+/* VTY Socket prefix */
+char vty_sock_path[MAXPATHLEN] = ZEBRA_VTYSH_PATH;
+
/* Pacify zclient.o in libzebra, which expects this variable. */
struct thread_master *master;
#endif /* HAVE_NETLINK */
/* Command line options. */
+#define OPTION_VTYSOCK 1000
struct option longopts[] =
{
{ "batch", no_argument, NULL, 'b'},
{ "help", no_argument, NULL, 'h'},
{ "vty_addr", required_argument, NULL, 'A'},
{ "vty_port", required_argument, NULL, 'P'},
+ { "vty_socket", required_argument, NULL, OPTION_VTYSOCK },
{ "retain", no_argument, NULL, 'r'},
{ "dryrun", no_argument, NULL, 'C'},
#ifdef HAVE_NETLINK
"-C, --dryrun Check configuration for validity and exit\n"\
"-A, --vty_addr Set vty's bind address\n"\
"-P, --vty_port Set vty's port number\n"\
+ " --vty_socket Override vty socket path\n"\
"-r, --retain When program terminates, retain added route "\
"by zebra.\n"\
"-u, --user User to run as\n"\
char *p;
char *vty_addr = NULL;
int vty_port = ZEBRA_VTY_PORT;
+ char *vty_sock_name;
int dryrun = 0;
int batch_mode = 0;
int daemon_mode = 0;
if (vty_port <= 0 || vty_port > 0xffff)
vty_port = ZEBRA_VTY_PORT;
break;
+ case OPTION_VTYSOCK:
+ set_socket_path(vty_sock_path, ZEBRA_VTYSH_PATH, optarg, sizeof (vty_sock_path));
+ break;
case 'r':
retain_mode = 1;
break;
zebra_zserv_socket_init (zserv_path);
/* Make vty server socket. */
- vty_serv_sock (vty_addr, vty_port, ZEBRA_VTYSH_PATH);
+ vty_serv_sock (vty_addr, vty_port, vty_sock_path);
/* Print banner. */
zlog_notice ("Zebra %s starting: vty@%d", FRR_VERSION, vty_port);