Glib docs recommend using the slice API if you know you won't need to realloc.
[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 #ifdef _WIN32
66         const char *guid_text;
67         GUID guid;
68 #endif
69
70         if_info = (if_info_t *)g_malloc(sizeof (if_info_t));
71         if_info->name = g_strdup(name);
72 #ifdef _WIN32
73         /*
74          * On Windows, the "description" is a vendor description,
75          * and the friendly name isn't returned by WinPcap.
76          * Fetch it ourselves.
77          */
78
79         /*
80          * Skip over the "\Device\NPF_" prefix in the device name,
81          * if present.
82          */
83         if (strncmp("\\Device\\NPF_", name, 12) == 0)
84                 guid_text = name + 12;
85         else
86                 guid_text = name;
87
88         /* Now try to parse what remains as a GUID. */
89         if (parse_as_guid(guid_text, &guid)) {
90                 /*
91                  * Success. Try to get a friendly name using the GUID.
92                  * As this is a regular interface, the description is a
93                  * vendor description.
94                  */
95                 if_info->friendly_name = get_interface_friendly_name_from_device_guid(&guid);
96                 if_info->vendor_description = g_strdup(description);
97         } else {
98                 /*
99                  * This is probably not a regular interface; we only
100                  * support NT 5 (W2K) and later, so all regular interfaces
101                  * should have GUIDs at the end of the name.  Therefore,
102                  * the description, if supplied, is a friendly name
103                  * provided by WinPcap, and there is no vendor
104                  * description.
105                  */
106                 if_info->friendly_name = g_strdup(description);
107                 if_info->vendor_description = NULL;
108         }
109 #else
110         /*
111          * On UN*X, if there is a description, it's a friendly
112          * name, and there is no vendor description.
113          * If there's no description, fetch a friendly name
114          * if we can; if that fails, then, for a loopback
115          * interface, give it the friendly name "Loopback".
116          */
117         if_info->friendly_name = g_strdup(description);
118         if (if_info->friendly_name == NULL) {
119                 if_info->friendly_name = get_unix_interface_friendly_name(name);
120                 if (if_info->friendly_name == NULL) {
121                         /*
122                          * If this is a loopback interface, give it a
123                          * "friendly name" of "Loopback".
124                          */
125                         if (loopback)
126                                 if_info->friendly_name = g_strdup("Loopback");
127                 }
128         }
129         if_info->vendor_description = NULL;
130 #endif
131         if_info->loopback = loopback;
132         if_info->addrs = NULL;
133         return if_info;
134 }
135
136 void
137 if_info_add_address(if_info_t *if_info, struct sockaddr *addr)
138 {
139         if_addr_t *if_addr;
140         struct sockaddr_in *ai;
141 #ifdef INET6
142         struct sockaddr_in6 *ai6;
143 #endif
144
145         switch (addr->sa_family) {
146
147         case AF_INET:
148                 ai = (struct sockaddr_in *)(void *)addr;
149                 if_addr = (if_addr_t *)g_malloc(sizeof(*if_addr));
150                 if_addr->ifat_type = IF_AT_IPv4;
151                 if_addr->addr.ip4_addr =
152                     *((guint32 *)&(ai->sin_addr.s_addr));
153                 if_info->addrs = g_slist_append(if_info->addrs, if_addr);
154                 break;
155
156 #ifdef INET6
157         case AF_INET6:
158                 ai6 = (struct sockaddr_in6 *)(void *)addr;
159                 if_addr = (if_addr_t *)g_malloc(sizeof(*if_addr));
160                 if_addr->ifat_type = IF_AT_IPv6;
161                 memcpy((void *)&if_addr->addr.ip6_addr,
162                     (void *)&ai6->sin6_addr.s6_addr,
163                     sizeof if_addr->addr.ip6_addr);
164                 if_info->addrs = g_slist_append(if_info->addrs, if_addr);
165                 break;
166 #endif
167         }
168 }
169
170 #ifdef HAVE_PCAP_FINDALLDEVS
171 /*
172  * Get all IP address information for the given interface.
173  */
174 static void
175 if_info_ip(if_info_t *if_info, pcap_if_t *d)
176 {
177         pcap_addr_t *a;
178
179         /* All addresses */
180         for (a = d->addresses; a != NULL; a = a->next) {
181                 if (a->addr != NULL)
182                         if_info_add_address(if_info, a->addr);
183         }
184 }
185
186 #ifdef HAVE_PCAP_REMOTE
187 GList *
188 get_interface_list_findalldevs_ex(const char *source,
189                                   struct pcap_rmtauth *auth,
190                                   int *err, char **err_str)
191 {
192         GList  *il = NULL;
193         pcap_if_t *alldevs, *dev;
194         if_info_t *if_info;
195         char errbuf[PCAP_ERRBUF_SIZE];
196
197         if (pcap_findalldevs_ex((char *)source, auth, &alldevs, errbuf) == -1) {
198                 *err = CANT_GET_INTERFACE_LIST;
199                 if (err_str != NULL)
200                         *err_str = cant_get_if_list_error_message(errbuf);
201                 return NULL;
202         }
203
204         if (alldevs == NULL) {
205                 /*
206                  * No interfaces found.
207                  */
208                 *err = NO_INTERFACES_FOUND;
209                 if (err_str != NULL)
210                         *err_str = NULL;
211                 return NULL;
212         }
213
214         for (dev = alldevs; dev != NULL; dev = dev->next) {
215                 if_info = if_info_new(dev->name, dev->description,
216                     (dev->flags & PCAP_IF_LOOPBACK) ? TRUE : FALSE);
217                 il = g_list_append(il, if_info);
218                 if_info_ip(if_info, dev);
219         }
220         pcap_freealldevs(alldevs);
221
222         return il;
223 }
224 #endif
225
226 GList *
227 get_interface_list_findalldevs(int *err, char **err_str)
228 {
229         GList  *il = NULL;
230         pcap_if_t *alldevs, *dev;
231         if_info_t *if_info;
232         char errbuf[PCAP_ERRBUF_SIZE];
233
234         if (pcap_findalldevs(&alldevs, errbuf) == -1) {
235                 *err = CANT_GET_INTERFACE_LIST;
236                 if (err_str != NULL)
237                         *err_str = cant_get_if_list_error_message(errbuf);
238                 return NULL;
239         }
240
241         if (alldevs == NULL) {
242                 /*
243                  * No interfaces found.
244                  */
245                 *err = NO_INTERFACES_FOUND;
246                 if (err_str != NULL)
247                         *err_str = NULL;
248                 return NULL;
249         }
250
251         for (dev = alldevs; dev != NULL; dev = dev->next) {
252                 if_info = if_info_new(dev->name, dev->description,
253                     (dev->flags & PCAP_IF_LOOPBACK) ? TRUE : FALSE);
254                 il = g_list_append(il, if_info);
255                 if_info_ip(if_info, dev);
256         }
257         pcap_freealldevs(alldevs);
258
259         return il;
260 }
261 #endif /* HAVE_PCAP_FINDALLDEVS */
262
263 static void
264 free_if_info_addr_cb(gpointer addr, gpointer user_data _U_)
265 {
266         g_free(addr);
267 }
268
269 static void
270 free_if_cb(gpointer data, gpointer user_data _U_)
271 {
272         if_info_t *if_info = (if_info_t *)data;
273
274         g_free(if_info->name);
275         g_free(if_info->friendly_name);
276         g_free(if_info->vendor_description);
277
278         g_slist_foreach(if_info->addrs, free_if_info_addr_cb, NULL);
279         g_slist_free(if_info->addrs);
280         g_free(if_info);
281 }
282
283 void
284 free_interface_list(GList *if_list)
285 {
286         g_list_foreach(if_list, free_if_cb, NULL);
287         g_list_free(if_list);
288 }
289
290 #if !defined(HAVE_PCAP_DATALINK_NAME_TO_VAL) || !defined(HAVE_PCAP_DATALINK_VAL_TO_NAME) || !defined(HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION)
291 struct dlt_choice {
292         const char *name;
293         const char *description;
294         int     dlt;
295 };
296
297 #define DLT_CHOICE(code, description) { #code, description, code }
298 #define DLT_CHOICE_SENTINEL { NULL, NULL, 0 }
299
300 static struct dlt_choice dlt_choices[] = {
301         DLT_CHOICE(DLT_NULL, "BSD loopback"),
302         DLT_CHOICE(DLT_EN10MB, "Ethernet"),
303         DLT_CHOICE(DLT_IEEE802, "Token ring"),
304         DLT_CHOICE(DLT_ARCNET, "ARCNET"),
305         DLT_CHOICE(DLT_SLIP, "SLIP"),
306         DLT_CHOICE(DLT_PPP, "PPP"),
307         DLT_CHOICE(DLT_FDDI, "FDDI"),
308         DLT_CHOICE(DLT_ATM_RFC1483, "RFC 1483 IP-over-ATM"),
309         DLT_CHOICE(DLT_RAW, "Raw IP"),
310         DLT_CHOICE(DLT_SLIP_BSDOS, "BSD/OS SLIP"),
311         DLT_CHOICE(DLT_PPP_BSDOS, "BSD/OS PPP"),
312         DLT_CHOICE(DLT_ATM_CLIP, "Linux Classical IP-over-ATM"),
313         DLT_CHOICE(DLT_PPP_SERIAL, "PPP over serial"),
314         DLT_CHOICE(DLT_PPP_ETHER, "PPPoE"),
315         DLT_CHOICE(DLT_C_HDLC, "Cisco HDLC"),
316         DLT_CHOICE(DLT_IEEE802_11, "802.11"),
317         DLT_CHOICE(DLT_FRELAY, "Frame Relay"),
318         DLT_CHOICE(DLT_LOOP, "OpenBSD loopback"),
319         DLT_CHOICE(DLT_ENC, "OpenBSD encapsulated IP"),
320         DLT_CHOICE(DLT_LINUX_SLL, "Linux cooked"),
321         DLT_CHOICE(DLT_LTALK, "Localtalk"),
322         DLT_CHOICE(DLT_PFLOG, "OpenBSD pflog file"),
323         DLT_CHOICE(DLT_PRISM_HEADER, "802.11 plus Prism header"),
324         DLT_CHOICE(DLT_IP_OVER_FC, "RFC 2625 IP-over-Fibre Channel"),
325         DLT_CHOICE(DLT_SUNATM, "Sun raw ATM"),
326         DLT_CHOICE(DLT_IEEE802_11_RADIO, "802.11 plus BSD radio information header"),
327         DLT_CHOICE(DLT_APPLE_IP_OVER_IEEE1394, "Apple IP-over-IEEE 1394"),
328         DLT_CHOICE(DLT_ARCNET_LINUX, "Linux ARCNET"),
329         DLT_CHOICE(DLT_LINUX_IRDA, "Linux IrDA"),
330         DLT_CHOICE(DLT_IEEE802_11_RADIO_AVS, "802.11 plus AVS radio information header"),
331         DLT_CHOICE_SENTINEL
332 };
333
334 #if !defined(HAVE_PCAP_DATALINK_NAME_TO_VAL)
335 static int
336 pcap_datalink_name_to_val(const char *name)
337 {
338         int i;
339
340         for (i = 0; dlt_choices[i].name != NULL; i++) {
341                 if (g_ascii_strcasecmp(dlt_choices[i].name + sizeof("DLT_") - 1,
342                     name) == 0)
343                         return (dlt_choices[i].dlt);
344         }
345         return (-1);
346 }
347 #endif /* defined(HAVE_PCAP_DATALINK_NAME_TO_VAL) */
348
349 #if !defined(HAVE_PCAP_DATALINK_VAL_TO_NAME)
350 static const char *
351 pcap_datalink_val_to_name(int dlt)
352 {
353         int i;
354
355         for (i = 0; dlt_choices[i].name != NULL; i++) {
356                 if (dlt_choices[i].dlt == dlt)
357                         return (dlt_choices[i].name + sizeof("DLT_") - 1);
358         }
359         return (NULL);
360 }
361 #endif /* defined(HAVE_PCAP_DATALINK_VAL_TO_NAME) */
362
363 #if !defined(HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION)
364 const char *
365 pcap_datalink_val_to_description(int dlt)
366 {
367         int i;
368
369         for (i = 0; dlt_choices[i].name != NULL; i++) {
370                 if (dlt_choices[i].dlt == dlt)
371                         return (dlt_choices[i].description);
372         }
373         return (NULL);
374 }
375 #endif /* defined(HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION) */
376
377 #endif /* !defined(HAVE_PCAP_DATALINK_VAL_TO_NAME) || !defined(HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION) */
378
379 static void
380 free_linktype_cb(gpointer data, gpointer user_data _U_)
381 {
382         data_link_info_t *linktype_info = (data_link_info_t *)data;
383
384         g_free(linktype_info->name);
385         g_free(linktype_info->description);
386 }
387
388 void
389 free_if_capabilities(if_capabilities_t *caps)
390 {
391         g_list_foreach(caps->data_link_types, free_linktype_cb, NULL);
392         g_list_free(caps->data_link_types);
393         g_free(caps);
394 }
395
396 const char *
397 linktype_val_to_name(int dlt)
398 {
399     return pcap_datalink_val_to_name(dlt);
400 }
401
402 int linktype_name_to_val(const char *linktype)
403 {
404     return pcap_datalink_name_to_val(linktype);
405 }
406
407 #endif /* HAVE_LIBPCAP */