Whamcloud - gitweb
LU-6245 libcfs: move cfs_ip_addr_* function from kernel libcfs to LNet
[fs/lustre-release.git] / libcfs / libcfs / util / nidstrings.c
index 3a9087f..b150a0d 100644 (file)
@@ -87,39 +87,237 @@ libcfs_next_nidstring(void)
        return str;
 }
 
-static int  libcfs_lo_str2addr(const char *str, int nob, __u32 *addr);
-static void libcfs_ip_addr2str(__u32 addr, char *str, size_t size);
-static int  libcfs_ip_str2addr(const char *str, int nob, __u32 *addr);
+static int
+libcfs_lo_str2addr(const char *str, int nob, __u32 *addr)
+{
+       *addr = 0;
+       return 1;
+}
+
+static void
+libcfs_ip_addr2str(__u32 addr, char *str, size_t size)
+{
+       snprintf(str, size, "%u.%u.%u.%u",
+                (addr >> 24) & 0xff, (addr >> 16) & 0xff,
+                (addr >> 8) & 0xff, addr & 0xff);
+}
+
+/* CAVEAT EMPTOR XscanfX
+ * I use "%n" at the end of a sscanf format to detect trailing junk.  However
+ * sscanf may return immediately if it sees the terminating '0' in a string, so
+ * I initialise the %n variable to the expected length.  If sscanf sets it;
+ * fine, if it doesn't, then the scan ended at the end of the string, which is
+ * fine too :) */
+static int
+libcfs_ip_str2addr(const char *str, int nob, __u32 *addr)
+{
+       unsigned int    a;
+       unsigned int    b;
+       unsigned int    c;
+       unsigned int    d;
+       int             n = nob; /* XscanfX */
+
+       /* numeric IP? */
+       if (sscanf(str, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n) >= 4 &&
+           n == nob &&
+           (a & ~0xff) == 0 && (b & ~0xff) == 0 &&
+           (c & ~0xff) == 0 && (d & ~0xff) == 0) {
+               *addr = ((a<<24)|(b<<16)|(c<<8)|d);
+               return 1;
+       }
+
+#ifdef HAVE_GETHOSTBYNAME
+       /* known hostname? */
+       if (('a' <= str[0] && str[0] <= 'z') ||
+           ('A' <= str[0] && str[0] <= 'Z')) {
+               char *tmp;
+
+               tmp = calloc(1, nob + 1);
+               if (tmp != NULL) {
+                       struct hostent *he;
+
+                       memcpy(tmp, str, nob);
+                       tmp[nob] = 0;
+
+                       he = gethostbyname(tmp);
+
+                       free(tmp);
+
+                       if (he != NULL) {
+                               __u32 ip = *(__u32 *)he->h_addr;
+
+                               *addr = ntohl(ip);
+                               return 1;
+                       }
+               }
+       }
+#endif
+       return 0;
+}
+
+int
+cfs_ip_addr_parse(char *str, int len, struct list_head *list)
+{
+       struct cfs_expr_list *el;
+       struct cfs_lstr src;
+       int rc;
+       int i;
+
+       src.ls_str = str;
+       src.ls_len = len;
+       i = 0;
+
+       while (src.ls_str != NULL) {
+               struct cfs_lstr res;
+
+               if (!cfs_gettok(&src, '.', &res)) {
+                       rc = -EINVAL;
+                       goto out;
+               }
+
+               rc = cfs_expr_list_parse(res.ls_str, res.ls_len, 0, 255, &el);
+               if (rc != 0)
+                       goto out;
+
+               list_add_tail(&el->el_link, list);
+               i++;
+       }
+
+       if (i == 4)
+               return 0;
+
+       rc = -EINVAL;
+out:
+       cfs_expr_list_free_list(list);
+
+       return rc;
+}
+
+static int
+libcfs_ip_addr_range_print(char *buffer, int count, struct list_head *list)
+{
+       int i = 0, j = 0;
+       struct cfs_expr_list *el;
+
+       list_for_each_entry(el, list, el_link) {
+               assert(j++ < 4);
+               if (i != 0)
+                       i += snprintf(buffer + i, count - i, ".");
+               i += cfs_expr_list_print(buffer + i, count - i, el);
+       }
+       return i;
+}
+
+/**
+ * Matches address (\a addr) against address set encoded in \a list.
+ *
+ * \retval 1 if \a addr matches
+ * \retval 0 otherwise
+ */
+int
+cfs_ip_addr_match(__u32 addr, struct list_head *list)
+{
+       struct cfs_expr_list *el;
+       int i = 0;
+
+       list_for_each_entry_reverse(el, list, el_link) {
+               if (!cfs_expr_list_match(addr & 0xff, el))
+                       return 0;
+               addr >>= 8;
+               i++;
+       }
+
+       return i == 4;
+}
+
+static void
+libcfs_decnum_addr2str(__u32 addr, char *str, size_t size)
+{
+       snprintf(str, size, "%u", addr);
+}
+
+static void
+libcfs_hexnum_addr2str(__u32 addr, char *str, size_t size)
+{
+       snprintf(str, size, "0x%x", addr);
+}
+
+static int
+libcfs_num_str2addr(const char *str, int nob, __u32 *addr)
+{
+       int     n;
+
+       n = nob;
+       if (sscanf(str, "0x%x%n", addr, &n) >= 1 && n == nob)
+               return 1;
+
+       n = nob;
+       if (sscanf(str, "0X%x%n", addr, &n) >= 1 && n == nob)
+               return 1;
+
+       n = nob;
+       if (sscanf(str, "%u%n", addr, &n) >= 1 && n == nob)
+               return 1;
+
+       return 0;
+}
+
+/**
+ * Nf_parse_addrlist method for networks using numeric addresses.
+ *
+ * Examples of such networks are gm and elan.
+ *
+ * \retval 0 if \a str parsed to numeric address
+ * \retval errno otherwise
+ */
+static int
+libcfs_num_parse(char *str, int len, struct list_head *list)
+{
+       struct cfs_expr_list *el;
+       int     rc;
+
+       rc = cfs_expr_list_parse(str, len, 0, MAX_NUMERIC_VALUE, &el);
+       if (rc == 0)
+               list_add_tail(&el->el_link, list);
+
+       return rc;
+}
+
+static int
+libcfs_num_addr_range_print(char *buffer, int count, struct list_head *list)
+{
+       struct cfs_expr_list *el;
+       int i = 0, j = 0;
+
+       list_for_each_entry(el, list, el_link) {
+               assert(j++ < 1);
+               i += cfs_expr_list_print(buffer + i, count - i, el);
+       }
+       return i;
+}
+
+/*
+ * Nf_match_addr method for networks using numeric addresses
+ *
+ * \retval 1 on match
+ * \retval 0 otherwise
+ */
+static int
+libcfs_num_match(__u32 addr, struct list_head *numaddr)
+{
+       struct cfs_expr_list *el;
+
+       assert(!list_empty(numaddr));
+       el = list_entry(numaddr->next, struct cfs_expr_list, el_link);
+
+       return cfs_expr_list_match(addr, el);
+}
+
 static bool cfs_ip_is_contiguous(struct list_head *nidlist);
 static void cfs_ip_min_max(struct list_head *nidlist, __u32 *min, __u32 *max);
-static void libcfs_decnum_addr2str(__u32 addr, char *str, size_t size);
-static void libcfs_hexnum_addr2str(__u32 addr, char *str, size_t size);
-static int  libcfs_num_str2addr(const char *str, int nob, __u32 *addr);
-static int  libcfs_num_parse(char *str, int len, struct list_head *list);
-static int  libcfs_num_match(__u32 addr, struct list_head *list);
-static int  libcfs_num_addr_range_print(char *buffer, int count,
-                                       struct list_head *list);
-static int  libcfs_ip_addr_range_print(char *buffer, int count,
-                                      struct list_head *list);
 static bool cfs_num_is_contiguous(struct list_head *nidlist);
 static void cfs_num_min_max(struct list_head *nidlist, __u32 *min, __u32 *max);
 
-struct netstrfns {
-       __u32 nf_type;
-       char    *nf_name;
-       char    *nf_modname;
-       void    (*nf_addr2str)(__u32 addr, char *str, size_t size);
-       int     (*nf_str2addr)(const char *str, int nob, __u32 *addr);
-       int     (*nf_parse_addrlist)(char *str, int len,
-                                       struct list_head *list);
-       int     (*nf_print_addrlist)(char *buffer, int count,
-                                    struct list_head *list);
-       int     (*nf_match_addr)(__u32 addr, struct list_head *list);
-       bool    (*nf_is_contiguous)(struct list_head *nidlist);
-       void    (*nf_min_max)(struct list_head *nidlist, __u32 *min_nid,
-                             __u32 *max_nid);
-};
-
 static struct netstrfns  libcfs_netstrfns[] = {
        {/* .nf_type      */  LOLND,
         /* .nf_name      */  "lo",
@@ -268,106 +466,6 @@ static struct netstrfns  libcfs_netstrfns[] = {
 static const size_t libcfs_nnetstrfns =
        sizeof(libcfs_netstrfns)/sizeof(libcfs_netstrfns[0]);
 
-static int
-libcfs_lo_str2addr(const char *str, int nob, __u32 *addr)
-{
-       *addr = 0;
-       return 1;
-}
-
-static void
-libcfs_ip_addr2str(__u32 addr, char *str, size_t size)
-{
-       snprintf(str, size, "%u.%u.%u.%u",
-                (addr >> 24) & 0xff, (addr >> 16) & 0xff,
-                (addr >> 8) & 0xff, addr & 0xff);
-}
-
-/* CAVEAT EMPTOR XscanfX
- * I use "%n" at the end of a sscanf format to detect trailing junk.  However
- * sscanf may return immediately if it sees the terminating '0' in a string, so
- * I initialise the %n variable to the expected length.  If sscanf sets it;
- * fine, if it doesn't, then the scan ended at the end of the string, which is
- * fine too :) */
-static int
-libcfs_ip_str2addr(const char *str, int nob, __u32 *addr)
-{
-       unsigned int    a;
-       unsigned int    b;
-       unsigned int    c;
-       unsigned int    d;
-       int             n = nob; /* XscanfX */
-
-       /* numeric IP? */
-       if (sscanf(str, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n) >= 4 &&
-           n == nob &&
-           (a & ~0xff) == 0 && (b & ~0xff) == 0 &&
-           (c & ~0xff) == 0 && (d & ~0xff) == 0) {
-               *addr = ((a<<24)|(b<<16)|(c<<8)|d);
-               return 1;
-       }
-
-#ifdef HAVE_GETHOSTBYNAME
-       /* known hostname? */
-       if (('a' <= str[0] && str[0] <= 'z') ||
-           ('A' <= str[0] && str[0] <= 'Z')) {
-               char *tmp;
-
-               tmp = calloc(1, nob + 1);
-               if (tmp != NULL) {
-                       struct hostent *he;
-
-                       memcpy(tmp, str, nob);
-                       tmp[nob] = 0;
-
-                       he = gethostbyname(tmp);
-
-                       free(tmp);
-
-                       if (he != NULL) {
-                               __u32 ip = *(__u32 *)he->h_addr;
-
-                               *addr = ntohl(ip);
-                               return 1;
-                       }
-               }
-       }
-#endif
-       return 0;
-}
-
-static void
-libcfs_decnum_addr2str(__u32 addr, char *str, size_t size)
-{
-       snprintf(str, size, "%u", addr);
-}
-
-static void
-libcfs_hexnum_addr2str(__u32 addr, char *str, size_t size)
-{
-       snprintf(str, size, "0x%x", addr);
-}
-
-static int
-libcfs_num_str2addr(const char *str, int nob, __u32 *addr)
-{
-       int     n;
-
-       n = nob;
-       if (sscanf(str, "0x%x%n", addr, &n) >= 1 && n == nob)
-               return 1;
-
-       n = nob;
-       if (sscanf(str, "0X%x%n", addr, &n) >= 1 && n == nob)
-               return 1;
-
-       n = nob;
-       if (sscanf(str, "%u%n", addr, &n) >= 1 && n == nob)
-               return 1;
-
-       return 0;
-}
-
 static struct netstrfns *
 libcfs_lnd2netstrfns(__u32 lnd)
 {
@@ -668,27 +766,6 @@ struct addrrange {
 };
 
 /**
- * Nf_parse_addrlist method for networks using numeric addresses.
- *
- * Examples of such networks are gm and elan.
- *
- * \retval 0 if \a str parsed to numeric address
- * \retval errno otherwise
- */
-static int
-libcfs_num_parse(char *str, int len, struct list_head *list)
-{
-       struct cfs_expr_list *el;
-       int     rc;
-
-       rc = cfs_expr_list_parse(str, len, 0, MAX_NUMERIC_VALUE, &el);
-       if (rc == 0)
-               list_add_tail(&el->el_link, list);
-
-       return rc;
-}
-
-/**
  * Parses \<addrrange\> token on the syntax.
  *
  * Allocates struct addrrange and links to \a nidrange via
@@ -893,23 +970,6 @@ cfs_parse_nidlist(char *str, int len, struct list_head *nidlist)
        return 1;
 }
 
-/*
- * Nf_match_addr method for networks using numeric addresses
- *
- * \retval 1 on match
- * \retval 0 otherwise
- */
-static int
-libcfs_num_match(__u32 addr, struct list_head *numaddr)
-{
-       struct cfs_expr_list *el;
-
-       assert(!list_empty(numaddr));
-       el = list_entry(numaddr->next, struct cfs_expr_list, el_link);
-
-       return cfs_expr_list_match(addr, el);
-}
-
 /**
  * Matches a nid (\a nid) against the compiled list of nidranges (\a nidlist).
  *
@@ -938,35 +998,6 @@ int cfs_match_nid(lnet_nid_t nid, struct list_head *nidlist)
        return 0;
 }
 
-static int
-libcfs_num_addr_range_print(char *buffer, int count, struct list_head *list)
-{
-       struct cfs_expr_list *el;
-       int i = 0, j = 0;
-
-       list_for_each_entry(el, list, el_link) {
-               assert(j++ < 1);
-               i += cfs_expr_list_print(buffer + i, count - i, el);
-       }
-       return i;
-}
-
-static int
-libcfs_ip_addr_range_print(char *buffer, int count, struct list_head *list)
-{
-       int i = 0, j = 0;
-       struct cfs_expr_list *el;
-
-       list_for_each_entry(el, list, el_link) {
-               assert(j++ < 4);
-               if (i != 0)
-                       i += snprintf(buffer + i, count - i, ".");
-               i += cfs_expr_list_print(buffer + i, count - i, el);
-       }
-       return i;
-}
-
-
 /**
  * Print the network part of the nidrange \a nr into the specified \a buffer.
  *