Add socket client interface into fcoeadmin. In fcoeadm.c/h, remove the code
of access sysfs files, create socket to connect to fcoemon, send request,
parse and print out the response;

Signed-off-by: Lucy Liu <[email protected]>

---

 fcoeadm.c |  346 ++++++++++++++++++++++++++++++++-----------------------------
 fcoeadm.h |   16 ++-
 2 files changed, 194 insertions(+), 168 deletions(-)

diff --git a/fcoeadm.c b/fcoeadm.c
index c766921..3da52eb 100644
--- a/fcoeadm.c
+++ b/fcoeadm.c
@@ -17,25 +17,18 @@
  * Maintained at www.Open-FCoE.org
  */
 
-#include <stdio.h>
-#include <stdlib.h>
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
 #include <libgen.h>
-#include <errno.h>
-#include <getopt.h>
-#include <dirent.h>
+#include <paths.h>
 #include "fcoeadm.h"
+#include "fcoe_clif.h"
 
 static char *fcoeadm_version =                                         \
-       "fcoeadm v1.0.7\n Copyright (c) 2009, Intel Corporation.\n";
+       "fcoeadm v1.0.8\n Copyright (c) 2009, Intel Corporation.\n";
 
-#define SYSFS_MOUNT    "/sys"
-#define SYSFS_NET      SYSFS_MOUNT "/class/net"
-#define SYSFS_FCHOST   SYSFS_MOUNT "/class/fc_host"
-#define SYSFS_FCOE     SYSFS_MOUNT "/module/fcoe/parameters"
-#define FCOE_CREATE    SYSFS_FCOE "/create"
-#define FCOE_DESTROY   SYSFS_FCOE "/destroy"
-
-#define FCHOSTBUFLEN           64
+#define CMD_RESPONSE_TIMEOUT 5
 
 static struct option fcoeadm_opts[] = {
        {"create", 1, 0, 'c'},
@@ -53,6 +46,8 @@ static struct option fcoeadm_opts[] = {
 struct opt_info _opt_info, *opt_info = &_opt_info;
 char progname[20];
 
+struct clif *clif_conn;
+
 static void fcoeadm_help(void)
 {
        printf("%s\n", fcoeadm_version);
@@ -69,183 +64,225 @@ static void fcoeadm_help(void)
 }
 
 /*
- * Open and close to check if directory exists
- */
-static int fcoeadm_checkdir(char *dir)
-{
-       DIR *d = NULL;
-
-       if (!dir)
-               return -EINVAL;
-       /* check if we have sysfs */
-       d = opendir(dir);
-       if (!d)
-               return -EINVAL;
-       closedir(d);
-       return 0;
-}
-
-/*
  * TODO - check this ifname before performing any action
  */
 static int fcoeadm_check(char *ifname)
 {
        char path[256];
+       int fd;
+       int status = 0;
 
        /* check if we have sysfs */
-       if (fcoeadm_checkdir(SYSFS_MOUNT)) {
+       if (fcoeclif_checkdir(SYSFS_MOUNT)) {
                fprintf(stderr,
                        "%s: Sysfs mount point %s not found!\n",
                        progname, SYSFS_MOUNT);
-               return -EINVAL;
-       }
-       /* check fcoe module */
-       if (fcoeadm_checkdir(SYSFS_FCOE)) {
-               fprintf(stderr,
-                       "%s: Please make sure FCoE driver module is loaded!\n",
-                       progname);
-               return -EINVAL;
+               status = -EINVAL;
        }
+
        /* check target interface */
        if (!ifname) {
                fprintf(stderr, "%s: Invalid interface name!\n", progname);
-               return -EINVAL;
+               status = -EINVAL;
        }
        sprintf(path, "%s/%s", SYSFS_NET, ifname);
-       if (fcoeadm_checkdir(path)) {
+       if (fcoeclif_checkdir(path)) {
                fprintf(stderr,
                        "%s: Interface %s not found!\n", progname, ifname);
-               return -EINVAL;
+               status = -EINVAL;
+       }
+
+       fd = open(CLIF_PID_FILE, O_RDWR, S_IRUSR | S_IWUSR);
+       if (fd < 0) {
+               fprintf(stderr,
+                       "%s: fcoemon was not running!\n", progname);
+               status = -EINVAL;
+       }
+
+       return status;
+}
+
+static int fcoeadm_clif_request(const struct clif_data *cmd, size_t cmd_len,
+                                       char *reply, size_t *reply_len)
+{
+       struct timeval tv;
+       int ret;
+       fd_set rfds;
+
+       if (send(clif_conn->s, cmd, cmd_len, 0) < 0)
+               return -1;
+
+       for (;;) {
+               tv.tv_sec = CMD_RESPONSE_TIMEOUT;
+               tv.tv_usec = 0;
+               FD_ZERO(&rfds);
+               FD_SET(clif_conn->s, &rfds);
+               ret = select(clif_conn->s + 1, &rfds, NULL, NULL, &tv);
+               if (FD_ISSET(clif_conn->s, &rfds)) {
+                       ret = recv(clif_conn->s, reply, *reply_len, 0);
+                       if (ret < 0) {
+                               fprintf(stderr, "less then zero\n");
+                               return ret;
+                       }
+                       *reply_len = ret;
+                       break;
+               } else {
+                       fprintf(stderr, "timeout\n");
+                       return -2;
+               }
        }
 
        return 0;
 }
 
-/*
- * TODO - for now, this just writes to path
- */
-static int fcoeadm_action(char *path, char *s)
+static int fcoeadm_request(int cmd, char *s)
 {
-       FILE *fp = NULL;
+       struct clif_data *data = NULL;
+       char rbuf[MAX_MSGBUF];
+       size_t len;
+       int ret;
 
-       if (!path)
+       if (clif_conn == NULL) {
+               printf("Not connected to fcoemon.\n");
                return -EINVAL;
+       }
 
-       if (!s)
+       data = (struct clif_data *)malloc(sizeof(struct clif_data));
+       if (data == NULL)
                return -EINVAL;
 
-       fp = fopen(path, "w");
-       if (!fp) {
-               fprintf(stderr,
-                       "%s: Failed to open %s\n", progname, path);
-               return -ENOENT;
+       memset(data, 0, sizeof(data));
+       data->cmd = cmd;
+       strcpy(data->ifname, s);
+
+       len = sizeof(rbuf)-1;
+
+       ret = fcoeadm_clif_request(data, sizeof(struct clif_data), rbuf, &len);
+       if (ret == -2) {
+               printf("%d command timed out.\n", cmd);
+               goto fail;
+       } else if (ret < 0) {
+               printf("%d command failed.\n", cmd);
+               goto fail;
        }
-       if (EOF == fputs(s, fp))
-               fprintf(stderr,
-                       "%s: Failed to write %s to %s\n", progname, s, path);
 
-       fclose(fp);
+       rbuf[len] = '\0';
+       ret = atoi(rbuf);
+       free(data);
+       return ret;
 
-       return 0;
+fail:
+       free(data);
+       return -EINVAL;
 }
 
-static char *fcoeadm_read(const char *path)
+static void fcoeadm_close_cli(void)
 {
-       FILE *fp;
-       char *buf;
-       int size = 512;
-
-       if (!path)
-               return NULL;
-
-       buf = malloc(size);
-       if (!buf)
-               return NULL;
-       memset(buf, 0, size);
-
-       fp = fopen(path, "r");
-       if (fp) {
-               if (fgets(buf, size, fp)) {
-                       fclose(fp);
-                       return buf;
-               }
-       }
-       fclose(fp);
-       free(buf);
-       return NULL;
+       if (clif_conn == NULL)
+               return;
+
+       unlink(clif_conn->local.sun_path);
+       close(clif_conn->s);
+       free(clif_conn);
+       clif_conn = NULL;
 }
 
-static int fcoeadm_check_fchost(const char *ifname, const char *dname)
+/*
+ * Create fcoeadm client interface
+ */
+static struct clif *fcoeadm_open_cli(const char *ifname)
 {
-       char *buf;
-       char path[512];
-
-       if (!ifname)
-               return -EINVAL;
-
-       if (!dname)
-               return -EINVAL;
+       char *fcmon_file = NULL;
+       int flen;
+       static int counter;
+
+       flen = strlen(FCM_SRV_DIR) + strlen(ifname) + 2;
+       fcmon_file = malloc(flen);
+       if (fcmon_file == NULL)
+               goto fail;
+       snprintf(fcmon_file, flen, "%s/%s", FCM_SRV_DIR, ifname);
+
+       clif_conn = malloc(sizeof(*clif_conn));
+       if (clif_conn == NULL)
+               goto fail;
+       memset(clif_conn, 0, sizeof(*clif_conn));
+
+       clif_conn->s = socket(PF_UNIX, SOCK_DGRAM, 0);
+       if (clif_conn->s < 0)
+               goto fail;
+
+       clif_conn->local.sun_family = AF_UNIX;
+       snprintf(clif_conn->local.sun_path, sizeof(clif_conn->local.sun_path),
+                   "/tmp/fcadm_clif_%d-%d", getpid(), counter++);
+       if (bind(clif_conn->s, (struct sockaddr *) &clif_conn->local,
+                   sizeof(clif_conn->local)) < 0) {
+               close(clif_conn->s);
+               goto fail;
+       }
 
-       if (dname[0] == '.')
-               return -EINVAL;
+       clif_conn->dest.sun_family = AF_UNIX;
+       snprintf(clif_conn->dest.sun_path, sizeof(clif_conn->dest.sun_path),
+                       "%s", fcmon_file);
+       if (connect(clif_conn->s, (struct sockaddr *) &clif_conn->dest,
+                   sizeof(clif_conn->dest)) < 0) {
+               close(clif_conn->s);
+               unlink(clif_conn->local.sun_path);
+               goto fail;
+       }
 
-       sprintf(path, "%s/%s/symbolic_name", SYSFS_FCHOST, dname);
-       buf = fcoeadm_read(path);
-       if (!buf)
-               return -EINVAL;
+       free(fcmon_file);
+       return clif_conn;
 
-       if (!strstr(buf, ifname)) {
-               free(buf);
-               return -EINVAL;
-       }
-       free(buf);
-       return 0;
+fail:
+       free(fcmon_file);
+       free(clif_conn);
+       return NULL;
 }
 
-static int fcoeadm_find_fchost(char *ifname, char *fchost, int len)
+/*
+ * Send request to fcoemon
+ */
+static int fcoeadm_action(int cmd, char *device_name)
 {
-       int n, dname_len;
-       int found = 0;
-       struct dirent **namelist;
-
-       if (!ifname)
-               return -EINVAL;
+       char *clif_ifname = NULL;
+       int ret = 0;
 
-       if ((!fchost) || (len <= 0))
+       if (!device_name)
                return -EINVAL;
 
-       memset(fchost, 0, len);
-       n = scandir(SYSFS_FCHOST, &namelist, 0, alphasort);
-       if (n > 0) {
-               while (n--) {
-                       /* check symbolic name */
-                       if (!fcoeadm_check_fchost(ifname,
-                                                 namelist[n]->d_name)) {
-                               dname_len = strnlen(namelist[n]->d_name, len);
-                               if (dname_len != len) {
-                                       /*
-                                        * This assumes that d_name is always
-                                        * NULL terminated.
-                                        */
-                                       strncpy(fchost, namelist[n]->d_name,
-                                               dname_len + 1);
-                                       found = 1;
-                               } else {
-                                       fprintf(stderr, "scsi_host (%s) is "
-                                               "too large for a buffer that "
-                                               "is only %d bytes large\n",
-                                               namelist[n]->d_name, dname_len);
-                                       free(namelist[n]);
+       for (;;) {
+               if (clif_ifname == NULL) {
+                       struct dirent *dent;
+                       DIR *dir = opendir(FCM_SRV_DIR);
+                       if (dir) {
+                               while ((dent = readdir(dir))) {
+                                       if (strcmp(dent->d_name, ".") == 0 ||
+                                               strcmp(dent->d_name, "..") == 0)
+                                               continue;
+                                       clif_ifname = strdup(dent->d_name);
+                                       break;
                                }
+                       closedir(dir);
                        }
-                       free(namelist[n]);
                }
-               free(namelist);
+
+               clif_conn = fcoeadm_open_cli(clif_ifname);
+               if (clif_conn) {
+                       break;
+               } else {
+                       fprintf(stderr, "Failed to connect to fcoemon.\n");
+                       free(clif_ifname);
+                       return -1;
+               }
        }
 
-       return found;
-}
+       ret = fcoeadm_request(cmd, device_name);
+
+       free(clif_ifname);
+       fcoeadm_close_cli();
 
+       return ret;
+}
 
 /*
  * Create FCoE instance for this ifname
@@ -258,7 +295,7 @@ static int fcoeadm_create(char *ifname)
                        progname, ifname);
                return -EINVAL;
        }
-       return fcoeadm_action(FCOE_CREATE, ifname);
+       return fcoeadm_action(FCOE_CREATE_CMD, ifname);
 }
 
 /*
@@ -272,21 +309,7 @@ static int fcoeadm_destroy(char *ifname)
                        progname, ifname);
                return -EINVAL;
        }
-       return fcoeadm_action(FCOE_DESTROY, ifname);
-}
-
-/*
- * Validate an existing instance for an FC interface
- */
-static int fcoeadm_validate_interface(char *ifname, char *fchost, int len)
-{
-       if (!fcoeadm_find_fchost(ifname, fchost, len)) {
-               fprintf(stderr, "%s: No fc_host found for %s\n",
-                       progname, ifname);
-               return -EINVAL;
-       }
-
-       return 0;
+       return fcoeadm_action(FCOE_DESTROY_CMD, ifname);
 }
 
 /*
@@ -294,14 +317,7 @@ static int fcoeadm_validate_interface(char *ifname, char 
*fchost, int len)
  */
 static int fcoeadm_reset(char *ifname)
 {
-       char fchost[FCHOSTBUFLEN];
-       char path[256];
-
-       if (fcoeadm_validate_interface(ifname, fchost, FCHOSTBUFLEN))
-               return -EINVAL;
-
-       sprintf(path, "%s/%s/issue_lip", SYSFS_FCHOST, fchost);
-       return fcoeadm_action(path, "1");
+       return fcoeadm_action(FCOE_RESET_CMD, ifname);
 }
 
 /*
@@ -474,7 +490,7 @@ int main(int argc, char *argv[])
                                        sizeof(opt_info->ifname));
                        }
                        if (strnlen(opt_info->ifname, IFNAMSIZ - 1)) {
-                               if (fcoeadm_validate_interface(
+                               if (fcoeclif_validate_interface(
                                            opt_info->ifname,
                                            fchost, FCHOSTBUFLEN))
                                        goto done;
@@ -504,7 +520,7 @@ int main(int argc, char *argv[])
                                        sizeof(opt_info->ifname));
                        }
                        if (strnlen(opt_info->ifname, IFNAMSIZ - 1)) {
-                               if (fcoeadm_validate_interface(
+                               if (fcoeclif_validate_interface(
                                            opt_info->ifname,
                                            fchost, FCHOSTBUFLEN))
                                        goto done;
@@ -535,7 +551,7 @@ int main(int argc, char *argv[])
                                strncpy(opt_info->ifname, optarg,
                                        sizeof(opt_info->ifname));
                        if (strnlen(opt_info->ifname, IFNAMSIZ - 1)) {
-                               if (fcoeadm_validate_interface(
+                               if (fcoeclif_validate_interface(
                                            opt_info->ifname,
                                            fchost, FCHOSTBUFLEN))
                                        goto done;
diff --git a/fcoeadm.h b/fcoeadm.h
index 3064423..fdda13a 100644
--- a/fcoeadm.h
+++ b/fcoeadm.h
@@ -42,15 +42,13 @@
 #include <getopt.h>
 #include <byteswap.h>
 #include <net/if.h>
+#include <sys/un.h>
 
 #include "hbaapi.h"
 #include "net_types.h"
 #include "fc_types.h"
 #include "fc_scsi.h"
 
-#define __USE_GNU
-#include <string.h>
-
 #define FCOE_MAX_LUN   255
 
 struct opt_info {
@@ -67,6 +65,18 @@ struct opt_info {
        #define DEFAULT_STATS_INTERVAL  1
        int n_interval;         /* seconds */
 };
+
+/**
+ * struct clif - Internal structure for client interface library
+ *
+ * This structure is used by fcoeadm client interface to store internal data.
+ */
+struct clif {
+       int s;
+       struct sockaddr_un local;
+       struct sockaddr_un dest;
+};
+
 extern struct opt_info *opt_info;
 extern char build_date[];
 

-- 
Signature: Lucy Liu <[email protected]>
_______________________________________________
devel mailing list
[email protected]
http://www.open-fcoe.org/mailman/listinfo/devel

Reply via email to