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