epan: use json_dumper for json outputs.
[metze/wireshark/wip.git] / wsutil / interface.c
1 /* interface.c
2  * Utility functions to get infos from interfaces
3  *
4  * Copyright 2016, Dario Lombardo
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * SPDX-License-Identifier: GPL-2.0-or-later
11  */
12
13 #include "config.h"
14
15 #include "interface.h"
16
17 #include <string.h>
18 #include <wsutil/inet_addr.h>
19
20 #include <sys/types.h>
21
22 #ifdef HAVE_SYS_SOCKET_H
23         #include <sys/socket.h>
24 #endif
25
26 #ifdef HAVE_NETINET_IN_H
27         #include <netinet/in.h>
28 #endif
29
30 #ifdef HAVE_ARPA_INET_H
31         #include <arpa/inet.h>
32 #endif
33
34 #ifdef HAVE_IFADDRS_H
35         #include <ifaddrs.h>
36 #endif
37
38 #ifdef _WIN32
39         #include <winsock2.h>
40         #include <iphlpapi.h>
41         #include <Ws2tcpip.h>
42 #endif
43
44 #define WORKING_BUFFER_SIZE 15000
45
46 #ifdef HAVE_GETIFADDRS
47 static GSList* local_interfaces_to_list_nix(void)
48 {
49         GSList *interfaces = NULL;
50         struct ifaddrs *ifap;
51         struct ifaddrs *ifa;
52         int family;
53         char ip[WS_INET6_ADDRSTRLEN];
54
55         if (getifaddrs(&ifap)) {
56                 goto end;
57         }
58
59         for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
60                 if (ifa->ifa_addr == NULL)
61                         continue;
62
63                 family = ifa->ifa_addr->sa_family;
64
65                 memset(ip, 0x0, WS_INET6_ADDRSTRLEN);
66
67                 switch (family) {
68                         case AF_INET:
69                         {
70                                 struct sockaddr_in *addr4 = (struct sockaddr_in *)ifa->ifa_addr;
71                                 ws_inet_ntop4(&addr4->sin_addr, ip, sizeof(ip));
72                                 break;
73                         }
74
75                         case AF_INET6:
76                         {
77                                 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)ifa->ifa_addr;
78                                 ws_inet_ntop6(&addr6->sin6_addr, ip, sizeof(ip));
79                                 break;
80                         }
81
82                         default:
83                                 break;
84                 }
85
86                 /* skip loopback addresses */
87                 if (!g_strcmp0(ip, "127.0.0.1") || !g_strcmp0(ip, "::1"))
88                         continue;
89
90                 if (*ip) {
91                         interfaces = g_slist_prepend(interfaces, g_strdup(ip));
92                 }
93         }
94         freeifaddrs(ifap);
95 end:
96         return interfaces;
97 }
98 #endif /* HAVE_GETIFADDRS */
99
100 #ifdef _WIN32
101 static GSList* local_interfaces_to_list_win(void)
102 {
103         GSList *interfaces = NULL;
104         PIP_ADAPTER_ADDRESSES pAddresses = NULL;
105         ULONG outBufLen = WORKING_BUFFER_SIZE;
106         ULONG family = AF_UNSPEC;
107         PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
108         PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL;
109         char ip[100];
110         guint iplen = 100;
111
112         pAddresses = (IP_ADAPTER_ADDRESSES *)g_malloc0(outBufLen);
113         if (pAddresses == NULL)
114                 return NULL;
115
116         if (GetAdaptersAddresses(family, 0, NULL, pAddresses, &outBufLen) != NO_ERROR)
117                 goto end;
118
119         pCurrAddresses = pAddresses;
120         while (pCurrAddresses) {
121
122                 for (pUnicast = pCurrAddresses->FirstUnicastAddress; pUnicast != NULL; pUnicast = pUnicast->Next) {
123                         if (pUnicast->Address.lpSockaddr->sa_family == AF_INET) {
124                                 SOCKADDR_IN* sa_in = (SOCKADDR_IN *)pUnicast->Address.lpSockaddr;
125                                 ws_inet_ntop4(&(sa_in->sin_addr), ip, iplen);
126                                 if (!g_strcmp0(ip, "127.0.0.1"))
127                                         continue;
128                                 if (*ip)
129                                         interfaces = g_slist_prepend(interfaces, g_strdup(ip));
130                         }
131                         if (pUnicast->Address.lpSockaddr->sa_family == AF_INET6) {
132                                 SOCKADDR_IN6* sa_in6 = (SOCKADDR_IN6 *)pUnicast->Address.lpSockaddr;
133                                 ws_inet_ntop6(&(sa_in6->sin6_addr), ip, iplen);
134                                 if (!g_strcmp0(ip, "::1"))
135                                         continue;
136                                 if (*ip)
137                                         interfaces = g_slist_prepend(interfaces, g_strdup(ip));
138                         }
139                 }
140                 pCurrAddresses = pCurrAddresses->Next;
141         }
142 end:
143         g_free(pAddresses);
144
145         return interfaces;
146 }
147 #endif /* _WIN32 */
148
149 GSList* local_interfaces_to_list(void)
150 {
151 #if defined(_WIN32)
152         return local_interfaces_to_list_win();
153 #elif defined(HAVE_GETIFADDRS)
154         return local_interfaces_to_list_nix();
155 #else
156         return NULL;
157 #endif
158 }
159
160 /*
161  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
162  *
163  * Local variables:
164  * c-basic-offset: 4
165  * tab-width: 8
166  * indent-tabs-mode: t
167  * End:
168  *
169  * vi: set shiftwidth=4 tabstop=8 noexpandtab:
170  * :indentSize=4:tabSize=8:noTabs=false:
171  */