HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / capture_ifinfo.c
blob87153ad2b35e87c657ee1a35f1e188408df94f6a
1 /* capture_ifinfo.c
2 * Routines for getting interface information from dumpcap
4 * $Id$
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.
25 #include "config.h"
27 #ifdef HAVE_LIBPCAP
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stdio.h>
33 #ifdef HAVE_ARPA_INET_H
34 #include <arpa/inet.h>
35 #endif
37 #ifdef HAVE_SYS_SOCKET_H
38 #include <sys/socket.h> /* needed to define AF_ values on UNIX */
39 #endif
41 #ifdef HAVE_WINSOCK2_H
42 #include <winsock2.h> /* needed to define AF_ values on Windows */
43 #endif
45 #ifdef NEED_INET_V6DEFS_H
46 # include "wsutil/inet_v6defs.h"
47 #endif
49 #include <glib.h>
51 #include "capture_opts.h"
52 #include "capture_session.h"
53 #include "capture_sync.h"
54 #include "log.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)
63 GSList *list;
64 GList *rlist;
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;
77 if (if_addr) {
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;
81 } else {
82 memcpy(temp_addr->addr.ip6_addr, if_addr->addr.ip6_addr, sizeof(if_addr->addr));
84 } else {
85 g_free(temp_addr);
86 temp_addr = NULL;
88 if (temp_addr) {
89 temp->addrs = g_slist_append(temp->addrs, temp_addr);
92 temp->loopback = if_info->loopback;
93 iflist = g_list_append(iflist, temp);
96 #endif
98 /**
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? */
107 GList *
108 capture_interface_list(int *err, char **err_str, void (*update_cb)(void))
110 int ret;
111 GList *if_list = NULL;
112 int i, j;
113 gchar *data, *primary_msg, *secondary_msg;
114 gchar **raw_list, **if_parts, **addr_parts;
115 gchar *name;
116 if_info_t *if_info;
117 if_addr_t *if_addr;
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);
123 if (ret != 0) {
124 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Interface List failed!");
125 if (err_str) {
126 *err_str = primary_msg;
127 } else {
128 g_free(primary_msg);
130 g_free(secondary_msg);
131 *err = CANT_GET_INTERFACE_LIST;
132 return NULL;
135 /* Split our lines */
136 #ifdef _WIN32
137 raw_list = g_strsplit(data, "\r\n", 0);
138 #else
139 raw_list = g_strsplit(data, "\n", 0);
140 #endif
141 g_free(data);
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);
148 continue;
151 /* Number followed by the name, e.g "1. eth0" */
152 name = strchr(if_parts[0], ' ');
153 if (name) {
154 name++;
155 } else {
156 g_strfreev(if_parts);
157 continue;
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;
175 } else {
176 g_free(if_addr);
177 if_addr = NULL;
179 if (if_addr) {
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;
194 if (err_str)
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);
201 #endif
202 return 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? */
207 if_capabilities_t *
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;
213 int err, i;
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);
223 if (err != 0) {
224 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Interface Capabilities failed!");
225 if (err_str) {
226 *err_str = primary_msg;
227 } else {
228 g_free(primary_msg);
230 g_free(secondary_msg);
231 return NULL;
234 /* Split our lines */
235 #ifdef _WIN32
236 raw_list = g_strsplit(data, "\r\n", 0);
237 #else
238 raw_list = g_strsplit(data, "\n", 0);
239 #endif
240 g_free(data);
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!");
247 if (err_str) {
248 *err_str = g_strdup("Dumpcap returned no interface capability information");
250 return NULL;
254 * Allocate the interface capabilities structure.
256 caps = (if_capabilities_t *)g_malloc(sizeof *caps);
257 switch (*raw_list[0]) {
259 case '0':
260 caps->can_set_rfmon = FALSE;
261 break;
263 case '1':
264 caps->can_set_rfmon = TRUE;
265 break;
267 default:
268 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Interface Capabilities returned bad information!");
269 if (err_str) {
270 *err_str = g_strdup_printf("Dumpcap returned \"%s\" for monitor-mode capability",
271 raw_list[0]);
273 g_free(caps);
274 return NULL;
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);
285 continue;
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]);
293 else
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) {
302 /* No. */
303 if (err_str)
304 *err_str = g_strdup("Dumpcap returned no link-layer types");
305 g_free(caps);
306 return NULL;
308 caps->data_link_types = linktype_list;
309 return caps;
312 #ifdef HAVE_PCAP_REMOTE
313 void add_interface_to_remote_list(if_info_t *if_info)
315 GSList *list;
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;
325 if (if_addr) {
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;
329 } else {
330 memcpy(temp_addr->addr.ip6_addr, if_addr->addr.ip6_addr, sizeof(if_addr->addr));
332 } else {
333 g_free(temp_addr);
334 temp_addr = NULL;
336 if (temp_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);
343 #endif
344 #endif /* HAVE_LIBPCAP */