06eff2b06bc162beeaae8b25f7c347ab3f6b169e
[metze/wireshark/wip.git] / capture-pcap-util.c
1 /* capture-pcap-util.c
2  * Utility routines for packet capture
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
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.
14  *
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.
19  *
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.
23  */
24
25 #include "config.h"
26
27 #ifdef HAVE_LIBPCAP
28
29 #include <glib.h>
30
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <limits.h>
34 #include <string.h>
35
36 #ifdef HAVE_SYS_TYPES_H
37 # include <sys/types.h>
38 #endif
39
40 #ifdef HAVE_SYS_SOCKET_H
41 #include <sys/socket.h>
42 #endif
43
44 #include <wtap.h>
45 #include <libpcap.h>
46
47 #include "capture_ifinfo.h"
48 #include "capture-pcap-util.h"
49 #include "capture-pcap-util-int.h"
50
51 #ifndef _WIN32
52 #include <netinet/in.h>
53 #endif
54
55 #ifdef _WIN32
56 #include "capture_win_ifnames.h" /* windows friendly interface names */
57 #else
58 #include "capture_unix_ifnames.h"
59 #endif
60
61 if_info_t *
62 if_info_new(const char *name, const char *description, gboolean loopback)
63 {
64         if_info_t *if_info;
65
66         if_info = (if_info_t *)g_malloc(sizeof (if_info_t));
67         if_info->name = g_strdup(name);
68 #ifdef _WIN32
69         /*
70          * On Windows, the "description" is a vendor description,
71          * and the friendly name isn't returned by WinPcap.
72          * Fetch it ourselves.
73          */
74         get_windows_interface_friendlyname(name, &if_info->friendly_name);
75         if_info->vendor_description = g_strdup(description);
76 #else
77         /*
78          * On UN*X, if there is a description, it's a friendly
79          * name, and there is no vendor description.
80          * If there's no description, fetch a friendly name
81          * if we can; if that fails, then, for a loopback
82          * interface, give it the friendly name "Loopback".
83          */
84         if_info->friendly_name = g_strdup(description);
85         if (if_info->friendly_name == NULL) {
86                 if_info->friendly_name = get_unix_interface_friendly_name(name);
87                 if (if_info->friendly_name == NULL) {
88                         /*
89                          * If this is a loopback interface, give it a
90                          * "friendly name" of "Loopback".
91                          */
92                         if (loopback)
93                                 if_info->friendly_name = g_strdup("Loopback");
94                 }
95         }
96         if_info->vendor_description = NULL;
97 #endif
98         if_info->loopback = loopback;
99         if_info->addrs = NULL;
100         return if_info;
101 }
102
103 void
104 if_info_add_address(if_info_t *if_info, struct sockaddr *addr)
105 {
106         if_addr_t *if_addr;
107         struct sockaddr_in *ai;
108 #ifdef INET6
109         struct sockaddr_in6 *ai6;
110 #endif
111
112         switch (addr->sa_family) {
113
114         case AF_INET:
115                 ai = (struct sockaddr_in *)(void *)addr;
116                 if_addr = (if_addr_t *)g_malloc(sizeof(*if_addr));
117                 if_addr->ifat_type = IF_AT_IPv4;
118                 if_addr->addr.ip4_addr =
119                     *((guint32 *)&(ai->sin_addr.s_addr));
120                 if_info->addrs = g_slist_append(if_info->addrs, if_addr);
121                 break;
122
123 #ifdef INET6
124         case AF_INET6:
125                 ai6 = (struct sockaddr_in6 *)(void *)addr;
126                 if_addr = (if_addr_t *)g_malloc(sizeof(*if_addr));
127                 if_addr->ifat_type = IF_AT_IPv6;
128                 memcpy((void *)&if_addr->addr.ip6_addr,
129                     (void *)&ai6->sin6_addr.s6_addr,
130                     sizeof if_addr->addr.ip6_addr);
131                 if_info->addrs = g_slist_append(if_info->addrs, if_addr);
132                 break;
133 #endif
134         }
135 }
136
137 #ifdef HAVE_PCAP_FINDALLDEVS
138 /*
139  * Get all IP address information for the given interface.
140  */
141 static void
142 if_info_ip(if_info_t *if_info, pcap_if_t *d)
143 {
144         pcap_addr_t *a;
145
146         /* All addresses */
147         for (a = d->addresses; a != NULL; a = a->next) {
148                 if (a->addr != NULL)
149                         if_info_add_address(if_info, a->addr);
150         }
151 }
152
153 #ifdef HAVE_PCAP_REMOTE
154 GList *
155 get_interface_list_findalldevs_ex(const char *source,
156                                   struct pcap_rmtauth *auth,
157                                   int *err, char **err_str)
158 {
159         GList  *il = NULL;
160         pcap_if_t *alldevs, *dev;
161         if_info_t *if_info;
162         char errbuf[PCAP_ERRBUF_SIZE];
163
164         if (pcap_findalldevs_ex((char *)source, auth, &alldevs, errbuf) == -1) {
165                 *err = CANT_GET_INTERFACE_LIST;
166                 if (err_str != NULL)
167                         *err_str = cant_get_if_list_error_message(errbuf);
168                 return NULL;
169         }
170
171         if (alldevs == NULL) {
172                 /*
173                  * No interfaces found.
174                  */
175                 *err = NO_INTERFACES_FOUND;
176                 if (err_str != NULL)
177                         *err_str = NULL;
178                 return NULL;
179         }
180
181         for (dev = alldevs; dev != NULL; dev = dev->next) {
182                 if_info = if_info_new(dev->name, dev->description,
183                     (dev->flags & PCAP_IF_LOOPBACK) ? TRUE : FALSE);
184                 il = g_list_append(il, if_info);
185                 if_info_ip(if_info, dev);
186         }
187         pcap_freealldevs(alldevs);
188
189         return il;
190 }
191 #endif
192
193 GList *
194 get_interface_list_findalldevs(int *err, char **err_str)
195 {
196         GList  *il = NULL;
197         pcap_if_t *alldevs, *dev;
198         if_info_t *if_info;
199         char errbuf[PCAP_ERRBUF_SIZE];
200
201         if (pcap_findalldevs(&alldevs, errbuf) == -1) {
202                 *err = CANT_GET_INTERFACE_LIST;
203                 if (err_str != NULL)
204                         *err_str = cant_get_if_list_error_message(errbuf);
205                 return NULL;
206         }
207
208         if (alldevs == NULL) {
209                 /*
210                  * No interfaces found.
211                  */
212                 *err = NO_INTERFACES_FOUND;
213                 if (err_str != NULL)
214                         *err_str = NULL;
215                 return NULL;
216         }
217
218         for (dev = alldevs; dev != NULL; dev = dev->next) {
219                 if_info = if_info_new(dev->name, dev->description,
220                     (dev->flags & PCAP_IF_LOOPBACK) ? TRUE : FALSE);
221                 il = g_list_append(il, if_info);
222                 if_info_ip(if_info, dev);
223         }
224         pcap_freealldevs(alldevs);
225
226         return il;
227 }
228 #endif /* HAVE_PCAP_FINDALLDEVS */
229
230 static void
231 free_if_info_addr_cb(gpointer addr, gpointer user_data _U_)
232 {
233         g_free(addr);
234 }
235
236 static void
237 free_if_cb(gpointer data, gpointer user_data _U_)
238 {
239         if_info_t *if_info = (if_info_t *)data;
240
241         g_free(if_info->name);
242         g_free(if_info->friendly_name);
243         g_free(if_info->vendor_description);
244
245         g_slist_foreach(if_info->addrs, free_if_info_addr_cb, NULL);
246         g_slist_free(if_info->addrs);
247         g_free(if_info);
248 }
249
250 void
251 free_interface_list(GList *if_list)
252 {
253         g_list_foreach(if_list, free_if_cb, NULL);
254         g_list_free(if_list);
255 }
256
257 #if !defined(HAVE_PCAP_DATALINK_NAME_TO_VAL) || !defined(HAVE_PCAP_DATALINK_VAL_TO_NAME) || !defined(HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION)
258 struct dlt_choice {
259         const char *name;
260         const char *description;
261         int     dlt;
262 };
263
264 #define DLT_CHOICE(code, description) { #code, description, code }
265 #define DLT_CHOICE_SENTINEL { NULL, NULL, 0 }
266
267 static struct dlt_choice dlt_choices[] = {
268         DLT_CHOICE(DLT_NULL, "BSD loopback"),
269         DLT_CHOICE(DLT_EN10MB, "Ethernet"),
270         DLT_CHOICE(DLT_IEEE802, "Token ring"),
271         DLT_CHOICE(DLT_ARCNET, "ARCNET"),
272         DLT_CHOICE(DLT_SLIP, "SLIP"),
273         DLT_CHOICE(DLT_PPP, "PPP"),
274         DLT_CHOICE(DLT_FDDI, "FDDI"),
275         DLT_CHOICE(DLT_ATM_RFC1483, "RFC 1483 IP-over-ATM"),
276         DLT_CHOICE(DLT_RAW, "Raw IP"),
277         DLT_CHOICE(DLT_SLIP_BSDOS, "BSD/OS SLIP"),
278         DLT_CHOICE(DLT_PPP_BSDOS, "BSD/OS PPP"),
279         DLT_CHOICE(DLT_ATM_CLIP, "Linux Classical IP-over-ATM"),
280         DLT_CHOICE(DLT_PPP_SERIAL, "PPP over serial"),
281         DLT_CHOICE(DLT_PPP_ETHER, "PPPoE"),
282         DLT_CHOICE(DLT_C_HDLC, "Cisco HDLC"),
283         DLT_CHOICE(DLT_IEEE802_11, "802.11"),
284         DLT_CHOICE(DLT_FRELAY, "Frame Relay"),
285         DLT_CHOICE(DLT_LOOP, "OpenBSD loopback"),
286         DLT_CHOICE(DLT_ENC, "OpenBSD encapsulated IP"),
287         DLT_CHOICE(DLT_LINUX_SLL, "Linux cooked"),
288         DLT_CHOICE(DLT_LTALK, "Localtalk"),
289         DLT_CHOICE(DLT_PFLOG, "OpenBSD pflog file"),
290         DLT_CHOICE(DLT_PRISM_HEADER, "802.11 plus Prism header"),
291         DLT_CHOICE(DLT_IP_OVER_FC, "RFC 2625 IP-over-Fibre Channel"),
292         DLT_CHOICE(DLT_SUNATM, "Sun raw ATM"),
293         DLT_CHOICE(DLT_IEEE802_11_RADIO, "802.11 plus BSD radio information header"),
294         DLT_CHOICE(DLT_APPLE_IP_OVER_IEEE1394, "Apple IP-over-IEEE 1394"),
295         DLT_CHOICE(DLT_ARCNET_LINUX, "Linux ARCNET"),
296         DLT_CHOICE(DLT_LINUX_IRDA, "Linux IrDA"),
297         DLT_CHOICE(DLT_IEEE802_11_RADIO_AVS, "802.11 plus AVS radio information header"),
298         DLT_CHOICE_SENTINEL
299 };
300
301 #if !defined(HAVE_PCAP_DATALINK_NAME_TO_VAL)
302 static int
303 pcap_datalink_name_to_val(const char *name)
304 {
305         int i;
306
307         for (i = 0; dlt_choices[i].name != NULL; i++) {
308                 if (g_ascii_strcasecmp(dlt_choices[i].name + sizeof("DLT_") - 1,
309                     name) == 0)
310                         return (dlt_choices[i].dlt);
311         }
312         return (-1);
313 }
314 #endif /* defined(HAVE_PCAP_DATALINK_NAME_TO_VAL) */
315
316 #if !defined(HAVE_PCAP_DATALINK_VAL_TO_NAME)
317 static const char *
318 pcap_datalink_val_to_name(int dlt)
319 {
320         int i;
321
322         for (i = 0; dlt_choices[i].name != NULL; i++) {
323                 if (dlt_choices[i].dlt == dlt)
324                         return (dlt_choices[i].name + sizeof("DLT_") - 1);
325         }
326         return (NULL);
327 }
328 #endif /* defined(HAVE_PCAP_DATALINK_VAL_TO_NAME) */
329
330 #if !defined(HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION)
331 const char *
332 pcap_datalink_val_to_description(int dlt)
333 {
334         int i;
335
336         for (i = 0; dlt_choices[i].name != NULL; i++) {
337                 if (dlt_choices[i].dlt == dlt)
338                         return (dlt_choices[i].description);
339         }
340         return (NULL);
341 }
342 #endif /* defined(HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION) */
343
344 #endif /* !defined(HAVE_PCAP_DATALINK_VAL_TO_NAME) || !defined(HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION) */
345
346 static void
347 free_linktype_cb(gpointer data, gpointer user_data _U_)
348 {
349         data_link_info_t *linktype_info = (data_link_info_t *)data;
350
351         g_free(linktype_info->name);
352         g_free(linktype_info->description);
353 }
354
355 void
356 free_if_capabilities(if_capabilities_t *caps)
357 {
358         g_list_foreach(caps->data_link_types, free_linktype_cb, NULL);
359         g_list_free(caps->data_link_types);
360         g_free(caps);
361 }
362
363 const char *
364 linktype_val_to_name(int dlt)
365 {
366     return pcap_datalink_val_to_name(dlt);
367 }
368
369 int linktype_name_to_val(const char *linktype)
370 {
371     return pcap_datalink_name_to_val(linktype);
372 }
373
374 #endif /* HAVE_LIBPCAP */