]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | /* | |
4 | * Ceph - scalable distributed file system | |
5 | * | |
6 | * Copyright (C) 2011 New Dream Network | |
7 | * | |
8 | * This is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License version 2.1, as published by the Free Software | |
11 | * Foundation. See file COPYING. | |
12 | * | |
13 | */ | |
14 | ||
7c673cae FG |
15 | #include <stdio.h> |
16 | #include <stdlib.h> | |
17 | #include <string.h> | |
18 | #if defined(__FreeBSD__) || defined(_AIX) | |
19 | #include <sys/socket.h> | |
20 | #include <netinet/in.h> | |
21 | #endif | |
22 | #include <netdb.h> | |
23 | ||
24 | #define BUF_SIZE 128 | |
f67539c2 | 25 | #define ROUND_UP_128(x) (-(-(x) & -128)) |
7c673cae | 26 | |
f67539c2 | 27 | int safe_cat(char **pstr, int *plen, int pos, const char *src) |
7c673cae | 28 | { |
f67539c2 TL |
29 | size_t len2 = strlen(src); |
30 | size_t new_size = pos + len2 + 1; | |
31 | if (*plen < new_size) { | |
32 | size_t round_up = ROUND_UP_128(new_size); | |
33 | void* p = realloc(*pstr, round_up); | |
34 | if (!p) { | |
7c673cae FG |
35 | printf("Out of memory\n"); |
36 | exit(1); | |
37 | } else { | |
f67539c2 | 38 | *pstr = p; |
7c673cae | 39 | } |
7c673cae | 40 | } |
f67539c2 | 41 | memcpy(*pstr + pos, src, len2 + 1); |
7c673cae FG |
42 | return pos + len2; |
43 | } | |
44 | ||
45 | char *resolve_addrs(const char *orig_str) | |
46 | { | |
11fdf7f2 TL |
47 | int len = BUF_SIZE; |
48 | char *new_str = (char *)malloc(len); | |
7c673cae | 49 | |
7c673cae | 50 | if (!new_str) { |
7c673cae FG |
51 | return NULL; |
52 | } | |
53 | ||
11fdf7f2 TL |
54 | char *saveptr = NULL; |
55 | char *buf = strdup(orig_str); | |
56 | const char *delim = ",; "; | |
57 | ||
58 | char *tok = strtok_r(buf, delim, &saveptr); | |
7c673cae | 59 | |
11fdf7f2 | 60 | int pos = 0; |
7c673cae FG |
61 | |
62 | while (tok) { | |
63 | struct addrinfo hint; | |
64 | struct addrinfo *res, *ores; | |
65 | char *firstcolon, *lastcolon, *bracecolon; | |
66 | int r; | |
67 | int brackets = 0; | |
68 | ||
69 | firstcolon = strchr(tok, ':'); | |
70 | lastcolon = strrchr(tok, ':'); | |
71 | bracecolon = strstr(tok, "]:"); | |
72 | ||
73 | char *port_str = 0; | |
74 | if (firstcolon && firstcolon == lastcolon) { | |
75 | /* host:port or a.b.c.d:port */ | |
76 | *firstcolon = 0; | |
77 | port_str = firstcolon + 1; | |
78 | } else if (bracecolon) { | |
79 | /* [ipv6addr]:port */ | |
80 | port_str = bracecolon + 1; | |
81 | *port_str = 0; | |
82 | port_str++; | |
83 | } | |
84 | if (port_str && !*port_str) | |
85 | port_str = NULL; | |
86 | ||
87 | if (*tok == '[' && | |
88 | tok[strlen(tok)-1] == ']') { | |
89 | tok[strlen(tok)-1] = 0; | |
90 | tok++; | |
91 | brackets = 1; | |
92 | } | |
93 | ||
94 | //printf("name '%s' port '%s'\n", tok, port_str); | |
95 | ||
92f5a8d4 | 96 | // FIPS zeroization audit 20191115: this memset is fine. |
7c673cae FG |
97 | memset(&hint, 0, sizeof(hint)); |
98 | hint.ai_family = AF_UNSPEC; | |
99 | hint.ai_socktype = SOCK_STREAM; | |
100 | hint.ai_protocol = IPPROTO_TCP; | |
101 | ||
102 | r = getaddrinfo(tok, port_str, &hint, &res); | |
103 | if (r < 0) { | |
104 | printf("server name not found: %s (%s)\n", tok, | |
105 | gai_strerror(r)); | |
106 | free(new_str); | |
107 | free(buf); | |
108 | return 0; | |
109 | } | |
110 | ||
111 | /* build resolved addr list */ | |
112 | ores = res; | |
113 | while (res) { | |
114 | char host[40], port[40]; | |
115 | getnameinfo(res->ai_addr, res->ai_addrlen, | |
116 | host, sizeof(host), | |
117 | port, sizeof(port), | |
118 | NI_NUMERICSERV | NI_NUMERICHOST); | |
119 | /*printf(" host %s port %s flags %d family %d socktype %d proto %d sanonname %s\n", | |
120 | host, port, | |
121 | res->ai_flags, res->ai_family, res->ai_socktype, res->ai_protocol, | |
122 | res->ai_canonname);*/ | |
123 | if (res->ai_family == AF_INET6) | |
124 | brackets = 1; /* always surround ipv6 addrs with brackets */ | |
125 | if (brackets) | |
126 | pos = safe_cat(&new_str, &len, pos, "["); | |
127 | pos = safe_cat(&new_str, &len, pos, host); | |
128 | if (brackets) | |
129 | pos = safe_cat(&new_str, &len, pos, "]"); | |
130 | if (port_str) { | |
131 | pos = safe_cat(&new_str, &len, pos, ":"); | |
132 | pos = safe_cat(&new_str, &len, pos, port); | |
133 | } | |
134 | res = res->ai_next; | |
135 | if (res) | |
136 | pos = safe_cat(&new_str, &len, pos, ","); | |
137 | } | |
138 | freeaddrinfo(ores); | |
139 | ||
140 | tok = strtok_r(NULL, delim, &saveptr); | |
141 | if (tok) | |
142 | pos = safe_cat(&new_str, &len, pos, ","); | |
143 | ||
144 | } | |
145 | ||
146 | //printf("new_str is '%s'\n", new_str); | |
147 | free(buf); | |
148 | return new_str; | |
149 | } |