]> git.proxmox.com Git - ceph.git/blob - ceph/src/common/addr_parsing.c
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / common / addr_parsing.c
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
15 #include <errno.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #if defined(__FreeBSD__) || defined(_AIX)
20 #include <sys/socket.h>
21 #include <netinet/in.h>
22 #endif
23 #include <netdb.h>
24
25 #define BUF_SIZE 128
26
27 int safe_cat(char **pstr, int *plen, int pos, const char *str2)
28 {
29 int len2 = strlen(str2);
30
31 //printf("safe_cat '%s' max %d pos %d '%s' len %d\n", *pstr, *plen, pos, str2, len2);
32 while (*plen < pos + len2 + 1) {
33 *plen += BUF_SIZE;
34
35 void *_realloc = NULL;
36 if ((_realloc = realloc(*pstr, (size_t)*plen)) == NULL) {
37 printf("Out of memory\n");
38 exit(1);
39 } else {
40 *pstr = (char *)_realloc;
41 }
42 //printf("safe_cat '%s' max %d pos %d '%s' len %d\n", *pstr, *plen, pos, str2, len2);
43 }
44
45 strncpy((*pstr)+pos, str2, len2);
46 (*pstr)[pos+len2] = '\0';
47
48 return pos + len2;
49 }
50
51 char *resolve_addrs(const char *orig_str)
52 {
53 char *new_str;
54 char *tok, *saveptr = NULL;
55 int len, pos;
56 char *buf = strdup(orig_str);
57 const char *delim = ",; ";
58
59 len = BUF_SIZE;
60 new_str = (char *)malloc(len);
61 if (!new_str) {
62 free(buf);
63 return NULL;
64 }
65
66 pos = 0;
67
68 tok = strtok_r(buf, delim, &saveptr);
69
70 while (tok) {
71 struct addrinfo hint;
72 struct addrinfo *res, *ores;
73 char *firstcolon, *lastcolon, *bracecolon;
74 int r;
75 int brackets = 0;
76
77 firstcolon = strchr(tok, ':');
78 lastcolon = strrchr(tok, ':');
79 bracecolon = strstr(tok, "]:");
80
81 char *port_str = 0;
82 if (firstcolon && firstcolon == lastcolon) {
83 /* host:port or a.b.c.d:port */
84 *firstcolon = 0;
85 port_str = firstcolon + 1;
86 } else if (bracecolon) {
87 /* [ipv6addr]:port */
88 port_str = bracecolon + 1;
89 *port_str = 0;
90 port_str++;
91 }
92 if (port_str && !*port_str)
93 port_str = NULL;
94
95 if (*tok == '[' &&
96 tok[strlen(tok)-1] == ']') {
97 tok[strlen(tok)-1] = 0;
98 tok++;
99 brackets = 1;
100 }
101
102 //printf("name '%s' port '%s'\n", tok, port_str);
103
104 memset(&hint, 0, sizeof(hint));
105 hint.ai_family = AF_UNSPEC;
106 hint.ai_socktype = SOCK_STREAM;
107 hint.ai_protocol = IPPROTO_TCP;
108
109 r = getaddrinfo(tok, port_str, &hint, &res);
110 if (r < 0) {
111 printf("server name not found: %s (%s)\n", tok,
112 gai_strerror(r));
113 free(new_str);
114 free(buf);
115 return 0;
116 }
117
118 /* build resolved addr list */
119 ores = res;
120 while (res) {
121 char host[40], port[40];
122 getnameinfo(res->ai_addr, res->ai_addrlen,
123 host, sizeof(host),
124 port, sizeof(port),
125 NI_NUMERICSERV | NI_NUMERICHOST);
126 /*printf(" host %s port %s flags %d family %d socktype %d proto %d sanonname %s\n",
127 host, port,
128 res->ai_flags, res->ai_family, res->ai_socktype, res->ai_protocol,
129 res->ai_canonname);*/
130 if (res->ai_family == AF_INET6)
131 brackets = 1; /* always surround ipv6 addrs with brackets */
132 if (brackets)
133 pos = safe_cat(&new_str, &len, pos, "[");
134 pos = safe_cat(&new_str, &len, pos, host);
135 if (brackets)
136 pos = safe_cat(&new_str, &len, pos, "]");
137 if (port_str) {
138 pos = safe_cat(&new_str, &len, pos, ":");
139 pos = safe_cat(&new_str, &len, pos, port);
140 }
141 res = res->ai_next;
142 if (res)
143 pos = safe_cat(&new_str, &len, pos, ",");
144 }
145 freeaddrinfo(ores);
146
147 tok = strtok_r(NULL, delim, &saveptr);
148 if (tok)
149 pos = safe_cat(&new_str, &len, pos, ",");
150
151 }
152
153 //printf("new_str is '%s'\n", new_str);
154 free(buf);
155 return new_str;
156 }