This source file includes following definitions.
- opal_net_isaddr
- hostname_cleanup
- get_hostname_buffer
- opal_net_finalize
- opal_net_init
- opal_net_prefix2netmask
- opal_net_islocalhost
- opal_net_samenetwork
- opal_net_addr_isipv4public
- opal_net_addr_isipv6linklocal
- opal_net_get_hostname
- opal_net_get_port
- opal_net_init
- opal_net_finalize
- opal_net_prefix2netmask
- opal_net_islocalhost
- opal_net_samenetwork
- opal_net_addr_isipv4public
- opal_net_get_hostname
- opal_net_get_port
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 #include "opal_config.h"
31
32 #include <stdio.h>
33 #include <string.h>
34 #ifdef HAVE_UNISTD_H
35 #include <unistd.h>
36 #endif
37 #include <errno.h>
38 #ifdef HAVE_SYS_TYPES_H
39 #include <sys/types.h>
40 #endif
41 #ifdef HAVE_SYS_SOCKET_H
42 #include <sys/socket.h>
43 #endif
44 #ifdef HAVE_SYS_SOCKIO_H
45 #include <sys/sockio.h>
46 #endif
47 #ifdef HAVE_SYS_IOCTL_H
48 #include <sys/ioctl.h>
49 #endif
50 #ifdef HAVE_NETINET_IN_H
51 #include <netinet/in.h>
52 #endif
53 #ifdef HAVE_ARPA_INET_H
54 #include <arpa/inet.h>
55 #endif
56 #ifdef HAVE_NET_IF_H
57 #include <net/if.h>
58 #endif
59 #ifdef HAVE_NETDB_H
60 #include <netdb.h>
61 #endif
62 #ifdef HAVE_IFADDRS_H
63 #include <ifaddrs.h>
64 #endif
65
66 #include "opal/runtime/opal.h"
67 #include "opal/util/net.h"
68 #include "opal/util/output.h"
69 #include "opal/util/argv.h"
70 #include "opal/util/show_help.h"
71 #include "opal/constants.h"
72 #include "opal/threads/tsd.h"
73 #include "opal/runtime/opal_params.h"
74
75
76 bool opal_net_isaddr(const char *name)
77 {
78 struct addrinfo hint, *res = NULL;
79
80
81 memset(&hint, '\0', sizeof hint);
82
83
84 hint.ai_family = PF_UNSPEC;
85 hint.ai_flags = AI_NUMERICHOST;
86
87 if (0 != getaddrinfo(name, NULL, &hint, &res)) {
88
89 return false;
90 }
91
92
93
94 freeaddrinfo(res);
95 return true;
96 }
97
98 #ifdef HAVE_STRUCT_SOCKADDR_IN
99
100 typedef struct private_ipv4_t {
101 in_addr_t addr;
102 uint32_t netmask_bits;
103 } private_ipv4_t;
104
105 static private_ipv4_t* private_ipv4 = NULL;
106
107 #if OPAL_ENABLE_IPV6
108 static opal_tsd_key_t hostname_tsd_key;
109
110
111 static void
112 hostname_cleanup(void *value)
113 {
114 if (NULL != value) free(value);
115 }
116
117
118 static char*
119 get_hostname_buffer(void)
120 {
121 void *buffer;
122 int ret;
123
124 ret = opal_tsd_getspecific(hostname_tsd_key, &buffer);
125 if (OPAL_SUCCESS != ret) return NULL;
126
127 if (NULL == buffer) {
128 buffer = (void*) malloc((NI_MAXHOST + 1) * sizeof(char));
129 ret = opal_tsd_setspecific(hostname_tsd_key, buffer);
130 }
131
132 return (char*) buffer;
133 }
134 #endif
135
136
137
138
139
140
141
142
143
144
145 static void opal_net_finalize (void)
146 {
147 free(private_ipv4);
148 private_ipv4 = NULL;
149 }
150
151 int
152 opal_net_init(void)
153 {
154 char **args, *arg;
155 uint32_t a, b, c, d, bits, addr;
156 int i, count, found_bad = 0;
157
158 args = opal_argv_split( opal_net_private_ipv4, ';' );
159 if( NULL != args ) {
160 count = opal_argv_count(args);
161 private_ipv4 = (private_ipv4_t*)malloc( (count + 1) * sizeof(private_ipv4_t));
162 if( NULL == private_ipv4 ) {
163 opal_output(0, "Unable to allocate memory for the private addresses array" );
164 opal_argv_free(args);
165 goto do_local_init;
166 }
167 for( i = 0; i < count; i++ ) {
168 arg = args[i];
169
170 (void)sscanf( arg, "%u.%u.%u.%u/%u", &a, &b, &c, &d, &bits );
171
172 if( (a > 255) || (b > 255) || (c > 255) ||
173 (d > 255) || (bits > 32) ) {
174 if (0 == found_bad) {
175 opal_show_help("help-opal-util.txt",
176 "malformed net_private_ipv4",
177 true, args[i]);
178 found_bad = 1;
179 }
180 continue;
181 }
182 addr = (a << 24) | (b << 16) | (c << 8) | d;
183 private_ipv4[i].addr = htonl(addr);
184 private_ipv4[i].netmask_bits = bits;
185 }
186 private_ipv4[i].addr = 0;
187 private_ipv4[i].netmask_bits = 0;
188 opal_argv_free(args);
189 }
190
191 opal_finalize_register_cleanup (opal_net_finalize);
192
193 do_local_init:
194 #if OPAL_ENABLE_IPV6
195 return opal_tsd_key_create(&hostname_tsd_key, hostname_cleanup);
196 #else
197 return OPAL_SUCCESS;
198 #endif
199 }
200
201
202 uint32_t
203 opal_net_prefix2netmask(uint32_t prefixlen)
204 {
205 return htonl (((1 << prefixlen) - 1) << (32 - prefixlen));
206 }
207
208
209 bool
210 opal_net_islocalhost(const struct sockaddr *addr)
211 {
212 switch (addr->sa_family) {
213 case AF_INET:
214 {
215 const struct sockaddr_in *inaddr = (struct sockaddr_in*) addr;
216
217
218 if (0x7F000000 == (0x7F000000 & ntohl(inaddr->sin_addr.s_addr))) {
219 return true;
220 }
221 return false;
222 }
223 break;
224 #if OPAL_ENABLE_IPV6
225 case AF_INET6:
226 {
227 const struct sockaddr_in6 *inaddr = (struct sockaddr_in6*) addr;
228 if (IN6_IS_ADDR_LOOPBACK (&inaddr->sin6_addr)) {
229 return true;
230 }
231 return false;
232 }
233 break;
234 #endif
235
236 default:
237 opal_output(0, "unhandled sa_family %d passed to opal_net_islocalhost",
238 addr->sa_family);
239 return false;
240 break;
241 }
242 }
243
244
245 bool
246 opal_net_samenetwork(const struct sockaddr *addr1,
247 const struct sockaddr *addr2,
248 uint32_t plen)
249 {
250 uint32_t prefixlen;
251
252 if(addr1->sa_family != addr2->sa_family) {
253 return false;
254 }
255
256 switch (addr1->sa_family) {
257 case AF_INET:
258 {
259 if (0 == plen) {
260 prefixlen = 32;
261 } else {
262 prefixlen = plen;
263 }
264 struct sockaddr_in inaddr1, inaddr2;
265
266
267 memcpy(&inaddr1, addr1, sizeof(inaddr1));
268 memcpy(&inaddr2, addr2, sizeof(inaddr2));
269 uint32_t netmask = opal_net_prefix2netmask (prefixlen);
270
271 if((inaddr1.sin_addr.s_addr & netmask) ==
272 (inaddr2.sin_addr.s_addr & netmask)) {
273 return true;
274 }
275 return false;
276 }
277 break;
278 #if OPAL_ENABLE_IPV6
279 case AF_INET6:
280 {
281 struct sockaddr_in6 inaddr1, inaddr2;
282
283
284 memcpy(&inaddr1, addr1, sizeof(inaddr1));
285 memcpy(&inaddr2, addr2, sizeof(inaddr2));
286 struct in6_addr *a6_1 = (struct in6_addr*) &inaddr1.sin6_addr;
287 struct in6_addr *a6_2 = (struct in6_addr*) &inaddr2.sin6_addr;
288
289 if (0 == plen) {
290 prefixlen = 64;
291 } else {
292 prefixlen = plen;
293 }
294 if (64 == prefixlen) {
295
296
297
298
299
300 if (((const uint32_t *) (a6_1))[0] ==
301 ((const uint32_t *) (a6_2))[0] &&
302 ((const uint32_t *) (a6_1))[1] ==
303 ((const uint32_t *) (a6_2))[1]) {
304 return true;
305 }
306 }
307 return false;
308 }
309 break;
310 #endif
311 default:
312 opal_output(0, "unhandled sa_family %d passed to opal_samenetwork",
313 addr1->sa_family);
314 }
315
316 return false;
317 }
318
319
320
321
322
323 bool
324 opal_net_addr_isipv4public(const struct sockaddr *addr)
325 {
326 switch (addr->sa_family) {
327 #if OPAL_ENABLE_IPV6
328 case AF_INET6:
329 return false;
330 #endif
331 case AF_INET:
332 {
333 const struct sockaddr_in *inaddr = (struct sockaddr_in*) addr;
334 int i;
335
336 if( NULL == private_ipv4 ) {
337 return true;
338 }
339
340 for( i = 0; private_ipv4[i].addr != 0; i++ ) {
341 if( private_ipv4[i].addr == (inaddr->sin_addr.s_addr &
342 opal_net_prefix2netmask(private_ipv4[i].netmask_bits)) )
343 return false;
344 }
345
346 }
347 return true;
348 default:
349 opal_output (0,
350 "unhandled sa_family %d passed to opal_net_addr_isipv4public\n",
351 addr->sa_family);
352 }
353
354 return false;
355 }
356
357 bool
358 opal_net_addr_isipv6linklocal(const struct sockaddr *addr)
359 {
360 #if OPAL_ENABLE_IPV6
361 struct sockaddr_in6 if_addr;
362 #endif
363
364 switch (addr->sa_family) {
365 #if OPAL_ENABLE_IPV6
366 case AF_INET6:
367 if_addr.sin6_family = AF_INET6;
368 if (1 != inet_pton(AF_INET6, "fe80::0000", &if_addr.sin6_addr)) {
369 return false;
370 }
371 return opal_net_samenetwork(addr, (struct sockaddr*)&if_addr, 64);
372 #endif
373 case AF_INET:
374 return false;
375 default:
376 opal_output (0,
377 "unhandled sa_family %d passed to opal_net_addr_isipv6linklocal\n",
378 addr->sa_family);
379 }
380
381 return false;
382 }
383
384 char*
385 opal_net_get_hostname(const struct sockaddr *addr)
386 {
387 #if OPAL_ENABLE_IPV6
388 char *name = get_hostname_buffer();
389 int error;
390 socklen_t addrlen;
391 char *p;
392
393 if (NULL == name) {
394 opal_output(0, "opal_sockaddr2str: malloc() failed\n");
395 return NULL;
396 }
397 OPAL_DEBUG_ZERO(*name);
398
399 switch (addr->sa_family) {
400 case AF_INET:
401 addrlen = sizeof (struct sockaddr_in);
402 break;
403 case AF_INET6:
404 #if defined( __NetBSD__)
405
406
407 if(NULL == inet_ntop(AF_INET6, &((struct sockaddr_in6*) addr)->sin6_addr,
408 name, NI_MAXHOST)) {
409 opal_output(0, "opal_sockaddr2str failed with error code %d", errno);
410 return NULL;
411 }
412 return name;
413 #else
414 addrlen = sizeof (struct sockaddr_in6);
415 #endif
416 break;
417 default:
418 return NULL;
419 }
420
421 error = getnameinfo(addr, addrlen,
422 name, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
423
424 if (error) {
425 int err = errno;
426 opal_output (0, "opal_sockaddr2str failed:%s (return code %i)\n",
427 gai_strerror(err), error);
428 return NULL;
429 }
430
431 if (NULL != (p = strrchr(name, '%'))) {
432 *p = '\0';
433 }
434 return name;
435 #else
436 return inet_ntoa(((struct sockaddr_in*) addr)->sin_addr);
437 #endif
438 }
439
440
441 int
442 opal_net_get_port(const struct sockaddr *addr)
443 {
444 switch (addr->sa_family) {
445 case AF_INET:
446 return ntohs(((struct sockaddr_in*) addr)->sin_port);
447 break;
448 #if OPAL_ENABLE_IPV6
449 case AF_INET6:
450 return ntohs(((struct sockaddr_in6*) addr)->sin6_port);
451 break;
452 #endif
453 }
454
455 return -1;
456 }
457
458
459 #else
460
461 int
462 opal_net_init()
463 {
464 return OPAL_SUCCESS;
465 }
466
467
468 int
469 opal_net_finalize()
470 {
471 return OPAL_SUCCESS;
472 }
473
474
475 uint32_t
476 opal_net_prefix2netmask(uint32_t prefixlen)
477 {
478 return 0;
479 }
480
481
482 bool
483 opal_net_islocalhost(const struct sockaddr *addr)
484 {
485 return false;
486 }
487
488
489 bool
490 opal_net_samenetwork(const struct sockaddr *addr1,
491 const struct sockaddr *addr2,
492 uint32_t prefixlen)
493 {
494 return false;
495 }
496
497
498 bool
499 opal_net_addr_isipv4public(const struct sockaddr *addr)
500 {
501 return false;
502 }
503
504
505 char*
506 opal_net_get_hostname(const struct sockaddr *addr)
507 {
508 return NULL;
509 }
510
511
512 int
513 opal_net_get_port(const struct sockaddr *addr)
514 {
515 return -1;
516 }
517
518 #endif