4 * $Id: util.c,v 1.51 2001/04/02 09:53:43 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
50 # include "snprintf.h"
65 typedef int mode_t; /* for win32 */
70 #ifdef HAVE_SYS_SOCKET_H
71 #include <sys/socket.h>
74 #ifdef HAVE_SYS_IOCTL_H
75 #include <sys/ioctl.h>
84 #ifdef HAVE_SYS_SOCKIO_H
85 # include <sys/sockio.h>
93 * Given a pathname, return:
95 * the errno, if an attempt to "stat()" the file fails;
97 * EISDIR, if the attempt succeeded and the file turned out
100 * 0, if the attempt succeeded and the file turned out not
105 * Visual C++ on Win32 systems doesn't define these. (Old UNIX systems don't
106 * define them either.)
108 * Visual C++ on Win32 systems doesn't define S_IFIFO, it defines _S_IFIFO.
111 #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
114 #define S_IFIFO _S_IFIFO
117 #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
120 #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
124 test_for_directory(const char *path)
128 if (stat(path, &statb) < 0)
131 if (S_ISDIR(statb.st_mode))
138 * Collect command-line arguments as a string consisting of the arguments,
139 * separated by spaces.
142 get_args_as_string(int argc, char **argv, int optind)
149 * Find out how long the string will be.
152 for (i = optind; i < argc; i++) {
153 len += strlen(argv[i]);
154 len++; /* space, or '\0' if this is the last argument */
158 * Allocate the buffer for the string.
160 argstring = g_malloc(len);
163 * Now construct the string.
165 strcpy(argstring, "");
168 strcat(argstring, argv[i]);
172 strcat(argstring, " ");
178 setup_tmpdir(char *dir)
180 int len = strlen(dir);
183 /* Append slash if necessary */
184 if (dir[len - 1] == '/') {
188 newdir = g_malloc(len + 2);
196 try_tempfile(char *namebuf, int namebuflen, const char *dir, const char *pfx)
198 static const char suffix[] = "XXXXXXXXXX";
199 int namelen = strlen(dir) + strlen(pfx) + sizeof suffix;
203 if (namebuflen < namelen) {
204 /* Stick in a truncated name, so that if this error is
205 reported with the file name, you at least get
207 snprintf(namebuf, namebuflen, "%s%s%s", dir, pfx, suffix);
208 errno = ENAMETOOLONG;
211 strcpy(namebuf, dir);
212 strcat(namebuf, pfx);
213 strcat(namebuf, suffix);
215 /* The Single UNIX Specification doesn't say that "mkstemp()"
216 creates the temporary file with mode rw-------, so we
217 won't assume that all UNIXes will do so; instead, we set
218 the umask to 0077 to take away all group and other
219 permissions, attempt to create the file, and then put
221 old_umask = umask(0077);
222 tmp_fd = mkstemp(namebuf);
227 static char *tmpdir = NULL;
229 static char *temp = NULL;
231 static char *E_tmpdir;
234 #define P_tmpdir "/var/tmp"
238 create_tempfile(char *namebuf, int namebuflen, const char *pfx)
242 static gboolean initialized;
245 if ((dir = getenv("TMPDIR")) != NULL)
246 tmpdir = setup_tmpdir(dir);
248 if ((dir = getenv("TEMP")) != NULL)
249 temp = setup_tmpdir(dir);
252 E_tmpdir = setup_tmpdir(P_tmpdir);
256 if (tmpdir != NULL) {
257 fd = try_tempfile(namebuf, namebuflen, tmpdir, pfx);
264 fd = try_tempfile(namebuf, namebuflen, temp, pfx);
270 fd = try_tempfile(namebuf, namebuflen, E_tmpdir, pfx);
274 return try_tempfile(namebuf, namebuflen, "/tmp", pfx);
277 /* ASCII/EBCDIC conversion tables from
278 * http://www.room42.com/store/computer_center/code_tables.shtml
280 static guint8 ASCII_translate_EBCDIC [ 256 ] = {
281 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
282 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
283 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
284 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
285 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, 0x4D,
286 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
287 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
288 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
289 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8,
290 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
291 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
292 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D,
293 0x7D, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
294 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
295 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
296 0xA8, 0xA9, 0xC0, 0x6A, 0xD0, 0xA1, 0x4B,
297 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
298 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
299 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
300 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
301 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
302 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
303 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
304 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
305 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
306 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
307 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
308 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
309 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
310 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
311 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
312 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B
316 ASCII_to_EBCDIC(guint8 *buf, guint bytes)
323 for (i = 0; i < bytes; i++, bufptr++) {
324 *bufptr = ASCII_translate_EBCDIC[*bufptr];
329 ASCII_to_EBCDIC1(guint8 c)
331 return ASCII_translate_EBCDIC[c];
334 static guint8 EBCDIC_translate_ASCII [ 256 ] = {
335 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
336 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
337 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
338 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
339 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
340 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
341 0x2E, 0x2E, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
342 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x2E, 0x3F,
343 0x20, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
344 0x2E, 0x2E, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
345 0x26, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
346 0x2E, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E,
347 0x2D, 0x2F, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
348 0x2E, 0x7C, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
349 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
350 0x2E, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
351 0x2E, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
352 0x69, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
353 0x2E, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71,
354 0x72, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
355 0x2E, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
356 0x7A, 0x2E, 0x2E, 0x2E, 0x5B, 0x2E, 0x2E,
357 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
358 0x2E, 0x2E, 0x2E, 0x2E, 0x5D, 0x2E, 0x2E,
359 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
360 0x49, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
361 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51,
362 0x52, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
363 0x5C, 0x2E, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
364 0x5A, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
365 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
366 0x39, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E
370 EBCDIC_to_ASCII(guint8 *buf, guint bytes)
377 for (i = 0; i < bytes; i++, bufptr++) {
378 *bufptr = EBCDIC_translate_ASCII[*bufptr];
383 EBCDIC_to_ASCII1(guint8 c)
385 return EBCDIC_translate_ASCII[c];
391 * If the ability to capture packets is added to Wiretap, these
392 * routines should be moved to the Wiretap source (with
393 * "get_interface_list()" and "free_interface_list()" renamed to
394 * "wtap_get_interface_list()" and "wtap_free_interface_list()",
395 * and modified to use Wiretap routines to attempt to open the
399 struct search_user_data {
405 search_for_if_cb(gpointer data, gpointer user_data);
408 free_if_cb(gpointer data, gpointer user_data);
412 get_interface_list(int *err, char *err_str)
415 gint nonloopback_pos = 0;
416 struct ifreq *ifr, *last;
418 struct ifreq ifrflags;
419 int sock = socket(AF_INET, SOCK_DGRAM, 0);
420 struct search_user_data user_data;
426 sprintf(err_str, "Error opening socket: %s",
432 * This code came from: W. Richard Stevens: "UNIX Network Programming",
433 * Networking APIs: Sockets and XTI, Vol 1, page 434.
436 len = 100 * sizeof(struct ifreq);
441 memset (buf, 0, len);
442 if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
443 if (errno != EINVAL || lastlen != 0) {
445 "SIOCGIFCONF ioctl error getting list of interfaces: %s",
450 if (ifc.ifc_len < sizeof(struct ifreq)) {
452 "SIOCGIFCONF ioctl gave too small return buffer");
455 if (ifc.ifc_len == lastlen)
456 break; /* success, len has not changed */
457 lastlen = ifc.ifc_len;
459 len += 10 * sizeof(struct ifreq); /* increment */
462 ifr = (struct ifreq *) ifc.ifc_req;
463 last = (struct ifreq *) ((char *) ifr + ifc.ifc_len);
466 * Skip addresses that begin with "dummy", or that include
467 * a ":" (the latter are Solaris virtuals).
469 if (strncmp(ifr->ifr_name, "dummy", 5) == 0 ||
470 strchr(ifr->ifr_name, ':') != NULL)
474 * If we already have this interface name on the list,
475 * don't add it (SIOCGIFCONF returns, at least on
476 * BSD-flavored systems, one entry per interface *address*;
477 * if an interface has multiple addresses, we get multiple
480 user_data.name = ifr->ifr_name;
481 user_data.found = FALSE;
482 g_list_foreach(il, search_for_if_cb, &user_data);
487 * Get the interface flags.
489 memset(&ifrflags, 0, sizeof ifrflags);
490 strncpy(ifrflags.ifr_name, ifr->ifr_name,
491 sizeof ifrflags.ifr_name);
492 if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifrflags) < 0) {
495 sprintf(err_str, "SIOCGIFFLAGS error getting flags for interface %s: %s",
496 ifr->ifr_name, strerror(errno));
501 * Skip interfaces that aren't up.
503 if (!(ifrflags.ifr_flags & IFF_UP))
507 * Skip interfaces that we can't open with "libpcap".
508 * Open with the minimum packet size - it appears that the
509 * IRIX SIOCSNOOPLEN "ioctl" may fail if the capture length
510 * supplied is too large, rather than just truncating it.
512 pch = pcap_open_live(ifr->ifr_name, MIN_PACKET_SIZE, 0, 0,
519 * If it's a loopback interface, add it at the end of the
520 * list, otherwise add it after the last non-loopback
521 * interface, so all loopback interfaces go at the end - we
522 * don't want a loopback interface to be the default capture
523 * device unless there are no non-loopback devices.
525 if ((ifrflags.ifr_flags & IFF_LOOPBACK) ||
526 strncmp(ifr->ifr_name, "lo", 2) == 0)
527 il = g_list_insert(il, g_strdup(ifr->ifr_name), -1);
529 il = g_list_insert(il, g_strdup(ifr->ifr_name),
532 * Insert the next non-loopback interface after this
540 ifr = (struct ifreq *) ((char *) ifr + ifr->ifr_addr.sa_len + IFNAMSIZ);
542 ifr = (struct ifreq *) ((char *) ifr + sizeof(struct ifreq));
548 * OK, maybe we have support for the "any" device, to do a cooked
549 * capture on all interfaces at once.
550 * Try opening it and, if that succeeds, add it to the end of
551 * the list of interfaces.
553 pch = pcap_open_live("any", MIN_PACKET_SIZE, 0, 0, err_str);
556 * It worked; we can use the "any" device.
558 il = g_list_insert(il, g_strdup("any"), -1);
568 * No interfaces found.
570 *err = NO_INTERFACES_FOUND;
576 g_list_foreach(il, free_if_cb, NULL);
581 *err = CANT_GET_INTERFACE_LIST;
586 search_for_if_cb(gpointer data, gpointer user_data)
588 struct search_user_data *search_user_data = user_data;
590 if (strcmp((char *)data, search_user_data->name) == 0)
591 search_user_data->found = TRUE;
595 get_interface_list(int *err, char *err_str) {
602 names = (wchar_t *)pcap_lookupdev(err_str);
607 /* If names[0] is less than 256 it means the first byte is 0
608 This implies that we are using unicode characters */
612 while (names[i] != 0)
613 newname[j++] = names[i++];
618 il = g_list_append(il, g_strdup(newname));
622 /* Otherwise we are in Windows 95/98 and using ascii(8 bit)
626 win95names=(char *)names;
628 while (win95names[i] != 0)
629 newname[j++] = win95names[i++];
631 if (win95names[i] == 0)
634 il = g_list_append(il, g_strdup(newname));
643 free_if_cb(gpointer data, gpointer user_data)
649 free_interface_list(GList *if_list)
651 while (if_list != NULL) {
652 g_free(if_list->data);
653 if_list = g_list_remove_link(if_list, if_list);
657 #endif /* HAVE_LIBPCAP */
660 /* Compute the difference between two seconds/microseconds time stamps. */
662 compute_timestamp_diff(gint *diffsec, gint *diffusec,
663 guint32 sec1, guint32 usec1, guint32 sec2, guint32 usec2)
666 /* The seconds part of the first time is the same as the seconds
667 part of the second time, so if the microseconds part of the first
668 time is less than the microseconds part of the second time, the
669 first time is before the second time. The microseconds part of
670 the delta should just be the difference between the microseconds
671 part of the first time and the microseconds part of the second
672 time; don't adjust the seconds part of the delta, as it's OK if
673 the microseconds part is negative. */
675 *diffsec = sec1 - sec2;
676 *diffusec = usec1 - usec2;
677 } else if (sec1 <= sec2) {
678 /* The seconds part of the first time is less than the seconds part
679 of the second time, so the first time is before the second time.
681 Both the "seconds" and "microseconds" value of the delta
682 should have the same sign, so if the difference between the
683 microseconds values would be *positive*, subtract 1,000,000
684 from it, and add one to the seconds value. */
685 *diffsec = sec1 - sec2;
686 if (usec2 >= usec1) {
687 *diffusec = usec1 - usec2;
689 *diffusec = (usec1 - 1000000) - usec2;
693 /* Oh, good, we're not caught in a chronosynclastic infindibulum. */
694 *diffsec = sec1 - sec2;
695 if (usec2 <= usec1) {
696 *diffusec = usec1 - usec2;
698 *diffusec = (usec1 + 1000000) - usec2;