4 * $Id: util.c,v 1.27 2000/01/16 02:47:47 guy Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@zing.org>
8 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
41 #ifdef HAVE_SYS_TYPES_H
42 #include <sys/types.h>
45 #ifdef HAVE_SYS_STAT_H
49 #ifdef NEED_SNPRINTF_H
55 # include "snprintf.h"
66 typedef int mode_t; /* for win32 */
71 #ifdef HAVE_SYS_SOCKET_H
72 #include <sys/socket.h>
75 #ifdef HAVE_SYS_IOCTL_H
76 #include <sys/ioctl.h>
83 #ifdef HAVE_SYS_SOCKIO_H
84 # include <sys/sockio.h>
92 setup_tmpdir(char *dir)
94 int len = strlen(dir);
97 /* Append slash if necessary */
98 if (dir[len - 1] == '/') {
102 newdir = g_malloc(len + 2);
110 try_tempfile(char *namebuf, int namebuflen, const char *dir, const char *pfx)
112 static const char suffix[] = "XXXXXXXXXX";
113 int namelen = strlen(dir) + strlen(pfx) + sizeof suffix;
117 if (namebuflen < namelen) {
118 /* Stick in a truncated name, so that if this error is
119 reported with the file name, you at least get
121 snprintf(namebuf, namebuflen, "%s%s%s", dir, pfx, suffix);
122 errno = ENAMETOOLONG;
125 strcpy(namebuf, dir);
126 strcat(namebuf, pfx);
127 strcat(namebuf, suffix);
129 /* The Single UNIX Specification doesn't say that "mkstemp()"
130 creates the temporary file with mode rw-------, so we
131 won't assume that all UNIXes will do so; instead, we set
132 the umask to 0077 to take away all group and other
133 permissions, attempt to create the file, and then put
135 old_umask = umask(0077);
136 tmp_fd = mkstemp(namebuf);
141 static char *tmpdir = NULL;
143 static char *temp = NULL;
145 static char *E_tmpdir;
148 #define P_tmpdir "/var/tmp"
152 create_tempfile(char *namebuf, int namebuflen, const char *pfx)
156 static gboolean initialized;
159 if ((dir = getenv("TMPDIR")) != NULL)
160 tmpdir = setup_tmpdir(dir);
162 if ((dir = getenv("TEMP")) != NULL)
163 temp = setup_tmpdir(dir);
166 E_tmpdir = setup_tmpdir(P_tmpdir);
170 if (tmpdir != NULL) {
171 fd = try_tempfile(namebuf, namebuflen, tmpdir, pfx);
178 fd = try_tempfile(namebuf, namebuflen, temp, pfx);
184 fd = try_tempfile(namebuf, namebuflen, E_tmpdir, pfx);
188 return try_tempfile(namebuf, namebuflen, "/tmp", pfx);
191 /* ASCII/EBCDIC conversion tables from
192 * http://www.room42.com/store/computer_center/code_tables.shtml
194 static guint8 ASCII_translate_EBCDIC [ 256 ] = {
195 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
196 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
197 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
198 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
199 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, 0x4D,
200 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
201 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
202 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
203 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8,
204 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
205 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
206 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D,
207 0x7D, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
208 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
209 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
210 0xA8, 0xA9, 0xC0, 0x6A, 0xD0, 0xA1, 0x4B,
211 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
212 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
213 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
214 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
215 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
216 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
217 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
218 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
219 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
220 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
221 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
222 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
223 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
224 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
225 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
226 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B
230 ASCII_to_EBCDIC(guint8 *buf, guint bytes)
237 for (i = 0; i < bytes; i++, bufptr++) {
238 *bufptr = ASCII_translate_EBCDIC[*bufptr];
243 ASCII_to_EBCDIC1(guint8 c)
245 return ASCII_translate_EBCDIC[c];
248 static guint8 EBCDIC_translate_ASCII [ 256 ] = {
249 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
250 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
251 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
252 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
253 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
254 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
255 0x2E, 0x2E, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
256 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x2E, 0x3F,
257 0x20, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
258 0x2E, 0x2E, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
259 0x26, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
260 0x2E, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E,
261 0x2D, 0x2F, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
262 0x2E, 0x7C, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
263 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
264 0x2E, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
265 0x2E, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
266 0x69, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
267 0x2E, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71,
268 0x72, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
269 0x2E, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
270 0x7A, 0x2E, 0x2E, 0x2E, 0x5B, 0x2E, 0x2E,
271 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
272 0x2E, 0x2E, 0x2E, 0x2E, 0x5D, 0x2E, 0x2E,
273 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
274 0x49, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
275 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51,
276 0x52, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
277 0x5C, 0x2E, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
278 0x5A, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
279 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
280 0x39, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E
284 EBCDIC_to_ASCII(guint8 *buf, guint bytes)
291 for (i = 0; i < bytes; i++, bufptr++) {
292 *bufptr = EBCDIC_translate_ASCII[*bufptr];
297 EBCDIC_to_ASCII1(guint8 c)
299 return EBCDIC_translate_ASCII[c];
305 * If the ability to capture packets is added to Wiretap, these
306 * routines should be moved to the Wiretap source (with
307 * "get_interface_list()" and "free_interface_list()" renamed to
308 * "wtap_get_interface_list()" and "wtap_free_interface_list()",
309 * and modified to use Wiretap routines to attempt to open the
313 struct search_user_data {
319 search_for_if_cb(gpointer data, gpointer user_data);
322 free_if_cb(gpointer data, gpointer user_data);
325 get_interface_list(int *err, char *err_str)
328 gint nonloopback_pos = 0;
329 struct ifreq *ifr, *last;
331 struct ifreq ifrflags;
332 int sock = socket(AF_INET, SOCK_DGRAM, 0);
333 struct search_user_data user_data;
337 sprintf(err_str, "Error opening socket: %s",
343 * Since we have to grab the interface list all at once, we'll
344 * make plenty of room.
346 ifc.ifc_len = 1024 * sizeof(struct ifreq);
347 ifc.ifc_buf = malloc(ifc.ifc_len);
349 if (ioctl(sock, SIOCGIFCONF, &ifc) < 0 ||
350 ifc.ifc_len < sizeof(struct ifreq)) {
351 sprintf(err_str, "SIOCGIFCONF error getting list of interfaces: %s",
356 ifr = (struct ifreq *) ifc.ifc_req;
357 last = (struct ifreq *) ((char *) ifr + ifc.ifc_len);
360 * Skip addresses that begin with "dummy", or that include
361 * a ":" (the latter are Solaris virtuals).
363 if (strncmp(ifr->ifr_name, "dummy", 5) == 0 ||
364 strchr(ifr->ifr_name, ':') != NULL)
368 * If we already have this interface name on the list,
369 * don't add it (SIOCGIFCONF returns, at least on
370 * BSD-flavored systems, one entry per interface *address*;
371 * if an interface has multiple addresses, we get multiple
374 user_data.name = ifr->ifr_name;
375 user_data.found = FALSE;
376 g_list_foreach(il, search_for_if_cb, &user_data);
381 * Get the interface flags.
383 memset(&ifrflags, 0, sizeof ifrflags);
384 strncpy(ifrflags.ifr_name, ifr->ifr_name,
385 sizeof ifrflags.ifr_name);
386 if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifrflags) < 0) {
389 sprintf(err_str, "SIOCGIFFLAGS error getting flags for interface %s: %s",
390 ifr->ifr_name, strerror(errno));
395 * Skip interfaces that aren't up.
397 if (!(ifrflags.ifr_flags & IFF_UP))
401 * Skip interfaces that we can't open with "libpcap".
402 * Open with the minimum packet size - it appears that the
403 * IRIX SIOCSNOOPLEN "ioctl" may fail if the capture length
404 * supplied is too large, rather than just truncating it.
406 pch = pcap_open_live(ifr->ifr_name, MIN_PACKET_SIZE, 0, 0,
413 * If it's a loopback interface, add it at the end of the
414 * list, otherwise add it after the last non-loopback
415 * interface, so all loopback interfaces go at the end - we
416 * don't want a loopback interface to be the default capture
417 * device unless there are no non-loopback devices.
419 if ((ifrflags.ifr_flags & IFF_LOOPBACK) ||
420 strncmp(ifr->ifr_name, "lo", 2) == 0)
421 il = g_list_insert(il, g_strdup(ifr->ifr_name), -1);
423 il = g_list_insert(il, g_strdup(ifr->ifr_name),
426 * Insert the next non-loopback interface after this
434 ifr = (struct ifreq *) ((char *) ifr + ifr->ifr_addr.sa_len + IFNAMSIZ);
436 ifr = (struct ifreq *) ((char *) ifr + sizeof(struct ifreq));
445 * No interfaces found.
447 *err = NO_INTERFACES_FOUND;
453 g_list_foreach(il, free_if_cb, NULL);
458 *err = CANT_GET_INTERFACE_LIST;
463 search_for_if_cb(gpointer data, gpointer user_data)
465 struct search_user_data *search_user_data = user_data;
467 if (strcmp((char *)data, search_user_data->name) == 0)
468 search_user_data->found = TRUE;
472 free_if_cb(gpointer data, gpointer user_data)
478 free_interface_list(GList *if_list)
480 while (if_list != NULL) {
481 g_free(if_list->data);
482 if_list = g_list_remove_link(if_list, if_list);
486 #endif /* HAVE_LIBPCAP */