2 * Routines for getting interface information from dumpcap
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
33 #ifdef HAVE_ARPA_INET_H
34 #include <arpa/inet.h>
37 #ifdef HAVE_SYS_SOCKET_H
38 #include <sys/socket.h> /* needed to define AF_ values on UNIX */
41 #ifdef HAVE_WINSOCK2_H
42 #include <winsock2.h> /* needed to define AF_ values on Windows */
45 #ifdef NEED_INET_V6DEFS_H
46 # include "wsutil/inet_v6defs.h"
51 #include "capture_opts.h"
52 #include "capture_session.h"
53 #include "capture_sync.h"
56 #include "capture_ifinfo.h"
58 #ifdef HAVE_PCAP_REMOTE
59 static GList
*remote_interface_list
= NULL
;
61 static void append_remote_list(GList
*iflist
)
65 if_addr_t
*if_addr
, *temp_addr
;
66 if_info_t
*if_info
, *temp
;
68 for (rlist
= g_list_nth(remote_interface_list
, 0); rlist
!= NULL
; rlist
= g_list_next(rlist
)) {
69 if_info
= (if_info_t
*)rlist
->data
;
70 temp
= g_malloc0(sizeof(if_info_t
));
71 temp
->name
= g_strdup(if_info
->name
);
72 temp
->friendly_name
= g_strdup(if_info
->friendly_name
);
73 temp
->vendor_description
= g_strdup(if_info
->vendor_description
);
74 for (list
= g_slist_nth(if_info
->addrs
, 0); list
!= NULL
; list
= g_slist_next(list
)) {
75 temp_addr
= g_malloc0(sizeof(if_addr_t
));
76 if_addr
= (if_addr_t
*)list
->data
;
78 temp_addr
->ifat_type
= if_addr
->ifat_type
;
79 if (temp_addr
->ifat_type
== IF_AT_IPv4
) {
80 temp_addr
->addr
.ip4_addr
= if_addr
->addr
.ip4_addr
;
82 memcpy(temp_addr
->addr
.ip6_addr
, if_addr
->addr
.ip6_addr
, sizeof(if_addr
->addr
));
89 temp
->addrs
= g_slist_append(temp
->addrs
, temp_addr
);
92 temp
->loopback
= if_info
->loopback
;
93 iflist
= g_list_append(iflist
, temp
);
99 * Fetch the interface list from a child process (dumpcap).
101 * @return A GList containing if_info_t structs if successful, NULL (with err and possibly err_str set) otherwise.
105 /* XXX - We parse simple text output to get our interface list. Should
106 * we use "real" data serialization instead, e.g. via XML? */
108 capture_interface_list(int *err
, char **err_str
, void (*update_cb
)(void))
111 GList
*if_list
= NULL
;
113 gchar
*data
, *primary_msg
, *secondary_msg
;
114 gchar
**raw_list
, **if_parts
, **addr_parts
;
119 g_log(LOG_DOMAIN_CAPTURE
, G_LOG_LEVEL_MESSAGE
, "Capture Interface List ...");
121 /* Try to get our interface list */
122 ret
= sync_interface_list_open(&data
, &primary_msg
, &secondary_msg
, update_cb
);
124 g_log(LOG_DOMAIN_CAPTURE
, G_LOG_LEVEL_MESSAGE
, "Capture Interface List failed!");
126 *err_str
= primary_msg
;
130 g_free(secondary_msg
);
131 *err
= CANT_GET_INTERFACE_LIST
;
135 /* Split our lines */
137 raw_list
= g_strsplit(data
, "\r\n", 0);
139 raw_list
= g_strsplit(data
, "\n", 0);
143 for (i
= 0; raw_list
[i
] != NULL
; i
++) {
144 if_parts
= g_strsplit(raw_list
[i
], "\t", 6);
145 if (if_parts
[0] == NULL
|| if_parts
[1] == NULL
|| if_parts
[2] == NULL
||
146 if_parts
[3] == NULL
|| if_parts
[4] == NULL
|| if_parts
[5] == NULL
) {
147 g_strfreev(if_parts
);
151 /* Number followed by the name, e.g "1. eth0" */
152 name
= strchr(if_parts
[0], ' ');
156 g_strfreev(if_parts
);
160 if_info
= g_new0(if_info_t
,1);
161 if_info
->name
= g_strdup(name
);
162 if (strlen(if_parts
[1]) > 0)
163 if_info
->vendor_description
= g_strdup(if_parts
[1]);
164 if (strlen(if_parts
[2]) > 0)
165 if_info
->friendly_name
= g_strdup(if_parts
[2]);
166 if_info
->type
= (interface_type
)(int)strtol(if_parts
[3], NULL
, 10);
167 addr_parts
= g_strsplit(if_parts
[4], ",", 0);
168 for (j
= 0; addr_parts
[j
] != NULL
; j
++) {
169 if_addr
= g_new0(if_addr_t
,1);
170 if (inet_pton(AF_INET
, addr_parts
[j
], &if_addr
->addr
.ip4_addr
) > 0) {
171 if_addr
->ifat_type
= IF_AT_IPv4
;
172 } else if (inet_pton(AF_INET6
, addr_parts
[j
],
173 &if_addr
->addr
.ip6_addr
) > 0) {
174 if_addr
->ifat_type
= IF_AT_IPv6
;
180 if_info
->addrs
= g_slist_append(if_info
->addrs
, if_addr
);
183 if (strcmp(if_parts
[5], "loopback") == 0)
184 if_info
->loopback
= TRUE
;
185 g_strfreev(if_parts
);
186 g_strfreev(addr_parts
);
187 if_list
= g_list_append(if_list
, if_info
);
189 g_strfreev(raw_list
);
191 /* Check to see if we built a list */
192 if (if_list
== NULL
) {
193 *err
= NO_INTERFACES_FOUND
;
195 *err_str
= g_strdup("No interfaces found");
197 #ifdef HAVE_PCAP_REMOTE
198 if (remote_interface_list
&& g_list_length(remote_interface_list
) > 0) {
199 append_remote_list(if_list
);
205 /* XXX - We parse simple text output to get our interface list. Should
206 * we use "real" data serialization instead, e.g. via XML? */
208 capture_get_if_capabilities(const gchar
*ifname
, gboolean monitor_mode
,
209 char **err_str
, void (*update_cb
)(void))
211 if_capabilities_t
*caps
;
212 GList
*linktype_list
= NULL
;
214 gchar
*data
, *primary_msg
, *secondary_msg
;
215 gchar
**raw_list
, **lt_parts
;
216 data_link_info_t
*data_link_info
;
218 g_log(LOG_DOMAIN_CAPTURE
, G_LOG_LEVEL_MESSAGE
, "Capture Interface Capabilities ...");
220 /* Try to get our interface list */
221 err
= sync_if_capabilities_open(ifname
, monitor_mode
, &data
,
222 &primary_msg
, &secondary_msg
, update_cb
);
224 g_log(LOG_DOMAIN_CAPTURE
, G_LOG_LEVEL_MESSAGE
, "Capture Interface Capabilities failed!");
226 *err_str
= primary_msg
;
230 g_free(secondary_msg
);
234 /* Split our lines */
236 raw_list
= g_strsplit(data
, "\r\n", 0);
238 raw_list
= g_strsplit(data
, "\n", 0);
243 * First line is 0 if monitor mode isn't supported, 1 if it is.
245 if (raw_list
[0] == NULL
|| *raw_list
[0] == '\0') {
246 g_log(LOG_DOMAIN_CAPTURE
, G_LOG_LEVEL_MESSAGE
, "Capture Interface Capabilities returned no information!");
248 *err_str
= g_strdup("Dumpcap returned no interface capability information");
254 * Allocate the interface capabilities structure.
256 caps
= (if_capabilities_t
*)g_malloc(sizeof *caps
);
257 switch (*raw_list
[0]) {
260 caps
->can_set_rfmon
= FALSE
;
264 caps
->can_set_rfmon
= TRUE
;
268 g_log(LOG_DOMAIN_CAPTURE
, G_LOG_LEVEL_MESSAGE
, "Capture Interface Capabilities returned bad information!");
270 *err_str
= g_strdup_printf("Dumpcap returned \"%s\" for monitor-mode capability",
278 * The rest are link-layer types.
280 for (i
= 1; raw_list
[i
] != NULL
; i
++) {
281 /* ...and what if the interface name has a tab in it, Mr. Clever Programmer? */
282 lt_parts
= g_strsplit(raw_list
[i
], "\t", 3);
283 if (lt_parts
[0] == NULL
|| lt_parts
[1] == NULL
|| lt_parts
[2] == NULL
) {
284 g_strfreev(lt_parts
);
288 data_link_info
= g_new(data_link_info_t
,1);
289 data_link_info
->dlt
= (int) strtol(lt_parts
[0], NULL
, 10);
290 data_link_info
->name
= g_strdup(lt_parts
[1]);
291 if (strcmp(lt_parts
[2], "(not supported)") != 0)
292 data_link_info
->description
= g_strdup(lt_parts
[2]);
294 data_link_info
->description
= NULL
;
296 linktype_list
= g_list_append(linktype_list
, data_link_info
);
298 g_strfreev(raw_list
);
300 /* Check to see if we built a list */
301 if (linktype_list
== NULL
) {
304 *err_str
= g_strdup("Dumpcap returned no link-layer types");
308 caps
->data_link_types
= linktype_list
;
312 #ifdef HAVE_PCAP_REMOTE
313 void add_interface_to_remote_list(if_info_t
*if_info
)
316 if_addr_t
*if_addr
, *temp_addr
;
318 if_info_t
*temp
= g_malloc0(sizeof(if_info_t
));
319 temp
->name
= g_strdup(if_info
->name
);
320 temp
->friendly_name
= g_strdup(if_info
->friendly_name
);
321 temp
->vendor_description
= g_strdup(if_info
->vendor_description
);
322 for (list
= g_slist_nth(if_info
->addrs
, 0); list
!= NULL
; list
= g_slist_next(list
)) {
323 temp_addr
= g_malloc0(sizeof(if_addr_t
));
324 if_addr
= (if_addr_t
*)list
->data
;
326 temp_addr
->ifat_type
= if_addr
->ifat_type
;
327 if (temp_addr
->ifat_type
== IF_AT_IPv4
) {
328 temp_addr
->addr
.ip4_addr
= if_addr
->addr
.ip4_addr
;
330 memcpy(temp_addr
->addr
.ip6_addr
, if_addr
->addr
.ip6_addr
, sizeof(if_addr
->addr
));
337 temp
->addrs
= g_slist_append(temp
->addrs
, temp_addr
);
340 temp
->loopback
= if_info
->loopback
;
341 remote_interface_list
= g_list_append(remote_interface_list
, temp
);
344 #endif /* HAVE_LIBPCAP */