Statistics
| Branch: | Revision:

pstreamer / src / net_helpers.c @ 662a3ab9

History | View | Annotate | Download (6.56 KB)

1
/*
2
 * Copyright (c) 2010-2011 Luca Abeni
3
 * Copyright (c) 2010-2011 Csaba Kiraly
4
 * Copyright (c) 2017 Luca Baldesi
5
 *
6
 * This file is part of PeerStreamer.
7
 *
8
 * PeerStreamer is free software: you can redistribute it and/or
9
 * modify it under the terms of the GNU Affero General Public License as
10
 * published by the Free Software Foundation, either version 3 of the
11
 * License, or (at your option) any later version.
12
 *
13
 * PeerStreamer is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero
16
 * General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Affero General Public License
19
 * along with PeerStreamer.  If not, see <http://www.gnu.org/licenses/>.
20
 *
21
 */
22

    
23
#include <sys/types.h>
24
#ifndef _WIN32
25
#include <ifaddrs.h>
26
#include <sys/ioctl.h>
27
#include <sys/socket.h>
28
#include <netinet/in.h>
29
#include <arpa/inet.h>
30
#include <net/if.h>     /* For struct ifreq */
31
#include <netdb.h>
32
#include <dbg.h>
33
#else
34
#ifndef _WIN32_WINNT
35
#define _WIN32_WINNT 0x0501 /* WINNT>=0x501 (WindowsXP) for supporting getaddrinfo/freeaddrinfo.*/
36
#endif
37
#include <ws2tcpip.h>
38
#endif
39
#include <unistd.h>
40
#include <stdlib.h>
41
#include <stdio.h>
42
#include <string.h>
43

    
44
#include "net_helpers.h"
45

    
46
char *iface_addr(const char *iface, enum L3PROTOCOL l3)
47
{
48
#ifndef _WIN32
49
    struct ifaddrs *if_addr, *ifap;
50
        int family;
51
        char *host_addr;
52
        int ifcount;
53

    
54
        if (getifaddrs(&if_addr) == -1)
55
        {
56
          perror("getif_addrs");
57
          return NULL;
58
        }
59
        ifcount = 0;
60
        for (ifap = if_addr; ifap != NULL; ifap = ifap->ifa_next)
61
        {
62
                if (ifap->ifa_addr == NULL)
63
                {
64
                        ifcount++;
65
                        continue;
66
                }
67
                family = ifap->ifa_addr->sa_family;
68
                if (l3 == IP4 && family == AF_INET && !strcmp (ifap->ifa_name, iface))
69
                {
70
                        host_addr = malloc((size_t)INET_ADDRSTRLEN);
71
                        if (!host_addr)
72
                        {
73
                                perror("malloc host_addr");
74
                                return NULL;
75
                        }
76
                        if (!inet_ntop(AF_INET, (void *)&(((struct sockaddr_in *)(ifap->ifa_addr))->sin_addr), host_addr, INET_ADDRSTRLEN))
77
                        {
78
                                free(host_addr);
79
                                perror("inet_ntop");
80
                                return NULL;
81
                        }
82
                        break;
83
                }
84
                if (l3 == IP6 && family == AF_INET6 && !strcmp (ifap->ifa_name, iface))
85
                {
86
                        host_addr = malloc((size_t)INET6_ADDRSTRLEN);
87
                        if (!host_addr)
88
                        {
89
                                perror("malloc host_addr");
90
                                return NULL;
91
                        }
92
                        if (!inet_ntop(AF_INET6, (void *)&(((struct sockaddr_in6 *)(ifap->ifa_addr))->sin6_addr), host_addr, INET6_ADDRSTRLEN))
93
                        {
94
                                free(host_addr);
95
                                perror("inet_ntop");
96
                                return NULL;
97
                        }
98
                        break;
99
                }
100

    
101
        }
102
        freeifaddrs(if_addr);
103
        return host_addr;
104
#else
105
    char *res;
106
    if(iface != NULL && strcmp(iface, "lo") == 0)
107
    {
108
          switch (l3)
109
          {
110
                case IP4:
111
                        res = malloc (INET_ADDRSTRLEN);
112
                        strcpy(res, "127.0.0.1");
113
                  break;
114
                case IP6:
115
                        res = malloc (INET6_ADDRSTRLEN);
116
                        strcpy(res, "::1");
117
                  break;
118
                default:
119
                  return NULL;
120
                  break;
121
          }
122
      return res;
123
    }
124
    if(iface != NULL && inet_addr(iface) != INADDR_NONE) return strdup(iface);
125
    return default_ip_addr();
126
#endif
127
}
128

    
129
const char *hostname_ip_addr()
130
{
131
#ifndef _WIN32
132
  const char *ip;
133
  char hostname[256];
134
  struct addrinfo * result;
135
  struct addrinfo * res;
136
  int error;
137

    
138
  if (gethostname(hostname, sizeof hostname) < 0) {
139
    dtprintf("can't get hostname\n");
140
    return NULL;
141
  }
142
  dtprintf("hostname is: %s ...", hostname);
143

    
144
  /* resolve the domain name into a list of addresses */
145
  error = getaddrinfo(hostname, NULL, NULL, &result);
146
  if (error != 0) {
147
    dtprintf("can't resolve IP: %s\n", gai_strerror(error));
148
    return NULL;
149
  }
150

    
151
  /* loop over all returned results and do inverse lookup */
152
  for (res = result; res != NULL; res = res->ai_next) {
153
    ip = inet_ntoa(((struct sockaddr_in*)res->ai_addr)->sin_addr);
154
    dtprintf("IP is: %s ...", ip);
155
    if ( strncmp("127.", ip, 4) == 0) {
156
      dtprintf(":( ...");
157
      ip = NULL;
158
    } else {
159
      break;
160
    }
161
  }
162
  freeaddrinfo(result);
163

    
164
  return ip;
165
#else
166
  const char *ip;
167
  char hostname[256];
168
  struct addrinfo hints, *result, *res;
169
  int error;
170
  ip = malloc (INET6_ADDRSTRLEN);
171
  if (!ip)
172
  {
173
          perror("hostname_ip_addr");
174
          return NULL;
175
  }
176
  dtprintf(stderr, "Trying to guess IP ...");
177
  if (gethostname(hostname, sizeof hostname) < 0) {
178
    dtprintf(stderr, "can't get hostname\n");
179
    return NULL;
180
  }
181
  memset(&hints, 0, sizeof(hints));
182
  hints.ai_flags = AI_CANONNAME;
183
  hints.ai_family = AF_UNSPEC;
184
  hints.ai_protocol = IPPROTO_TCP;
185

    
186
  dtprintf(stderr, "hostname is: %s ...\n", hostname);
187
  error = getaddrinfo(hostname, NULL, NULL, &result);
188
  if (error != 0)
189
  {
190
    dtprintf(stderr, "can't resolve IP: %s\n", gai_strerror(error));
191
    return NULL;
192
  }
193

    
194
  for (res = result; res != NULL ; res = res->ai_next)
195
  {
196
      dtprintf(stderr, "Address Family is %d...", res->ai_family);
197
          if ( (res->ai_family == AF_INET && l3 == IP4) ||
198
                          (res->ai_family == AF_INET6 && l3 == IP6))
199
          {
200
                  if (res->ai_family == AF_INET)
201
                  {
202
                          inet_ntop(res->ai_family, &((const struct sockaddr_in *)(res->ai_addr))->sin_addr, ip, INET6_ADDRSTRLEN);
203
                  }
204
                  else
205
                  {
206
                          inet_ntop(res->ai_family, &((const struct sockaddr_in6 *)(res->ai_addr))->sin6_addr, ip, INET6_ADDRSTRLEN);
207
                  }
208
                  dtprintf(stderr, "IP is: %s ...", ip);
209
                  if ( (l3 == AF_INET && strncmp("127.", ip, 4) == 0) ||
210
                                  (l3 == AF_INET6 && strncmp("::1", ip, 3) == 0)) {
211
                          dtprintf(stderr, ":( ...");
212
                          memset (&ip, 0, INET6_ADDRSTRLEN);
213
                  }
214
                  else break;
215
          }
216
  }
217
  freeaddrinfo(result);
218

    
219
  return ip;
220
#endif
221
}
222

    
223
char *autodetect_ip_address(enum L3PROTOCOL l3) {
224
#ifdef __linux__
225

    
226
        char iface[IFNAMSIZ] = "";
227
        char line[128] = "x";
228

    
229
        FILE *r = fopen("/proc/net/route", "r");
230
        if (!r) return NULL;
231

    
232
        while (1) {
233
                char dst[32];
234
                char ifc[IFNAMSIZ];
235

    
236
                fgets(line, 127, r);
237
                if (feof(r)) break;
238
                if ((sscanf(line, "%s\t%s", iface, dst) == 2) && !strcpy(dst, "00000000")) {
239
                        strcpy(iface, ifc);
240
                         break;
241
                }
242
        }
243
        fclose(r);
244

    
245
        return iface_addr(iface, l3);
246
#else
247
                return hostname_ip_addr();
248
#endif
249
}
250

    
251
char *default_ip_addr(enum L3PROTOCOL l3)
252
{
253
  char *ip = NULL;
254

    
255
  dtprintf("Trying to guess IP ...");
256

    
257
  ip = autodetect_ip_address(l3);
258

    
259
  if (!ip) {
260
    dtprintf("cannot detect IP!\n");
261
    return NULL;
262
  }
263
  dtprintf("IP is: %s ...\n", ip);
264

    
265
  return ip;
266
}
267

    
268
char * nodeid_static_str(const struct nodeID * id)
269
/* WARNING: extremely error prone (but convenient)
270
 * This function converts on-the-fly a nodeID to a printable string without the need
271
 * of allocating or freeing memory. It works with statically allocated memory in the
272
 * stuck so it is NOT thread safe and CANNOT be used twice in the same function call.
273
 */
274
{
275
        static char buff[80];
276
        node_addr(id, buff, 80);
277
        return buff;
278
}