Whamcloud - gitweb
LU-17676 build: configure should prefer to ask if
[fs/lustre-release.git] / lnet / lnet / nidstrings.c
1 // SPDX-License-Identifier: GPL-2.0
2
3 /* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
4  * Use is subject to license terms.
5  *
6  * Copyright (c) 2011, 2015, Intel Corporation.
7  */
8
9 /* This file is part of Lustre, http://www.lustre.org/
10  *
11  * Author: Phil Schwan <phil@clusterfs.com>
12  */
13
14 #define DEBUG_SUBSYSTEM S_LNET
15
16 #include <linux/sunrpc/addr.h>
17 #include <libcfs/libcfs.h>
18 #include <uapi/linux/lnet/nidstr.h>
19 #include <lnet/lib-types.h>
20
21 /* max value for numeric network address */
22 #define MAX_NUMERIC_VALUE 0xffffffff
23
24 #define IPSTRING_LENGTH 16
25
26 /* CAVEAT VENDITOR! Keep the canonical string representation of nets/nids
27  * consistent in all conversion functions.  Some code fragments are copied
28  * around for the sake of clarity...
29  */
30
31 /* CAVEAT EMPTOR! Racey temporary buffer allocation!
32  * Choose the number of nidstrings to support the MAXIMUM expected number of
33  * concurrent users.  If there are more, the returned string will be volatile.
34  * NB this number must allow for a process to be descheduled for a timeslice
35  * between getting its string and using it.
36  */
37
38 static char      libcfs_nidstrings[LNET_NIDSTR_COUNT][LNET_NIDSTR_SIZE];
39 static int       libcfs_nidstring_idx;
40
41 static DEFINE_SPINLOCK(libcfs_nidstring_lock);
42
43 static struct netstrfns *libcfs_namenum2netstrfns(const char *name);
44
45 char *
46 libcfs_next_nidstring(void)
47 {
48         char          *str;
49         unsigned long  flags;
50
51         spin_lock_irqsave(&libcfs_nidstring_lock, flags);
52
53         str = libcfs_nidstrings[libcfs_nidstring_idx++];
54         if (libcfs_nidstring_idx == ARRAY_SIZE(libcfs_nidstrings))
55                 libcfs_nidstring_idx = 0;
56
57         spin_unlock_irqrestore(&libcfs_nidstring_lock, flags);
58         return str;
59 }
60 EXPORT_SYMBOL(libcfs_next_nidstring);
61
62 /**
63  * Nid range list syntax.
64  * \verbatim
65  *
66  * <nidlist>         :== <nidrange> [ ' ' <nidrange> ]
67  * <nidrange>        :== <addrrange> '@' <net>
68  * <addrrange>       :== '*' |
69  *                       <ipaddr_range> |
70  *                       <cfs_expr_list>
71  * <ipaddr_range>    :== <cfs_expr_list>.<cfs_expr_list>.<cfs_expr_list>.
72  *                       <cfs_expr_list>
73  * <cfs_expr_list>   :== <number> |
74  *                       <expr_list>
75  * <expr_list>       :== '[' <range_expr> [ ',' <range_expr>] ']'
76  * <range_expr>      :== <number> |
77  *                       <number> '-' <number> |
78  *                       <number> '-' <number> '/' <number>
79  * <net>             :== <netname> | <netname><number>
80  * <netname>         :== "lo" | "tcp" | "o2ib" | "cib" | "openib" | "iib" |
81  *                       "vib" | "ra" | "elan" | "mx" | "ptl"
82  * \endverbatim
83  */
84
85 /**
86  * Structure to represent \<nidrange\> token of the syntax.
87  *
88  * One of this is created for each \<net\> parsed.
89  */
90 struct nidrange {
91         /**
92          * Link to list of this structures which is built on nid range
93          * list parsing.
94          */
95         struct list_head nr_link;
96         /**
97          * List head for addrrange::ar_link.
98          */
99         struct list_head nr_addrranges;
100         /**
101          * Flag indicating that *@<net> is found.
102          */
103         int nr_all;
104         /**
105          * Pointer to corresponding element of libcfs_netstrfns.
106          */
107         struct netstrfns *nr_netstrfns;
108         /**
109          * Number of network. E.g. 5 if \<net\> is "elan5".
110          */
111         int nr_netnum;
112 };
113
114 /**
115  * Structure to represent \<addrrange\> token of the syntax.
116  */
117 struct addrrange {
118         /**
119          * Link to nidrange::nr_addrranges.
120          */
121         struct list_head ar_link;
122         /**
123          * List head for cfs_expr_list::el_list.
124          */
125         struct list_head ar_numaddr_ranges;
126 };
127
128 /**
129  * Parses \<range_expr\> token of the syntax. If \a bracketed is false,
130  * \a src should only have a single token which can be \<number\> or  \*
131  *
132  * \retval pointer to allocated range_expr and initialized
133  * range_expr::re_lo, range_expr::re_hi and range_expr:re_stride if \a
134  `* src parses to
135  * \<number\> |
136  * \<number\> '-' \<number\> |
137  * \<number\> '-' \<number\> '/' \<number\>
138  * \retval 0 will be returned if it can be parsed, otherwise -EINVAL or
139  * -ENOMEM will be returned.
140  */
141 static int
142 cfs_range_expr_parse(char *src, unsigned int min, unsigned int max,
143                      int bracketed, struct cfs_range_expr **expr)
144 {
145         struct cfs_range_expr *re;
146         char *tok;
147         unsigned int num;
148
149         LIBCFS_ALLOC(re, sizeof(*re));
150         if (!re)
151                 return -ENOMEM;
152
153         src = strim(src);
154         if (strcmp(src, "*") == 0) {
155                 re->re_lo = min;
156                 re->re_hi = max;
157                 re->re_stride = 1;
158                 goto out;
159         }
160
161         if (kstrtouint(src, 0, &num) == 0) {
162                 if (num < min || num > max)
163                         goto failed;
164                 /* <number> is parsed */
165                 re->re_lo = num;
166                 re->re_hi = re->re_lo;
167                 re->re_stride = 1;
168                 goto out;
169         }
170
171         if (!bracketed)
172                 goto failed;
173         tok = strim(strsep(&src, "-"));
174         if (!src)
175                 goto failed;
176         if (kstrtouint(tok, 0, &num) != 0 ||
177             num < min || num > max)
178                 goto failed;
179         re->re_lo = num;
180
181         /* <number> - */
182         if (kstrtouint(strim(src), 0, &num) == 0) {
183                 if (num < min || num > max)
184                         goto failed;
185                 re->re_hi = num;
186                 /* <number> - <number> is parsed */
187                 re->re_stride = 1;
188                 goto out;
189         }
190
191         /* go to check <number> '-' <number> '/' <number> */
192         tok = strim(strsep(&src, "/"));
193         if (!src)
194                 goto failed;
195         if (kstrtouint(tok, 0, &num) != 0 ||
196             num < min || num > max)
197                 goto failed;
198         re->re_hi = num;
199         if (kstrtouint(strim(src), 0, &num) != 0 ||
200             num < min || num > max)
201                 goto failed;
202         re->re_stride = num;
203
204 out:
205         *expr = re;
206         return 0;
207
208 failed:
209         LIBCFS_FREE(re, sizeof(*re));
210         return -EINVAL;
211 }
212
213 /**
214  * Matches value (\a value) against ranges expression list \a expr_list.
215  *
216  * \retval 1 if \a value matches
217  * \retval 0 otherwise
218  */
219 int
220 cfs_expr_list_match(u32 value, struct cfs_expr_list *expr_list)
221 {
222         struct cfs_range_expr *expr;
223
224         list_for_each_entry(expr, &expr_list->el_exprs, re_link) {
225                 if (value >= expr->re_lo && value <= expr->re_hi &&
226                     ((value - expr->re_lo) % expr->re_stride) == 0)
227                         return 1;
228         }
229
230         return 0;
231 }
232
233 /**
234  * Convert express list (\a expr_list) to an array of all matched values
235  *
236  * \retval N N is total number of all matched values
237  * \retval 0 if expression list is empty
238  * \retval < 0 for failure
239  */
240 int
241 cfs_expr_list_values(struct cfs_expr_list *expr_list, int max, u32 **valpp)
242 {
243         struct cfs_range_expr *expr;
244         int count = 0;
245         u32 *val;
246         int i;
247
248         list_for_each_entry(expr, &expr_list->el_exprs, re_link) {
249                 for (i = expr->re_lo; i <= expr->re_hi; i++) {
250                         if (((i - expr->re_lo) % expr->re_stride) == 0)
251                                 count++;
252                 }
253         }
254
255         if (count == 0) /* empty expression list */
256                 return 0;
257
258         if (count > max) {
259                 CERROR("Number of values %d exceeds max allowed %d\n",
260                        max, count);
261                 return -EINVAL;
262         }
263
264         CFS_ALLOC_PTR_ARRAY(val, count);
265         if (!val)
266                 return -ENOMEM;
267
268         count = 0;
269         list_for_each_entry(expr, &expr_list->el_exprs, re_link) {
270                 for (i = expr->re_lo; i <= expr->re_hi; i++) {
271                         if (((i - expr->re_lo) % expr->re_stride) == 0)
272                                 val[count++] = i;
273                 }
274         }
275
276         *valpp = val;
277         return count;
278 }
279 EXPORT_SYMBOL(cfs_expr_list_values);
280
281 /**
282  * Frees cfs_range_expr structures of \a expr_list.
283  *
284  * \retval none
285  */
286 void
287 cfs_expr_list_free(struct cfs_expr_list *expr_list)
288 {
289         while (!list_empty(&expr_list->el_exprs)) {
290                 struct cfs_range_expr *expr;
291
292                 expr = list_entry(expr_list->el_exprs.next,
293                                       struct cfs_range_expr, re_link);
294                 list_del(&expr->re_link);
295                 LIBCFS_FREE(expr, sizeof(*expr));
296         }
297
298         LIBCFS_FREE(expr_list, sizeof(*expr_list));
299 }
300 EXPORT_SYMBOL(cfs_expr_list_free);
301
302 /**
303  * Parses \<cfs_expr_list\> token of the syntax.
304  *
305  * \retval 0 if \a str parses to \<number\> | \<expr_list\>
306  * \retval -errno otherwise
307  */
308 int
309 cfs_expr_list_parse(char *str, int len, unsigned int min, unsigned int max,
310                     struct cfs_expr_list **elpp)
311 {
312         struct cfs_expr_list *expr_list;
313         struct cfs_range_expr *expr;
314         char *src;
315         int rc;
316
317         CFS_ALLOC_PTR(expr_list);
318         if (!expr_list)
319                 return -ENOMEM;
320
321         str = kstrndup(str, len, GFP_KERNEL);
322         if (!str) {
323                 CFS_FREE_PTR(expr_list);
324                 return -ENOMEM;
325         }
326
327         src = str;
328
329         INIT_LIST_HEAD(&expr_list->el_exprs);
330
331         if (src[0] == '[' &&
332             src[strlen(src) - 1] == ']') {
333                 src++;
334                 src[strlen(src)-1] = '\0';
335
336                 rc = -EINVAL;
337                 while (src) {
338                         char *tok = strsep(&src, ",");
339
340                         if (!*tok) {
341                                 rc = -EINVAL;
342                                 break;
343                         }
344                         tok = strim(tok);
345
346                         rc = cfs_range_expr_parse(tok, min, max, 1, &expr);
347                         if (rc != 0)
348                                 break;
349
350                         list_add_tail(&expr->re_link, &expr_list->el_exprs);
351                 }
352         } else {
353                 rc = cfs_range_expr_parse(src, min, max, 0, &expr);
354                 if (rc == 0)
355                         list_add_tail(&expr->re_link, &expr_list->el_exprs);
356         }
357         kfree(str);
358
359         if (rc != 0)
360                 cfs_expr_list_free(expr_list);
361         else
362                 *elpp = expr_list;
363
364         return rc;
365 }
366 EXPORT_SYMBOL(cfs_expr_list_parse);
367
368 /**
369  * Frees cfs_expr_list structures of \a list.
370  *
371  * For each struct cfs_expr_list structure found on \a list it frees
372  * range_expr list attached to it and frees the cfs_expr_list itself.
373  *
374  * \retval none
375  */
376 void
377 cfs_expr_list_free_list(struct list_head *list)
378 {
379         struct cfs_expr_list *el;
380
381         while (!list_empty(list)) {
382                 el = list_first_entry(list,
383                                       struct cfs_expr_list, el_link);
384                 list_del(&el->el_link);
385                 cfs_expr_list_free(el);
386         }
387 }
388
389 /**
390  * Parses \<addrrange\> token on the syntax.
391  *
392  * Allocates struct addrrange and links to \a nidrange via
393  * (nidrange::nr_addrranges)
394  *
395  * \retval 0 if \a src parses to '*' | \<ipaddr_range\> | \<cfs_expr_list\>
396  * \retval -errno otherwise
397  */
398 static int
399 parse_addrange(char *str, struct nidrange *nidrange)
400 {
401         struct addrrange *addrrange;
402
403         if (strcmp(str, "*") == 0) {
404                 nidrange->nr_all = 1;
405                 return 0;
406         }
407
408         CFS_ALLOC_PTR(addrrange);
409         if (addrrange == NULL)
410                 return -ENOMEM;
411         list_add_tail(&addrrange->ar_link, &nidrange->nr_addrranges);
412         INIT_LIST_HEAD(&addrrange->ar_numaddr_ranges);
413
414         return nidrange->nr_netstrfns->nf_parse_addrlist(str, strlen(str),
415                                                 &addrrange->ar_numaddr_ranges);
416 }
417
418 /**
419  * Finds or creates struct nidrange.
420  *
421  * Checks if \a src is a valid network name, looks for corresponding
422  * nidrange on the ist of nidranges (\a nidlist), creates new struct
423  * nidrange if it is not found.
424  *
425  * \retval pointer to struct nidrange matching network specified via \a src
426  * \retval NULL if \a src does not match any network
427  */
428 static struct nidrange *
429 add_nidrange(char *str, struct list_head *nidlist)
430 {
431         struct netstrfns *nf;
432         struct nidrange *nr;
433         char *end;
434         unsigned int netnum;
435
436         nf = libcfs_namenum2netstrfns(str);
437         if (nf == NULL)
438                 return NULL;
439         end = str + strlen(nf->nf_name);
440         if (!*end) {
441                 /* network name only, e.g. "elan" or "tcp" */
442                 netnum = 0;
443         } else {
444                 /* e.g. "elan25" or "tcp23", refuse to parse if
445                  * network name is not appended with decimal or
446                  * hexadecimal number
447                  */
448                 if (kstrtouint(end, 0, &netnum) != 0)
449                         return NULL;
450         }
451
452         list_for_each_entry(nr, nidlist, nr_link) {
453                 if (nr->nr_netstrfns != nf)
454                         continue;
455                 if (nr->nr_netnum != netnum)
456                         continue;
457                 return nr;
458         }
459
460         CFS_ALLOC_PTR(nr);
461         if (nr == NULL)
462                 return NULL;
463         list_add_tail(&nr->nr_link, nidlist);
464         INIT_LIST_HEAD(&nr->nr_addrranges);
465         nr->nr_netstrfns = nf;
466         nr->nr_all = 0;
467         nr->nr_netnum = netnum;
468
469         return nr;
470 }
471
472 /**
473  * Parses \<nidrange\> token of the syntax.
474  *
475  * \retval 0 if \a src parses to \<addrrange\> '@' \<net\>
476  * \retval -EINVAL otherwise
477  */
478 static int
479 parse_nidrange(char *str, struct list_head *nidlist)
480 {
481         char *addrrange;
482         char *net;
483         struct nidrange *nr;
484
485         addrrange = strim(strsep(&str, "@"));
486         if (!str)
487                 goto failed;
488
489         net = strim(str);
490         if (strchr(net, '@') != NULL || !*net)
491                 goto failed;
492
493         nr = add_nidrange(net, nidlist);
494         if (nr == NULL)
495                 goto failed;
496
497         if (parse_addrange(addrrange, nr) != 0)
498                 goto failed;
499
500         return 0;
501 failed:
502         return -EINVAL;
503 }
504
505 /**
506  * Frees addrrange structures of \a list.
507  *
508  * For each struct addrrange structure found on \a list it frees
509  * cfs_expr_list list attached to it and frees the addrrange itself.
510  *
511  * \retval none
512  */
513 static void
514 free_addrranges(struct list_head *list)
515 {
516         struct addrrange *ar;
517
518         while ((ar = list_first_entry_or_null(list,
519                                               struct addrrange,
520                                               ar_link)) != NULL) {
521                 cfs_expr_list_free_list(&ar->ar_numaddr_ranges);
522                 list_del(&ar->ar_link);
523                 CFS_FREE_PTR(ar);
524         }
525 }
526
527 /**
528  * Frees nidrange strutures of \a list.
529  *
530  * For each struct nidrange structure found on \a list it frees
531  * addrrange list attached to it and frees the nidrange itself.
532  *
533  * \retval none
534  */
535 void
536 cfs_free_nidlist(struct list_head *list)
537 {
538         struct list_head *pos, *next;
539         struct nidrange *nr;
540
541         list_for_each_safe(pos, next, list) {
542                 nr = list_entry(pos, struct nidrange, nr_link);
543                 free_addrranges(&nr->nr_addrranges);
544                 list_del(pos);
545                 CFS_FREE_PTR(nr);
546         }
547 }
548 EXPORT_SYMBOL(cfs_free_nidlist);
549
550 /**
551  * Parses nid range list.
552  *
553  * Parses with rigorous syntax and overflow checking \a str into
554  * \<nidrange\> [ ' ' \<nidrange\> ], compiles \a str into set of
555  * structures and links that structure to \a nidlist. The resulting
556  * list can be used to match a NID againts set of NIDS defined by \a
557  * str.
558  * \see cfs_match_nid
559  *
560  * \retval 0 on success
561  * \retval -errno otherwise (-ENOMEM or -EINVAL)
562  */
563 int
564 cfs_parse_nidlist(char *orig, struct list_head *nidlist)
565 {
566         int rc = 0;
567         char *str;
568
569         orig = kstrdup(orig, GFP_KERNEL);
570         if (!orig)
571                 return -ENOMEM;
572
573         INIT_LIST_HEAD(nidlist);
574         str = orig;
575         while (rc == 0 && str) {
576                 char *tok = strsep(&str, " ");
577
578                 if (*tok)
579                         rc = parse_nidrange(tok, nidlist);
580         }
581         kfree(orig);
582         if (rc)
583                 cfs_free_nidlist(nidlist);
584         else if (list_empty(nidlist))
585                 rc = -EINVAL;
586         return rc;
587 }
588 EXPORT_SYMBOL(cfs_parse_nidlist);
589
590 /**
591  * Matches a nid (\a nid) against the compiled list of nidranges (\a nidlist).
592  *
593  * \see cfs_parse_nidlist()
594  *
595  * \retval 1 on match
596  * \retval 0  otherwises
597  */
598 int cfs_match_nid(struct lnet_nid *nid, struct list_head *nidlist)
599 {
600         struct nidrange *nr;
601         struct addrrange *ar;
602
603         if (!nid_is_nid4(nid))
604                 return 0;
605         list_for_each_entry(nr, nidlist, nr_link) {
606                 if (nr->nr_netstrfns->nf_type != nid->nid_type)
607                         continue;
608                 if (nr->nr_netnum != be16_to_cpu(nid->nid_num))
609                         continue;
610                 if (nr->nr_all)
611                         return 1;
612                 list_for_each_entry(ar, &nr->nr_addrranges, ar_link)
613                         if (nr->nr_netstrfns->nf_match_addr(
614                                     be32_to_cpu(nid->nid_addr[0]),
615                                     &ar->ar_numaddr_ranges))
616                                 return 1;
617         }
618         return 0;
619 }
620 EXPORT_SYMBOL(cfs_match_nid);
621
622 /**
623  * Print the network part of the nidrange \a nr into the specified \a buffer.
624  *
625  * \retval number of characters written
626  */
627 static int
628 cfs_print_network(char *buffer, int count, struct nidrange *nr)
629 {
630         struct netstrfns *nf = nr->nr_netstrfns;
631
632         if (nr->nr_netnum == 0)
633                 return scnprintf(buffer, count, "@%s", nf->nf_name);
634         else
635                 return scnprintf(buffer, count, "@%s%u",
636                                     nf->nf_name, nr->nr_netnum);
637 }
638
639 /**
640  * Print a list of addrrange (\a addrranges) into the specified \a buffer.
641  * At max \a count characters can be printed into \a buffer.
642  *
643  * \retval number of characters written
644  */
645 static int
646 cfs_print_addrranges(char *buffer, int count, struct list_head *addrranges,
647                      struct nidrange *nr)
648 {
649         int i = 0;
650         struct addrrange *ar;
651         struct netstrfns *nf = nr->nr_netstrfns;
652
653         list_for_each_entry(ar, addrranges, ar_link) {
654                 if (i != 0)
655                         i += scnprintf(buffer + i, count - i, " ");
656                 i += nf->nf_print_addrlist(buffer + i, count - i,
657                                            &ar->ar_numaddr_ranges);
658                 i += cfs_print_network(buffer + i, count - i, nr);
659         }
660         return i;
661 }
662
663 /**
664  * Print a list of nidranges (\a nidlist) into the specified \a buffer.
665  * At max \a count characters can be printed into \a buffer.
666  * Nidranges are separated by a space character.
667  *
668  * \retval number of characters written
669  */
670 int cfs_print_nidlist(char *buffer, int count, struct list_head *nidlist)
671 {
672         int i = 0;
673         struct nidrange *nr;
674
675         if (count <= 0)
676                 return 0;
677
678         list_for_each_entry(nr, nidlist, nr_link) {
679                 if (i != 0)
680                         i += scnprintf(buffer + i, count - i, " ");
681
682                 if (nr->nr_all != 0) {
683                         LASSERT(list_empty(&nr->nr_addrranges));
684                         i += scnprintf(buffer + i, count - i, "*");
685                         i += cfs_print_network(buffer + i, count - i, nr);
686                 } else {
687                         i += cfs_print_addrranges(buffer + i, count - i,
688                                                   &nr->nr_addrranges, nr);
689                 }
690         }
691         return i;
692 }
693 EXPORT_SYMBOL(cfs_print_nidlist);
694
695 static int
696 libcfs_lo_str2addr(const char *str, int nob, __u32 *addr)
697 {
698         *addr = 0;
699         return 1;
700 }
701
702 static void
703 libcfs_ip_addr2str(__u32 addr, char *str, size_t size)
704 {
705         snprintf(str, size, "%u.%u.%u.%u",
706                  (addr >> 24) & 0xff, (addr >> 16) & 0xff,
707                  (addr >> 8) & 0xff, addr & 0xff);
708 }
709
710 static void
711 libcfs_ip_addr2str_size(const __be32 *addr, size_t asize,
712                         char *str, size_t size)
713 {
714         struct sockaddr_storage sa = {};
715
716         switch (asize) {
717         case 4:
718                 sa.ss_family = AF_INET;
719                 memcpy(&((struct sockaddr_in *)(&sa))->sin_addr.s_addr,
720                        addr, asize);
721                 break;
722         case 16:
723                 sa.ss_family = AF_INET6;
724                 memcpy(&((struct sockaddr_in6 *)(&sa))->sin6_addr.s6_addr,
725                        addr, asize);
726                 break;
727         default:
728                 return;
729         }
730
731         rpc_ntop((struct sockaddr *)&sa, str, size);
732 }
733
734 /* CAVEAT EMPTOR XscanfX
735  * I use "%n" at the end of a sscanf format to detect trailing junk.  However
736  * sscanf may return immediately if it sees the terminating '0' in a string, so
737  * I initialise the %n variable to the expected length.  If sscanf sets it;
738  * fine, if it doesn't, then the scan ended at the end of the string, which is
739  * fine too :) */
740 static int
741 libcfs_ip_str2addr(const char *str, int nob, __u32 *addr)
742 {
743         unsigned int    a;
744         unsigned int    b;
745         unsigned int    c;
746         unsigned int    d;
747         int             n = nob; /* XscanfX */
748
749         /* numeric IP? */
750         if (sscanf(str, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n) >= 4 &&
751             n == nob &&
752             (a & ~0xff) == 0 && (b & ~0xff) == 0 &&
753             (c & ~0xff) == 0 && (d & ~0xff) == 0) {
754                 *addr = ((a<<24)|(b<<16)|(c<<8)|d);
755                 return 1;
756         }
757         return 0;
758 }
759
760 static int
761 libcfs_ip_str2addr_size(const char *str, int nob,
762                         __be32 *addr, size_t *alen)
763 {
764         struct sockaddr_storage sa;
765
766         /* Note: 'net' arg to rpc_pton is only needed for link-local
767          * addresses.  Such addresses would not work with LNet routing,
768          * so we can assume they aren't used.  So it doesn't matter
769          * which net namespace is passed.
770          */
771         if (rpc_pton(&init_net, str, nob,
772                      (struct sockaddr *)&sa, sizeof(sa)) == 0)
773                 return 0;
774         if (sa.ss_family == AF_INET6) {
775                 memcpy(addr,
776                        &((struct sockaddr_in6 *)(&sa))->sin6_addr.s6_addr,
777                        16);
778                 *alen = 16;
779                 return 1;
780         }
781         if (sa.ss_family == AF_INET) {
782                 memcpy(addr,
783                        &((struct sockaddr_in *)(&sa))->sin_addr.s_addr,
784                        4);
785                 *alen = 4;
786                 return 1;
787         }
788         return 0;
789 }
790
791
792 /* Used by lnet/config.c so it can't be static */
793 int
794 cfs_ip_addr_parse(char *str, int len_ignored, struct list_head *list)
795 {
796         struct cfs_expr_list *el;
797         int rc = 0;
798         int i = 0;
799
800         str = strim(str);
801         while (rc == 0 && str) {
802                 char *res;
803
804                 res = strsep(&str, ".");
805                 res = strim(res);
806                 if (!*res) {
807                         rc = -EINVAL;
808                 } else if ((rc = cfs_expr_list_parse(res, strlen(res),
809                                                    0, 255, &el)) == 0) {
810                         list_add_tail(&el->el_link, list);
811                         i++;
812                 }
813         }
814
815         if (rc == 0 && i == 4)
816                 return 0;
817         cfs_expr_list_free_list(list);
818
819         return rc ?: -EINVAL;
820 }
821
822 /**
823  * Print the range expression \a re into specified \a buffer.
824  * If \a bracketed is true, expression does not need additional
825  * brackets.
826  *
827  * \retval number of characters written
828  */
829 static int
830 cfs_range_expr_print(char *buffer, int count, struct cfs_range_expr *expr,
831                      bool bracketed)
832 {
833         int i;
834         char s[] = "[";
835         char e[] = "]";
836
837         if (bracketed)
838                 s[0] = e[0] = '\0';
839
840         if (expr->re_lo == expr->re_hi)
841                 i = scnprintf(buffer, count, "%u", expr->re_lo);
842         else if (expr->re_stride == 1)
843                 i = scnprintf(buffer, count, "%s%u-%u%s",
844                               s, expr->re_lo, expr->re_hi, e);
845         else
846                 i = scnprintf(buffer, count, "%s%u-%u/%u%s",
847                               s, expr->re_lo, expr->re_hi,
848                               expr->re_stride, e);
849         return i;
850 }
851
852 /**
853  * Print a list of range expressions (\a expr_list) into specified \a buffer.
854  * If the list contains several expressions, separate them with comma
855  * and surround the list with brackets.
856  *
857  * \retval number of characters written
858  */
859 static int
860 cfs_expr_list_print(char *buffer, int count, struct cfs_expr_list *expr_list)
861 {
862         struct cfs_range_expr *expr;
863         int i = 0, j = 0;
864         int numexprs = 0;
865
866         if (count <= 0)
867                 return 0;
868
869         list_for_each_entry(expr, &expr_list->el_exprs, re_link)
870                 numexprs++;
871
872         if (numexprs > 1)
873                 i += scnprintf(buffer + i, count - i, "[");
874
875         list_for_each_entry(expr, &expr_list->el_exprs, re_link) {
876                 if (j++ != 0)
877                         i += scnprintf(buffer + i, count - i, ",");
878                 i += cfs_range_expr_print(buffer + i, count - i, expr,
879                                           numexprs > 1);
880         }
881
882         if (numexprs > 1)
883                 i += scnprintf(buffer + i, count - i, "]");
884
885         return i;
886 }
887
888 static int
889 libcfs_ip_addr_range_print(char *buffer, int count, struct list_head *list)
890 {
891         int i = 0, j = 0;
892         struct cfs_expr_list *el;
893
894         list_for_each_entry(el, list, el_link) {
895                 LASSERT(j++ < 4);
896                 if (i != 0)
897                         i += scnprintf(buffer + i, count - i, ".");
898                 i += cfs_expr_list_print(buffer + i, count - i, el);
899         }
900         return i;
901 }
902
903 /**
904  * Matches address (\a addr) against address set encoded in \a list.
905  *
906  * \retval 1 if \a addr matches
907  * \retval 0 otherwise
908  */
909 int
910 cfs_ip_addr_match(__u32 addr, struct list_head *list)
911 {
912         struct cfs_expr_list *el;
913         int i = 0;
914
915         list_for_each_entry_reverse(el, list, el_link) {
916                 if (!cfs_expr_list_match(addr & 0xff, el))
917                         return 0;
918                 addr >>= 8;
919                 i++;
920         }
921
922         return i == 4;
923 }
924
925 /**
926  * Print the network part of the nidrange \a nr into the specified \a buffer.
927  *
928  * \retval number of characters written
929  */
930 static void
931 libcfs_decnum_addr2str(__u32 addr, char *str, size_t size)
932 {
933         snprintf(str, size, "%u", addr);
934 }
935
936 static int
937 libcfs_num_str2addr(const char *str, int nob, __u32 *addr)
938 {
939         int     n;
940
941         n = nob;
942         if (sscanf(str, "0x%x%n", addr, &n) >= 1 && n == nob)
943                 return 1;
944
945         n = nob;
946         if (sscanf(str, "0X%x%n", addr, &n) >= 1 && n == nob)
947                 return 1;
948
949         n = nob;
950         if (sscanf(str, "%u%n", addr, &n) >= 1 && n == nob)
951                 return 1;
952
953         return 0;
954 }
955
956 /**
957  * Nf_parse_addrlist method for networks using numeric addresses.
958  *
959  * Examples of such networks are gm and elan.
960  *
961  * \retval 0 if \a str parsed to numeric address
962  * \retval errno otherwise
963  */
964 int
965 libcfs_num_parse(char *str, int len, struct list_head *list)
966 {
967         struct cfs_expr_list *el;
968         int     rc;
969
970         rc = cfs_expr_list_parse(str, len, 0, MAX_NUMERIC_VALUE, &el);
971         if (rc == 0)
972                 list_add_tail(&el->el_link, list);
973
974         return rc;
975 }
976
977 static int
978 libcfs_num_addr_range_print(char *buffer, int count, struct list_head *list)
979 {
980         int i = 0, j = 0;
981         struct cfs_expr_list *el;
982
983         list_for_each_entry(el, list, el_link) {
984                 LASSERT(j++ < 1);
985                 i += cfs_expr_list_print(buffer + i, count - i, el);
986         }
987         return i;
988 }
989
990 /*
991  * Nf_match_addr method for networks using numeric addresses
992  *
993  * \retval 1 on match
994  * \retval 0 otherwise
995  */
996 static int
997 libcfs_num_match(__u32 addr, struct list_head *numaddr)
998 {
999         struct cfs_expr_list *el;
1000
1001         LASSERT(!list_empty(numaddr));
1002         el = list_first_entry(numaddr, struct cfs_expr_list, el_link);
1003
1004         return cfs_expr_list_match(addr, el);
1005 }
1006
1007 static struct netstrfns libcfs_netstrfns[] = {
1008         { .nf_type              = LOLND,
1009           .nf_name              = "lo",
1010           .nf_modname           = "klolnd",
1011           .nf_addr2str          = libcfs_decnum_addr2str,
1012           .nf_str2addr          = libcfs_lo_str2addr,
1013           .nf_parse_addrlist    = libcfs_num_parse,
1014           .nf_print_addrlist    = libcfs_num_addr_range_print,
1015           .nf_match_addr        = libcfs_num_match
1016         },
1017         { .nf_type              = SOCKLND,
1018           .nf_name              = "tcp",
1019           .nf_modname           = "ksocklnd",
1020           .nf_addr2str          = libcfs_ip_addr2str,
1021           .nf_addr2str_size     = libcfs_ip_addr2str_size,
1022           .nf_str2addr          = libcfs_ip_str2addr,
1023           .nf_str2addr_size     = libcfs_ip_str2addr_size,
1024           .nf_parse_addrlist    = cfs_ip_addr_parse,
1025           .nf_print_addrlist    = libcfs_ip_addr_range_print,
1026           .nf_match_addr        = cfs_ip_addr_match
1027         },
1028         { .nf_type              = O2IBLND,
1029           .nf_name              = "o2ib",
1030           .nf_modname           = "ko2iblnd",
1031           .nf_addr2str          = libcfs_ip_addr2str,
1032           .nf_str2addr          = libcfs_ip_str2addr,
1033           .nf_parse_addrlist    = cfs_ip_addr_parse,
1034           .nf_print_addrlist    = libcfs_ip_addr_range_print,
1035           .nf_match_addr        = cfs_ip_addr_match
1036         },
1037         { .nf_type              = GNILND,
1038           .nf_name              = "gni",
1039           .nf_modname           = "kgnilnd",
1040           .nf_addr2str          = libcfs_decnum_addr2str,
1041           .nf_str2addr          = libcfs_num_str2addr,
1042           .nf_parse_addrlist    = libcfs_num_parse,
1043           .nf_print_addrlist    = libcfs_num_addr_range_print,
1044           .nf_match_addr        = libcfs_num_match
1045         },
1046         { .nf_type              = GNIIPLND,
1047           .nf_name              = "gip",
1048           .nf_modname           = "kgnilnd",
1049           .nf_addr2str          = libcfs_ip_addr2str,
1050           .nf_str2addr          = libcfs_ip_str2addr,
1051           .nf_parse_addrlist    = cfs_ip_addr_parse,
1052           .nf_print_addrlist    = libcfs_ip_addr_range_print,
1053           .nf_match_addr        = cfs_ip_addr_match
1054         },
1055         { .nf_type              = PTL4LND,
1056           .nf_name              = "ptlf",
1057           .nf_modname           = "kptl4lnd",
1058           .nf_addr2str          = libcfs_decnum_addr2str,
1059           .nf_str2addr          = libcfs_num_str2addr,
1060           .nf_parse_addrlist    = libcfs_num_parse,
1061           .nf_print_addrlist    = libcfs_num_addr_range_print,
1062           .nf_match_addr        = libcfs_num_match
1063         },
1064         {
1065           .nf_type              = KFILND,
1066           .nf_name              = "kfi",
1067           .nf_modname           = "kkfilnd",
1068           .nf_addr2str          = libcfs_decnum_addr2str,
1069           .nf_str2addr          = libcfs_num_str2addr,
1070           .nf_parse_addrlist    = libcfs_num_parse,
1071           .nf_print_addrlist    = libcfs_num_addr_range_print,
1072           .nf_match_addr        = libcfs_num_match
1073         },
1074 };
1075
1076 static const size_t libcfs_nnetstrfns = ARRAY_SIZE(libcfs_netstrfns);
1077
1078 static struct netstrfns *
1079 type2net_info(__u32 net_type)
1080 {
1081         int i;
1082
1083         for (i = 0; i < libcfs_nnetstrfns; i++) {
1084                 if (libcfs_netstrfns[i].nf_type == net_type)
1085                         return &libcfs_netstrfns[i];
1086         }
1087
1088         return NULL;
1089 }
1090
1091 int
1092 cfs_match_net(__u32 net_id, __u32 net_type, struct list_head *net_num_list)
1093 {
1094         __u32 net_num;
1095
1096         if (!net_num_list)
1097                 return 0;
1098
1099         if (net_type != LNET_NETTYP(net_id))
1100                 return 0;
1101
1102         net_num = LNET_NETNUM(net_id);
1103
1104         /* if there is a net number but the list passed in is empty, then
1105          * there is no match.
1106          */
1107         if (!net_num && list_empty(net_num_list))
1108                 return 1;
1109         else if (list_empty(net_num_list))
1110                 return 0;
1111
1112         if (!libcfs_num_match(net_num, net_num_list))
1113                 return 0;
1114
1115         return 1;
1116 }
1117
1118 int
1119 cfs_match_nid_net(struct lnet_nid *nid, __u32 net_type,
1120                    struct list_head *net_num_list,
1121                    struct list_head *addr)
1122 {
1123         __u32 address;
1124         struct netstrfns *nf;
1125
1126         if (!addr || list_empty(addr) || !net_num_list)
1127                 return 0;
1128
1129         nf = type2net_info(LNET_NETTYP(LNET_NID_NET(nid)));
1130         if (!nf)
1131                 return 0;
1132
1133         /* FIXME handle long-addr nid */
1134         address = LNET_NIDADDR(lnet_nid_to_nid4(nid));
1135
1136         /* if either the address or net number don't match then no match */
1137         if (!nf->nf_match_addr(address, addr) ||
1138             !cfs_match_net(LNET_NID_NET(nid), net_type, net_num_list))
1139                 return 0;
1140
1141         return 1;
1142 }
1143 EXPORT_SYMBOL(cfs_match_nid_net);
1144
1145 static struct netstrfns *
1146 libcfs_lnd2netstrfns(__u32 lnd)
1147 {
1148         int     i;
1149
1150         for (i = 0; i < libcfs_nnetstrfns; i++)
1151                 if (lnd == libcfs_netstrfns[i].nf_type)
1152                         return &libcfs_netstrfns[i];
1153
1154         return NULL;
1155 }
1156
1157 static struct netstrfns *
1158 libcfs_namenum2netstrfns(const char *name)
1159 {
1160         struct netstrfns *nf;
1161         int               i;
1162
1163         for (i = 0; i < libcfs_nnetstrfns; i++) {
1164                 nf = &libcfs_netstrfns[i];
1165                 if (!strncmp(name, nf->nf_name, strlen(nf->nf_name)))
1166                         return nf;
1167         }
1168         return NULL;
1169 }
1170
1171 static struct netstrfns *
1172 libcfs_name2netstrfns(const char *name)
1173 {
1174         int    i;
1175
1176         for (i = 0; i < libcfs_nnetstrfns; i++)
1177                 if (!strcmp(libcfs_netstrfns[i].nf_name, name))
1178                         return &libcfs_netstrfns[i];
1179
1180         return NULL;
1181 }
1182
1183 int
1184 libcfs_isknown_lnd(__u32 lnd)
1185 {
1186         return libcfs_lnd2netstrfns(lnd) != NULL;
1187 }
1188 EXPORT_SYMBOL(libcfs_isknown_lnd);
1189
1190 char *
1191 libcfs_lnd2modname(__u32 lnd)
1192 {
1193         struct netstrfns *nf = libcfs_lnd2netstrfns(lnd);
1194
1195         return (nf == NULL) ? NULL : nf->nf_modname;
1196 }
1197 EXPORT_SYMBOL(libcfs_lnd2modname);
1198
1199 int
1200 libcfs_str2lnd(const char *str)
1201 {
1202         struct netstrfns *nf = libcfs_name2netstrfns(str);
1203
1204         if (nf != NULL)
1205                 return nf->nf_type;
1206
1207         return -ENXIO;
1208 }
1209 EXPORT_SYMBOL(libcfs_str2lnd);
1210
1211 char *
1212 libcfs_lnd2str_r(__u32 lnd, char *buf, size_t buf_size)
1213 {
1214         struct netstrfns *nf;
1215
1216         nf = libcfs_lnd2netstrfns(lnd);
1217         if (nf == NULL)
1218                 snprintf(buf, buf_size, "?%u?", lnd);
1219         else
1220                 snprintf(buf, buf_size, "%s", nf->nf_name);
1221
1222         return buf;
1223 }
1224 EXPORT_SYMBOL(libcfs_lnd2str_r);
1225
1226 char *
1227 libcfs_net2str_r(__u32 net, char *buf, size_t buf_size)
1228 {
1229         __u32             nnum = LNET_NETNUM(net);
1230         __u32             lnd  = LNET_NETTYP(net);
1231         struct netstrfns *nf;
1232
1233         nf = libcfs_lnd2netstrfns(lnd);
1234         if (nf == NULL)
1235                 snprintf(buf, buf_size, "<%u:%u>", lnd, nnum);
1236         else if (nnum == 0)
1237                 snprintf(buf, buf_size, "%s", nf->nf_name);
1238         else
1239                 snprintf(buf, buf_size, "%s%u", nf->nf_name, nnum);
1240
1241         return buf;
1242 }
1243 EXPORT_SYMBOL(libcfs_net2str_r);
1244
1245 char *
1246 libcfs_nid2str_r(lnet_nid_t nid, char *buf, size_t buf_size)
1247 {
1248         __u32             addr = LNET_NIDADDR(nid);
1249         __u32             net  = LNET_NIDNET(nid);
1250         __u32             nnum = LNET_NETNUM(net);
1251         __u32             lnd  = LNET_NETTYP(net);
1252         struct netstrfns *nf;
1253
1254         if (nid == LNET_NID_ANY) {
1255                 strncpy(buf, "<?>", buf_size);
1256                 buf[buf_size - 1] = '\0';
1257                 return buf;
1258         }
1259
1260         nf = libcfs_lnd2netstrfns(lnd);
1261         if (nf == NULL) {
1262                 snprintf(buf, buf_size, "%x@<%u:%u>", addr, lnd, nnum);
1263         } else {
1264                 size_t addr_len;
1265
1266                 nf->nf_addr2str(addr, buf, buf_size);
1267                 addr_len = strlen(buf);
1268                 if (nnum == 0)
1269                         snprintf(buf + addr_len, buf_size - addr_len, "@%s",
1270                                  nf->nf_name);
1271                 else
1272                         snprintf(buf + addr_len, buf_size - addr_len, "@%s%u",
1273                                  nf->nf_name, nnum);
1274         }
1275
1276         return buf;
1277 }
1278 EXPORT_SYMBOL(libcfs_nid2str_r);
1279
1280 char *
1281 libcfs_nidstr_r(const struct lnet_nid *nid, char *buf, size_t buf_size)
1282 {
1283         __u32 nnum;
1284         __u32 lnd;
1285         struct netstrfns *nf;
1286
1287         if (LNET_NID_IS_ANY(nid)) {
1288                 strncpy(buf, "<?>", buf_size);
1289                 buf[buf_size - 1] = '\0';
1290                 return buf;
1291         }
1292
1293         nnum = be16_to_cpu(nid->nid_num);
1294         lnd = nid->nid_type;
1295         nf = libcfs_lnd2netstrfns(lnd);
1296         if (nf) {
1297                 size_t addr_len;
1298
1299                 if (nf->nf_addr2str_size)
1300                         nf->nf_addr2str_size(nid->nid_addr, NID_ADDR_BYTES(nid),
1301                                              buf, buf_size);
1302                 else
1303                         nf->nf_addr2str(ntohl(nid->nid_addr[0]), buf, buf_size);
1304                 addr_len = strlen(buf);
1305                 if (nnum == 0)
1306                         snprintf(buf + addr_len, buf_size - addr_len, "@%s",
1307                                  nf->nf_name);
1308                 else
1309                         snprintf(buf + addr_len, buf_size - addr_len, "@%s%u",
1310                                  nf->nf_name, nnum);
1311         } else {
1312                 int l = 0;
1313                 int words = DIV_ROUND_UP(NID_ADDR_BYTES(nid), 4);
1314                 int i;
1315
1316                 for (i = 0; i < words && i < 4; i++)
1317                         l = snprintf(buf+l, buf_size-l, "%s%x",
1318                                      i ? ":" : "", ntohl(nid->nid_addr[i]));
1319                 snprintf(buf+l, buf_size-l, "@<%u:%u>", lnd, nnum);
1320         }
1321
1322         return buf;
1323 }
1324 EXPORT_SYMBOL(libcfs_nidstr_r);
1325
1326 static struct netstrfns *
1327 libcfs_str2net_internal(const char *str, __u32 *net)
1328 {
1329         struct netstrfns *nf = NULL;
1330         int               nob;
1331         unsigned int      netnum;
1332         int               i;
1333
1334         for (i = 0; i < libcfs_nnetstrfns; i++) {
1335                 nf = &libcfs_netstrfns[i];
1336                 if (!strncmp(str, nf->nf_name, strlen(nf->nf_name)))
1337                         break;
1338         }
1339
1340         if (i == libcfs_nnetstrfns)
1341                 return NULL;
1342
1343         nob = strlen(nf->nf_name);
1344
1345         if (strlen(str) == (unsigned int)nob) {
1346                 netnum = 0;
1347         } else {
1348                 if (nf->nf_type == LOLND) /* net number not allowed */
1349                         return NULL;
1350
1351                 str += nob;
1352                 i = strlen(str);
1353                 if (sscanf(str, "%u%n", &netnum, &i) < 1 ||
1354                     i != (int)strlen(str))
1355                         return NULL;
1356         }
1357
1358         *net = LNET_MKNET(nf->nf_type, netnum);
1359         return nf;
1360 }
1361
1362 __u32
1363 libcfs_str2net(const char *str)
1364 {
1365         __u32  net;
1366
1367         if (libcfs_str2net_internal(str, &net) != NULL)
1368                 return net;
1369
1370         return LNET_NET_ANY;
1371 }
1372 EXPORT_SYMBOL(libcfs_str2net);
1373
1374 lnet_nid_t
1375 libcfs_str2nid(const char *str)
1376 {
1377         const char       *sep = strchr(str, '@');
1378         struct netstrfns *nf;
1379         __u32             net;
1380         __u32             addr;
1381
1382         if (sep != NULL) {
1383                 nf = libcfs_str2net_internal(sep + 1, &net);
1384                 if (nf == NULL)
1385                         return LNET_NID_ANY;
1386         } else {
1387                 sep = str + strlen(str);
1388                 net = LNET_MKNET(SOCKLND, 0);
1389                 nf = libcfs_lnd2netstrfns(SOCKLND);
1390                 LASSERT(nf != NULL);
1391         }
1392
1393         if (!nf->nf_str2addr(str, (int)(sep - str), &addr))
1394                 return LNET_NID_ANY;
1395
1396         return LNET_MKNID(net, addr);
1397 }
1398 EXPORT_SYMBOL(libcfs_str2nid);
1399
1400 int
1401 libcfs_strnid(struct lnet_nid *nid, const char *str)
1402 {
1403         const char       *sep = strchr(str, '@');
1404         struct netstrfns *nf;
1405         __u32             net;
1406
1407         if (sep != NULL) {
1408                 nf = libcfs_str2net_internal(sep + 1, &net);
1409                 if (nf == NULL)
1410                         return -EINVAL;
1411         } else {
1412                 if (strcmp(str, "<?>") == 0) {
1413                         memcpy(nid, &LNET_ANY_NID, sizeof(*nid));
1414                         return 0;
1415                 }
1416                 sep = str + strlen(str);
1417                 net = LNET_MKNET(SOCKLND, 0);
1418                 nf = libcfs_lnd2netstrfns(SOCKLND);
1419                 LASSERT(nf != NULL);
1420         }
1421
1422         memset(nid, 0, sizeof(*nid));
1423         nid->nid_type = LNET_NETTYP(net);
1424         nid->nid_num = htons(LNET_NETNUM(net));
1425         if (nf->nf_str2addr_size) {
1426                 size_t asize = 0;
1427
1428                 if (!nf->nf_str2addr_size(str, (int)(sep - str),
1429                                           nid->nid_addr, &asize))
1430                         return -EINVAL;
1431                 nid->nid_size = asize - 4;
1432         } else {
1433                 __u32 addr;
1434
1435                 if (!nf->nf_str2addr(str, (int)(sep - str), &addr))
1436                         return -EINVAL;
1437                 nid->nid_addr[0] = htonl(addr);
1438                 nid->nid_size = 0;
1439         }
1440         return 0;
1441 }
1442 EXPORT_SYMBOL(libcfs_strnid);
1443
1444 char *
1445 libcfs_id2str(struct lnet_process_id id)
1446 {
1447         char *str = libcfs_next_nidstring();
1448
1449         if (id.pid == LNET_PID_ANY) {
1450                 snprintf(str, LNET_NIDSTR_SIZE,
1451                          "LNET_PID_ANY-%s", libcfs_nid2str(id.nid));
1452                 return str;
1453         }
1454
1455         snprintf(str, LNET_NIDSTR_SIZE, "%s%u-%s",
1456                  ((id.pid & LNET_PID_USERFLAG) != 0) ? "U" : "",
1457                  (id.pid & ~LNET_PID_USERFLAG), libcfs_nid2str(id.nid));
1458         return str;
1459 }
1460 EXPORT_SYMBOL(libcfs_id2str);
1461
1462 char *
1463 libcfs_idstr(struct lnet_processid *id)
1464 {
1465         char *str = libcfs_next_nidstring();
1466
1467         if (id->pid == LNET_PID_ANY) {
1468                 snprintf(str, LNET_NIDSTR_SIZE,
1469                          "LNET_PID_ANY-%s", libcfs_nidstr(&id->nid));
1470                 return str;
1471         }
1472
1473         snprintf(str, LNET_NIDSTR_SIZE, "%s%u-%s",
1474                  ((id->pid & LNET_PID_USERFLAG) != 0) ? "U" : "",
1475                  (id->pid & ~LNET_PID_USERFLAG), libcfs_nidstr(&id->nid));
1476         return str;
1477 }
1478 EXPORT_SYMBOL(libcfs_idstr);
1479
1480 int
1481 libcfs_strid(struct lnet_processid *id, const char *str)
1482 {
1483         char *tmp = strchr(str, '-');
1484
1485         id->pid = LNET_PID_LUSTRE;
1486         if (tmp &&
1487             strncmp("LNET_PID_ANY-", str, tmp - str) != 0) {
1488                 char pid[LNET_NIDSTR_SIZE];
1489                 int rc;
1490
1491                 strscpy(pid, str, tmp - str);
1492                 rc = kstrtou32(pid, 10, &id->pid);
1493                 if (rc < 0)
1494                         return rc;
1495                 tmp++;
1496         } else {
1497                 tmp = (char *)str;
1498         }
1499
1500         return libcfs_strnid(&id->nid, tmp);
1501 }
1502 EXPORT_SYMBOL(libcfs_strid);
1503
1504 int
1505 libcfs_str2anynid(lnet_nid_t *nidp, const char *str)
1506 {
1507         if (!strcmp(str, "*")) {
1508                 *nidp = LNET_NID_ANY;
1509                 return 1;
1510         }
1511
1512         *nidp = libcfs_str2nid(str);
1513         return *nidp != LNET_NID_ANY;
1514 }
1515 EXPORT_SYMBOL(libcfs_str2anynid);