Whamcloud - gitweb
LU-14199 sec: find policy version in use for sepol
[fs/lustre-release.git] / lustre / utils / nidlist.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Copyright (c) 2014, Intel Corporation.
27  */
28 /*
29  * This file is part of Lustre, http://www.lustre.org/
30  *
31  * lustre/utils/nidlist.c
32  *
33  * Author: Jim Garlick <garlick@llnl.gov>
34  */
35
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include <ctype.h>
40 #include <netdb.h>
41 #include <netinet/in.h>
42 #include <sys/socket.h>
43
44 #include "nidlist.h"
45
46 struct nl_struct {
47         char **nids;
48         int len;
49         int count;
50 };
51 #define NL_CHUNK        64
52
53 static void nl_oom(void)
54 {
55         fprintf(stderr, "%s: out of memory\n", prog);
56         exit(1);
57 }
58
59 NIDList nl_create(void)
60 {
61         struct nl_struct *nl;
62
63         nl = malloc(sizeof(struct nl_struct));
64         if (!nl)
65                 nl_oom();
66         nl->len = NL_CHUNK;
67         nl->nids = malloc(nl->len * sizeof(char *));
68         if (!nl->nids)
69                 nl_oom();
70         nl->count = 0;
71
72         return nl;
73 }
74
75 void nl_destroy(NIDList nl)
76 {
77         int i;
78
79         for (i = 0; i < nl->count; i++)
80                 free(nl->nids[i]);
81         free(nl->nids);
82         free(nl);
83 }
84
85 static void nl_grow(NIDList nl, int n)
86 {
87         nl->len += n;
88         nl->nids = realloc(nl->nids, nl->len * sizeof(char *));
89         if (!nl->nids)
90                 nl_oom();
91 }
92
93 void nl_add(NIDList nl, char *nid)
94 {
95         char *cp;
96
97         cp = strdup(nid);
98         if (!cp)
99                 nl_oom();
100         if (nl->count == nl->len)
101                 nl_grow(nl, NL_CHUNK);
102         nl->nids[nl->count++] = cp;
103 }
104
105 int nl_count(NIDList nl)
106 {
107         return nl->count;
108 }
109
110 static char *nl_nid_addr(char *nid)
111 {
112         char *addr, *p;
113
114         addr = strdup(nid);
115         if (!addr)
116                 nl_oom();
117         p = strchr(addr, '@');
118         if (p)
119                 *p = '\0';
120
121         return addr;
122 }
123
124 static int nl_nid_parse_addr(char *addr)
125 {
126         int o;
127
128         for (o = strlen(addr); o > 0; o--)
129                 if (!isdigit(addr[o - 1]))
130                         break;
131
132         return o;
133 }
134
135 static int nl_cmp_addr(char *nid1, char *nid2, int *cflagp)
136 {
137         char *p1 = nl_nid_addr(nid1);
138         char *p2 = nl_nid_addr(nid2);
139         int res, o1, o2, cflag = 0;
140
141         o1 = nl_nid_parse_addr(p1);
142         o2 = nl_nid_parse_addr(p2);
143
144         res = strncmp(p1, p2, o1);
145         if (o1 == o2 && res == 0) {
146                 res = strtoul(&p1[o1], NULL, 10) - strtoul(&p2[o2], NULL, 10);
147                 if (cflagp && strlen(&p1[o1]) > 0 && strlen(&p2[o2]) > 0)
148                         cflag = 1;
149         } else
150                 res = strcmp(p1, p2);
151         free(p1);
152         free(p2);
153         if (cflagp)
154                 *cflagp = cflag;
155         return res;
156 }
157
158 static int nl_cmp_lnet(char *nid1, char *nid2)
159 {
160         char *s1 = strchr(nid1, '@');
161         char *s2 = strchr(nid2, '@');
162
163         return strcmp(s1 ? s1 + 1 : "", s2 ? s2 + 1 : "");
164 }
165
166 static int nl_cmp(const void *p1, const void *p2)
167 {
168         int res;
169
170         res = nl_cmp_lnet(*(char **)p1, *(char **)p2);
171         if (res == 0)
172                 res = nl_cmp_addr(*(char **)p1, *(char **)p2, NULL);
173         return res;
174 }
175
176 void nl_sort(NIDList nl)
177 {
178         qsort(nl->nids, nl->count, sizeof(char *), nl_cmp);
179 }
180
181 void nl_uniq(NIDList nl)
182 {
183         int i, j;
184
185         for (i = 1; i < nl->count; i++) {
186                 if (!strcmp(nl->nids[i], nl->nids[i - 1])) {
187                         free(nl->nids[i]);
188                         for (j = i; j < nl->count - 1; j++)
189                                 nl->nids[j] = nl->nids[j + 1];
190                         nl->count--;
191                         i--;
192                 }
193         }
194 }
195
196 static char *nl_nid_lookup_ipaddr(char *nid)
197 {
198         struct addrinfo *ai, *aip;
199         char name[NI_MAXHOST] = "";
200         char *p, *addr, *lnet = NULL, *res = NULL;
201         int len, x;
202
203         addr = nl_nid_addr(nid);
204         if (sscanf(addr, "%d.%d.%d.%d", &x, &x, &x, &x) == 4) {
205                 p = strchr(nid, '@');
206                 if (p)
207                         lnet = p + 1;
208                 if (getaddrinfo(addr, NULL, NULL, &ai) == 0) {
209                         for (aip = ai; aip != NULL; aip = aip->ai_next) {
210                                 if (getnameinfo(aip->ai_addr, aip->ai_addrlen,
211                                     name, sizeof(name), NULL, 0,
212                                     NI_NAMEREQD | NI_NOFQDN) == 0) {
213                                         p = strchr(name, '.');
214                                         if (p)
215                                                 *p = '\0';
216                                         len = strlen(name) + 2;
217                                         if (lnet != NULL)
218                                                 len += strlen(lnet);
219                                         res = malloc(len);
220                                         if (!res)
221                                                 nl_oom();
222                                         if (lnet != NULL)
223                                                 snprintf(res, len, "%s@%s",
224                                                          name, lnet);
225                                         else
226                                                 snprintf(res, len, "%s", name);
227                                         break;
228                                 }
229                         }
230                         freeaddrinfo(ai);
231                 }
232         }
233         free(addr);
234
235         return res;
236 }
237
238 void nl_lookup_ip(NIDList nl)
239 {
240         int i;
241         char *new;
242
243         for (i = 0; i < nl->count; i++) {
244                 new = nl_nid_lookup_ipaddr(nl->nids[i]);
245                 if (new) {
246                         free(nl->nids[i]);
247                         nl->nids[i] = new;
248                 }
249         }
250 }
251
252 char *nl_string(NIDList nl, char *sep)
253 {
254         int seplen = strlen(sep);
255         int i, len = 1;
256         char *s;
257
258         for (i = 0; i < nl->count; i++)
259                 len += strlen(nl->nids[i]) + seplen;
260         s = malloc(len);
261         if (!s)
262                 nl_oom();
263         s[0] = '\0';
264         for (i = 0; i < nl->count; i++) {
265                 int cur = strlen(s);
266                 snprintf(s + cur, len - cur, "%s%s",
267                          i > 0 ? sep : "", nl->nids[i]);
268         }
269         return s;
270 }
271
272 static void nl_strxcat(char *s, char **nids, int len, const int max_len)
273 {
274         int i, o, lastn = 0;
275         char *base, *p, *lnet = NULL, *savedn = NULL;
276
277         p = strchr(nids[0], '@');
278         if (p)
279                 lnet = p + 1;
280         base = nl_nid_addr(nids[0]);
281         o = nl_nid_parse_addr(base);
282         base[o] = '\0';
283         for (i = 0; i < len; i++) {
284                 char *addr = nl_nid_addr(nids[i]);
285                 int n = strtoul(&addr[o], NULL, 10);
286
287                 if (i == 0)
288                         snprintf(s + strlen(s), max_len, "%s[%s", base,
289                                  &addr[o]);
290                 else if (i < len) {
291                         if (n == lastn + 1) {
292                                 if (savedn)
293                                         free(savedn);
294                                 savedn = strdup(&addr[o]);
295                                 if (!savedn)
296                                         nl_oom();
297                         } else {
298                                 if (savedn) {
299                                         snprintf(s + strlen(s),
300                                                  max_len - strlen(s),
301                                                  "-%s", savedn);
302                                         free(savedn);
303                                         savedn = NULL;
304                                 }
305                                 snprintf(s + strlen(s), max_len - strlen(s),
306                                          ",%s", &addr[o]);
307                         }
308                 }
309                 if (i == len - 1) {
310                         if (savedn) {
311                                 snprintf(s + strlen(s), max_len - strlen(s),
312                                          "-%s", savedn);
313                                 free(savedn);
314                         }
315                         strncat(s, "]", max_len - strlen(s));
316                         if (lnet)
317                                 snprintf(s + strlen(s), max_len - strlen(s),
318                                          "@%s", lnet);
319                 }
320                 free(addr);
321                 lastn = n;
322         }
323         free(base);
324 }
325
326 char *nl_xstring(NIDList nl, char *sep)
327 {
328         int seplen = strlen(sep);
329         int cflag, i, j, len = 1;
330         char *s;
331
332         for (i = 0; i < nl->count; i++)
333                 len += strlen(nl->nids[i]) + seplen;
334         s = malloc(len);
335         if (!s)
336                 nl_oom();
337         s[0] = '\0';
338         for (i = 0; i < nl->count; i++) {
339                 if (i > 0)
340                         strncat(s, sep, len);
341                 for (j = i + 1; j < nl->count; j++) {
342                         if (nl_cmp_lnet(nl->nids[i], nl->nids[j]) != 0)
343                                 break;
344                         (void)nl_cmp_addr(nl->nids[i], nl->nids[j], &cflag);
345                         if (!cflag)
346                                 break;
347                 }
348                 if (j - i > 1)
349                         nl_strxcat(s, &nl->nids[i], j - i, len);
350                 else
351                         strncat(s, nl->nids[i], len);
352                 i += j - i - 1;
353         }
354         return s;
355 }