From 87d79a9f79015421d8bf7cd07f8486a2bae15ef2 Mon Sep 17 00:00:00 2001 From: Martin Winter Date: Thu, 26 Jan 2017 00:43:58 +0700 Subject: [PATCH] vtysh: Add vty_socket cli option to override the compiled-in location for the VTY daemon sockets Signed-off-by: Martin Winter --- vtysh/vtysh.c | 52 ++++++++++++++++++++++++++++++++++++---------- vtysh/vtysh.h | 2 ++ vtysh/vtysh_main.c | 9 ++++++++ 3 files changed, 52 insertions(+), 11 deletions(-) diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 6d6fe61306..17f6bfa5a5 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -2898,13 +2898,34 @@ vtysh_connect (struct vtysh_client *vclient) 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); } @@ -2913,7 +2934,7 @@ vtysh_connect (struct vtysh_client *vclient) if (! S_ISSOCK(s_stat.st_mode)) { fprintf (stderr, "vtysh_connect(%s): Not a socket\n", - vclient->path); + path); exit (1); } @@ -2923,7 +2944,7 @@ vtysh_connect (struct vtysh_client *vclient) 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; @@ -2931,7 +2952,7 @@ vtysh_connect (struct vtysh_client *vclient) 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 @@ -2942,7 +2963,7 @@ vtysh_connect (struct vtysh_client *vclient) 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); @@ -2993,14 +3014,23 @@ vtysh_update_all_insances(struct vtysh_client * head_client) { 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) @@ -3010,8 +3040,8 @@ vtysh_update_all_insances(struct vtysh_client * head_client) 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)); @@ -3019,7 +3049,7 @@ vtysh_update_all_insances(struct vtysh_client * head_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); diff --git a/vtysh/vtysh.h b/vtysh/vtysh.h index 46ed001919..537f944a7a 100644 --- a/vtysh/vtysh.h +++ b/vtysh/vtysh.h @@ -96,4 +96,6 @@ extern int execute_flag; extern struct vty *vty; +extern char * vty_sock_path; + #endif /* VTYSH_H */ diff --git a/vtysh/vtysh_main.c b/vtysh/vtysh_main.c index 6b33fca39b..956f97321f 100644 --- a/vtysh/vtysh_main.c +++ b/vtysh/vtysh_main.c @@ -53,6 +53,9 @@ 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; @@ -144,6 +147,7 @@ usage (int status) "-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" \ + " --vty_socket Override vty socket path\n" \ "-m, --markfile Mark input file with context end\n" "-w, --writeconfig Write integrated config (Quagga.conf) and exit\n" "-h, --help Display this help and exit\n\n" \ @@ -156,6 +160,7 @@ usage (int status) } /* VTY shell options, we use GNU getopt library. */ +#define OPTION_VTYSOCK 1000 struct option longopts[] = { { "boot", no_argument, NULL, 'b'}, @@ -163,6 +168,7 @@ struct option longopts[] = { "eval", required_argument, NULL, 'e'}, { "command", required_argument, NULL, 'c'}, { "daemon", required_argument, NULL, 'd'}, + { "vty_socket", required_argument, NULL, OPTION_VTYSOCK}, { "inputfile", required_argument, NULL, 'f'}, { "echo", no_argument, NULL, 'E'}, { "dryrun", no_argument, NULL, 'C'}, @@ -310,6 +316,9 @@ main (int argc, char **argv, char **env) tail = cr; } break; + case OPTION_VTYSOCK: + vty_sock_path = optarg; + break; case 'd': daemon_name = optarg; break;