Maybe the problem is that the compilers used on AIX weren't defining
[obnox/wireshark/wip.git] / pcap-util.c
1 /* pcap-util.c
2  * Utility routines for packet capture
3  *
4  * $Id: pcap-util.c,v 1.21 2003/11/21 08:33:49 guy Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #ifdef HAVE_LIBPCAP
30
31 #include <glib.h>
32
33 #include <stdlib.h>
34 #include <limits.h>
35 #include <string.h>
36
37 #ifdef HAVE_SYS_TYPES_H
38 # include <sys/types.h>
39 #endif
40
41 #ifdef HAVE_SYS_SOCKET_H
42 #include <sys/socket.h>
43 #endif
44
45 #include <pcap.h>
46
47 #include <wtap.h>
48 #include <wtap-capture.h>
49
50 #include "pcap-util.h"
51 #include "pcap-util-int.h"
52
53 /*
54  * Get the data-link type for a libpcap device.
55  * This works around AIX 5.x's non-standard and incompatible-with-the-
56  * rest-of-the-universe libpcap.
57  */
58 int
59 get_pcap_linktype(pcap_t *pch, char *devname
60 #ifndef _AIX
61         _U_
62 #endif
63 )
64 {
65         int linktype;
66 #ifdef _AIX
67         char *ifacename;
68 #endif
69
70         linktype = pcap_datalink(pch);
71 #ifdef _AIX
72
73         /*
74          * The libpcap that comes with AIX 5.x uses RFC 1573 ifType values
75          * rather than DLT_ values for link-layer types; the ifType values
76          * for LAN devices are:
77          *
78          *      Ethernet        6
79          *      802.3           7
80          *      Token Ring      9
81          *      FDDI            15
82          *
83          * and the ifType value for a loopback device is 24.
84          *
85          * The AIX names for LAN devices begin with:
86          *
87          *      Ethernet                en
88          *      802.3                   et
89          *      Token Ring              tr
90          *      FDDI                    fi
91          *
92          * and the AIX names for loopback devices begin with "lo".
93          *
94          * (The difference between "Ethernet" and "802.3" is presumably
95          * whether packets have an Ethernet header, with a packet type,
96          * or an 802.3 header, with a packet length, followed by an 802.2
97          * header and possibly a SNAP header.)
98          *
99          * If the device name matches "linktype" interpreted as an ifType
100          * value, rather than as a DLT_ value, we will assume this is AIX's
101          * non-standard, incompatible libpcap, rather than a standard libpcap,
102          * and will map the link-layer type to the standard DLT_ value for
103          * that link-layer type, as that's what the rest of Ethereal expects.
104          *
105          * (This means the capture files won't be readable by a tcpdump
106          * linked with AIX's non-standard libpcap, but so it goes.  They
107          * *will* be readable by standard versions of tcpdump, Ethereal,
108          * and so on.)
109          *
110          * XXX - if we conclude we're using AIX libpcap, should we also
111          * set a flag to cause us to assume the time stamps are in
112          * seconds-and-nanoseconds form, and to convert them to
113          * seconds-and-microseconds form before processing them and
114          * writing them out?
115          */
116
117         /*
118          * Find the last component of the device name, which is the
119          * interface name.
120          */
121         ifacename = strchr(devname, '/');
122         if (ifacename == NULL)
123                 ifacename = devnames;
124
125         /* See if it matches any of the LAN device names. */
126         if (strncmp(ifacename, "en", 2) == 0) {
127                 if (linktype == 6) {
128                         /*
129                          * That's the RFC 1573 value for Ethernet; map it
130                          * to DLT_EN10MB.
131                          */
132                         linktype = 1;
133                 }
134         } else if (strncmp(ifacename, "et", 2) == 0) {
135                 if (linktype == 7) {
136                         /*
137                          * That's the RFC 1573 value for 802.3; map it to
138                          * DLT_EN10MB.
139                          * (libpcap, tcpdump, Ethereal, etc. don't care if
140                          * it's Ethernet or 802.3.)
141                          */
142                         linktype = 1;
143                 }
144         } else if (strncmp(ifacename, "tr", 2) == 0) {
145                 if (linktype == 9) {
146                         /*
147                          * That's the RFC 1573 value for 802.5 (Token Ring);
148                          * map it to DLT_IEEE802, which is what's used for
149                          * Token Ring.
150                          */
151                         linktype = 6;
152                 }
153         } else if (strncmp(ifacename, "fi", 2) == 0) {
154                 if (linktype == 15) {
155                         /*
156                          * That's the RFC 1573 value for FDDI; map it to
157                          * DLT_FDDI.
158                          */
159                         linktype = 10;
160                 }
161         } else if (strncmp(ifacename, "lo", 2) == 0) {
162                 if (linktype == 24) {
163                         /*
164                          * That's the RFC 1573 value for "software loopback"
165                          * devices; map it to DLT_NULL, which is what's used
166                          * for loopback devices on BSD.
167                          */
168                         linktype = 0;
169                 }
170         }
171 #endif
172
173         return linktype;
174 }
175
176 if_info_t *
177 if_info_new(char *name, char *description)
178 {
179         if_info_t *if_info;
180
181         if_info = g_malloc(sizeof (if_info_t));
182         if_info->name = g_strdup(name);
183         if (description == NULL)
184                 if_info->description = NULL;
185         else
186                 if_info->description = g_strdup(description);
187         return if_info;
188 }
189
190 #ifdef HAVE_PCAP_FINDALLDEVS
191 GList *
192 get_interface_list_findalldevs(int *err, char *err_str)
193 {
194         GList  *il = NULL;
195         pcap_if_t *alldevs, *dev;
196         if_info_t *if_info;
197
198         if (pcap_findalldevs(&alldevs, err_str) == -1) {
199                 *err = CANT_GET_INTERFACE_LIST;
200                 return NULL;
201         }
202
203         if (alldevs == NULL) {
204                 /*
205                  * No interfaces found.
206                  */
207                 *err = NO_INTERFACES_FOUND;
208                 return NULL;
209         }
210
211         for (dev = alldevs; dev != NULL; dev = dev->next) {
212                 if_info = if_info_new(dev->name, dev->description);
213                 il = g_list_append(il, if_info);
214         }
215         pcap_freealldevs(alldevs);
216
217         return il;
218 }
219 #endif /* HAVE_PCAP_FINDALLDEVS */
220
221 static void
222 free_if_cb(gpointer data, gpointer user_data _U_)
223 {
224         if_info_t *if_info = data;
225
226         g_free(if_info->name);
227         if (if_info->description != NULL)
228                 g_free(if_info->description);
229 }
230
231 void
232 free_interface_list(GList *if_list)
233 {
234         g_list_foreach(if_list, free_if_cb, NULL);
235         g_list_free(if_list);
236 }
237
238 /*
239  * Get the data-link types available for a libpcap device.
240  */
241 static data_link_info_t *
242 create_data_link_info(int dlt)
243 {
244         data_link_info_t *data_link_info;
245 #ifdef HAVE_PCAP_DATALINK_VAL_TO_NAME
246         const char *typename;
247 #endif
248         int wtap_encap;
249
250         data_link_info = g_malloc(sizeof (data_link_info_t));
251         data_link_info->dlt = dlt;
252 #ifdef HAVE_PCAP_DATALINK_VAL_TO_NAME
253         typename = pcap_datalink_val_to_name(dlt);
254         if (typename != NULL)
255                 data_link_info->name = g_strdup(typename);
256         else
257 #endif
258                 data_link_info->name = g_strdup_printf("DLT %d", dlt);
259         wtap_encap = wtap_pcap_encap_to_wtap_encap(dlt);
260         if (wtap_encap == WTAP_ENCAP_UNKNOWN) {
261                 /*
262                  * We don't support this in Wiretap.
263                  * However, we should, so you can capture on it.
264                  * Put in an entry for it, with no description.
265                  */
266                 data_link_info->description = NULL;
267         } else {
268                 /*
269                  * If this is null, that's a bug in
270                  * "wtap_pcap_encap_to_wtap_encap()" - it should always
271                  * return a valid encapsulation type - so we assume it's
272                  * not null.
273                  */
274                 data_link_info->description =
275                     g_strdup(wtap_encap_string(wtap_encap));
276         }
277         return data_link_info;
278 }
279
280 GList *
281 get_pcap_linktype_list(char *devname, char *err_buf)
282 {
283         GList *linktype_list = NULL;
284         pcap_t *pch;
285         int deflt;
286 #ifdef HAVE_PCAP_SET_DATALINK
287         int *linktypes;
288         int i, nlt;
289 #endif
290         data_link_info_t *data_link_info;
291
292         pch = pcap_open_live(devname, MIN_PACKET_SIZE, 0, 0, err_buf);
293         if (pch == NULL)
294                 return NULL;
295         err_buf[0] = '\0';      /* an empty list doesn't mean an error */
296         deflt = get_pcap_linktype(pch, devname);
297 #ifdef HAVE_PCAP_LIST_DATALINKS
298         nlt = pcap_list_datalinks(pch, &linktypes);
299         if (nlt == 0 || linktypes == NULL)
300                 return NULL;
301         for (i = 0; i < nlt; i++) {
302                 data_link_info = create_data_link_info(linktypes[i]);
303
304                 /*
305                  * XXX - for 802.11, make the most detailed 802.11
306                  * version the default, rather than the one the
307                  * device has as the default?
308                  */
309                 if (linktypes[i] == deflt)
310                         linktype_list = g_list_prepend(linktype_list,
311                             data_link_info);
312                 else
313                         linktype_list = g_list_append(linktype_list,
314                             data_link_info);
315         }
316         free(linktypes);
317 #else
318         data_link_info = create_data_link_info(deflt);
319         linktype_list = g_list_append(linktype_list, data_link_info);
320 #endif
321
322         pcap_close(pch);
323         return linktype_list;
324 }
325
326 static void
327 free_linktype_cb(gpointer data, gpointer user_data _U_)
328 {
329         data_link_info_t *linktype_info = data;
330
331         g_free(linktype_info->name);
332         if (linktype_info->description != NULL)
333                 g_free(linktype_info->description);
334 }
335
336 void
337 free_pcap_linktype_list(GList *linktype_list)
338 {
339         g_list_foreach(linktype_list, free_linktype_cb, NULL);
340         g_list_free(linktype_list);
341 }
342
343 /* Set the data link type on a pcap. */
344 const char *
345 set_pcap_linktype(pcap_t *pch, char *devname, int dlt)
346 {
347 #ifdef HAVE_PCAP_SET_DATALINK
348         if (pcap_set_datalink(pch, dlt) == 0)
349                 return NULL;    /* no error */
350         return pcap_geterr(pch);
351 #else
352         /* Let them set it to the type it is; reject any other request. */
353         if (get_pcap_linktype(pch, devname) == dlt)
354                 return NULL;    /* no error */
355         return "That DLT is not one of the DLTs supported by this device";
356 #endif
357 }
358
359 #endif /* HAVE_LIBPCAP */