#define DEBUG_SUBSYSTEM S_LNET
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
#include <libcfs/util/string.h>
-#include <libcfs/libcfs.h>
+#include <lnet/types.h>
#include <lnet/nidstr.h>
-#ifdef HAVE_GETHOSTBYNAME
+#ifdef HAVE_NETDB_H
# include <netdb.h>
#endif
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",
/* .nf_match_addr*/ cfs_ip_addr_match,
/* .nf_is_contiguous */ cfs_ip_is_contiguous,
/* .nf_min_max */ cfs_ip_min_max},
- /* placeholder for net0 alias. It MUST BE THE LAST ENTRY */
- {/* .nf_type */ -1},
};
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)
{
for (i = 0; i < libcfs_nnetstrfns; i++) {
nf = &libcfs_netstrfns[i];
- if (nf->nf_type >= 0 &&
- !strncmp(name, nf->nf_name, strlen(nf->nf_name)))
+ if (!strncmp(name, nf->nf_name, strlen(nf->nf_name)))
return nf;
}
return NULL;
int i;
for (i = 0; i < libcfs_nnetstrfns; i++)
- if (libcfs_netstrfns[i].nf_type >= 0 &&
- !strcmp(libcfs_netstrfns[i].nf_name, name))
+ if (!strcmp(libcfs_netstrfns[i].nf_name, name))
return &libcfs_netstrfns[i];
return NULL;
for (i = 0; i < libcfs_nnetstrfns; i++) {
nf = &libcfs_netstrfns[i];
- if (nf->nf_type >= 0 &&
- !strncmp(str, nf->nf_name, strlen(nf->nf_name)))
+ if (!strncmp(str, nf->nf_name, strlen(nf->nf_name)))
break;
}
sep = str + strlen(str);
net = LNET_MKNET(SOCKLND, 0);
nf = libcfs_lnd2netstrfns(SOCKLND);
- LASSERT(nf != NULL);
+ assert(nf != NULL);
}
if (!nf->nf_str2addr(str, (int)(sep - str), &addr))
};
/**
- * 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
return 1;
failed:
- CWARN("can't parse nidrange: \"%.*s\"\n", tmp.ls_len, tmp.ls_str);
+ fprintf(stderr, "can't parse nidrange: \"%.*s\"\n",
+ tmp.ls_len, tmp.ls_str);
return 0;
}
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;
-
- LASSERT(!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).
*
return 0;
}
-static int
-libcfs_num_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) {
- LASSERT(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) {
- LASSERT(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.
*
i += snprintf(buffer + i, count - i, " ");
if (nr->nr_all != 0) {
- LASSERT(list_empty(&nr->nr_addrranges));
+ assert(list_empty(&nr->nr_addrranges));
i += snprintf(buffer + i, count - i, "*");
i += cfs_print_network(buffer + i, count - i, nr);
} else {