"to_str.c" uses "size_t"; include <stdlib.h>, to declare it (necessary
[obnox/wireshark/wip.git] / util.c
1 /* util.c
2  * Utility routines
3  *
4  * $Id: util.c,v 1.51 2001/04/02 09:53:43 guy Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@zing.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * 
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.
15  * 
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.
20  * 
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.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <glib.h>
31
32 #include <stdlib.h>
33 #include <string.h>
34 #include <stdio.h>
35 #include <errno.h>
36
37 #ifdef HAVE_UNISTD_H
38 #include <unistd.h>
39 #endif
40
41 #ifdef HAVE_SYS_TYPES_H
42 #include <sys/types.h>
43 #endif
44
45 #ifdef HAVE_SYS_STAT_H
46 #include <sys/stat.h>
47 #endif
48
49 #ifdef NEED_SNPRINTF_H
50 # include "snprintf.h"
51 #endif
52
53 #ifndef WIN32
54 #include <pwd.h>
55 #endif
56
57 #ifdef NEED_MKSTEMP
58 #include "mkstemp.h"
59 #endif
60
61 #include "util.h"
62
63 #ifdef HAVE_IO_H
64 #include <io.h>
65 typedef int mode_t;     /* for win32 */
66 #endif
67
68 #ifdef HAVE_LIBPCAP
69
70 #ifdef HAVE_SYS_SOCKET_H
71 #include <sys/socket.h>
72 #endif
73
74 #ifdef HAVE_SYS_IOCTL_H
75 #include <sys/ioctl.h>
76 #endif
77
78 #include <pcap.h>
79
80 #ifndef WIN32
81 #include <net/if.h>
82 #endif
83
84 #ifdef HAVE_SYS_SOCKIO_H
85 # include <sys/sockio.h>
86 #endif
87
88 #include "globals.h"
89
90 #endif
91
92 /*
93  * Given a pathname, return:
94  *
95  *      the errno, if an attempt to "stat()" the file fails;
96  *
97  *      EISDIR, if the attempt succeeded and the file turned out
98  *      to be a directory;
99  *
100  *      0, if the attempt succeeded and the file turned out not
101  *      to be a directory.
102  */
103
104 /*
105  * Visual C++ on Win32 systems doesn't define these.  (Old UNIX systems don't
106  * define them either.)
107  *
108  * Visual C++ on Win32 systems doesn't define S_IFIFO, it defines _S_IFIFO.
109  */
110 #ifndef S_ISREG
111 #define S_ISREG(mode)   (((mode) & S_IFMT) == S_IFREG)
112 #endif
113 #ifndef S_IFIFO
114 #define S_IFIFO _S_IFIFO
115 #endif
116 #ifndef S_ISFIFO
117 #define S_ISFIFO(mode)  (((mode) & S_IFMT) == S_IFIFO)
118 #endif
119 #ifndef S_ISDIR
120 #define S_ISDIR(mode)   (((mode) & S_IFMT) == S_IFDIR)
121 #endif
122
123 int
124 test_for_directory(const char *path)
125 {
126         struct stat statb;
127
128         if (stat(path, &statb) < 0)
129                 return errno;
130
131         if (S_ISDIR(statb.st_mode))
132                 return EISDIR;
133         else
134                 return 0;
135 }
136
137 /*
138  * Collect command-line arguments as a string consisting of the arguments,
139  * separated by spaces.
140  */
141 char *
142 get_args_as_string(int argc, char **argv, int optind)
143 {
144         int len;
145         int i;
146         char *argstring;
147
148         /*
149          * Find out how long the string will be.
150          */
151         len = 0;
152         for (i = optind; i < argc; i++) {
153                 len += strlen(argv[i]);
154                 len++;  /* space, or '\0' if this is the last argument */
155         }
156
157         /*
158          * Allocate the buffer for the string.
159          */
160         argstring = g_malloc(len);
161
162         /*
163          * Now construct the string.
164          */
165         strcpy(argstring, "");
166         i = optind;
167         for (;;) {
168                 strcat(argstring, argv[i]);
169                 i++;
170                 if (i == argc)
171                         break;
172                 strcat(argstring, " ");
173         }
174         return argstring;
175 }
176
177 static char *
178 setup_tmpdir(char *dir)
179 {
180         int len = strlen(dir);
181         char *newdir;
182
183         /* Append slash if necessary */
184         if (dir[len - 1] == '/') {
185                 newdir = dir;
186         }
187         else {
188                 newdir = g_malloc(len + 2);
189                 strcpy(newdir, dir);
190                 strcat(newdir, "/");
191         }
192         return newdir;
193 }
194
195 static int
196 try_tempfile(char *namebuf, int namebuflen, const char *dir, const char *pfx)
197 {
198         static const char suffix[] = "XXXXXXXXXX";
199         int namelen = strlen(dir) + strlen(pfx) + sizeof suffix;
200         mode_t old_umask;
201         int tmp_fd;
202
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
206                    something. */
207                 snprintf(namebuf, namebuflen, "%s%s%s", dir, pfx, suffix);
208                 errno = ENAMETOOLONG;
209                 return -1;
210         }
211         strcpy(namebuf, dir);
212         strcat(namebuf, pfx);
213         strcat(namebuf, suffix);
214
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
220            the umask back. */
221         old_umask = umask(0077);
222         tmp_fd = mkstemp(namebuf);
223         umask(old_umask);
224         return tmp_fd;
225 }
226
227 static char *tmpdir = NULL;
228 #ifdef WIN32
229 static char *temp = NULL;
230 #endif
231 static char *E_tmpdir;
232
233 #ifndef P_tmpdir
234 #define P_tmpdir "/var/tmp"
235 #endif
236
237 int
238 create_tempfile(char *namebuf, int namebuflen, const char *pfx)
239 {
240         char *dir;
241         int fd;
242         static gboolean initialized;
243
244         if (!initialized) {
245                 if ((dir = getenv("TMPDIR")) != NULL)
246                         tmpdir = setup_tmpdir(dir);
247 #ifdef WIN32
248                 if ((dir = getenv("TEMP")) != NULL)
249                         temp = setup_tmpdir(dir);
250 #endif
251
252                 E_tmpdir = setup_tmpdir(P_tmpdir);
253                 initialized = TRUE;
254         }
255
256         if (tmpdir != NULL) {
257                 fd = try_tempfile(namebuf, namebuflen, tmpdir, pfx);
258                 if (fd != -1)
259                         return fd;
260         }
261
262 #ifdef WIN32
263         if (temp != NULL) {
264                 fd = try_tempfile(namebuf, namebuflen, temp, pfx);
265                 if (fd != -1)
266                         return fd;
267         }
268 #endif
269
270         fd = try_tempfile(namebuf, namebuflen, E_tmpdir, pfx);
271         if (fd != -1)
272                 return fd;
273
274         return try_tempfile(namebuf, namebuflen, "/tmp", pfx);
275 }
276
277 /* ASCII/EBCDIC conversion tables from
278  * http://www.room42.com/store/computer_center/code_tables.shtml
279  */
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
313 };
314
315 void
316 ASCII_to_EBCDIC(guint8 *buf, guint bytes)
317 {
318         guint   i;
319         guint8  *bufptr;
320
321         bufptr = buf;
322
323         for (i = 0; i < bytes; i++, bufptr++) {
324                 *bufptr = ASCII_translate_EBCDIC[*bufptr];
325         }
326 }
327
328 guint8
329 ASCII_to_EBCDIC1(guint8 c)
330 {
331         return ASCII_translate_EBCDIC[c];
332 }
333
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
367 };
368
369 void
370 EBCDIC_to_ASCII(guint8 *buf, guint bytes)
371 {
372         guint   i;
373         guint8  *bufptr;
374
375         bufptr = buf;
376
377         for (i = 0; i < bytes; i++, bufptr++) {
378                 *bufptr = EBCDIC_translate_ASCII[*bufptr];
379         }
380 }
381
382 guint8
383 EBCDIC_to_ASCII1(guint8 c)
384 {
385         return EBCDIC_translate_ASCII[c];
386 }
387
388 #ifdef HAVE_LIBPCAP
389
390 /*
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
396  * interface.
397  */
398
399 struct search_user_data {
400         char    *name;
401         int     found;
402 };
403
404 static void
405 search_for_if_cb(gpointer data, gpointer user_data);
406
407 static void
408 free_if_cb(gpointer data, gpointer user_data);
409
410 #ifndef WIN32
411 GList *
412 get_interface_list(int *err, char *err_str)
413 {
414         GList  *il = NULL;
415         gint    nonloopback_pos = 0;
416         struct  ifreq *ifr, *last;
417         struct  ifconf ifc;
418         struct  ifreq ifrflags;
419         int     sock = socket(AF_INET, SOCK_DGRAM, 0);
420         struct search_user_data user_data;
421         pcap_t *pch;
422         int len, lastlen;
423         char *buf;
424
425         if (sock < 0) {
426                 sprintf(err_str, "Error opening socket: %s",
427                     strerror(errno));
428                 return NULL;
429         }
430
431         /*
432          * This code came from: W. Richard Stevens: "UNIX Network Programming",
433          * Networking APIs: Sockets and XTI, Vol 1, page 434.
434          */
435         lastlen = 0;
436         len = 100 * sizeof(struct ifreq);
437         for ( ; ; ) {
438                 buf = g_malloc(len);
439                 ifc.ifc_len = len;
440                 ifc.ifc_buf = buf;
441                 memset (buf, 0, len);
442                 if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
443                         if (errno != EINVAL || lastlen != 0) {
444                                 sprintf(err_str,
445                                         "SIOCGIFCONF ioctl error getting list of interfaces: %s",
446                                         strerror(errno));
447                                 goto fail;
448                         }
449                 } else {
450                         if (ifc.ifc_len < sizeof(struct ifreq)) {
451                                 sprintf(err_str,
452                                         "SIOCGIFCONF ioctl gave too small return buffer");
453                                 goto fail;
454                         }
455                         if (ifc.ifc_len == lastlen)
456                                 break;                  /* success, len has not changed */
457                         lastlen = ifc.ifc_len;
458                 }
459                 len += 10 * sizeof(struct ifreq);       /* increment */
460                 g_free(buf);
461         }
462         ifr = (struct ifreq *) ifc.ifc_req;
463         last = (struct ifreq *) ((char *) ifr + ifc.ifc_len);
464         while (ifr < last) {
465                 /*
466                  * Skip addresses that begin with "dummy", or that include
467                  * a ":" (the latter are Solaris virtuals).
468                  */
469                 if (strncmp(ifr->ifr_name, "dummy", 5) == 0 ||
470                     strchr(ifr->ifr_name, ':') != NULL)
471                         goto next;
472
473                 /*
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
478                  * entries for it).
479                  */
480                 user_data.name = ifr->ifr_name;
481                 user_data.found = FALSE;
482                 g_list_foreach(il, search_for_if_cb, &user_data);
483                 if (user_data.found)
484                         goto next;
485
486                 /*
487                  * Get the interface flags.
488                  */
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) {
493                         if (errno == ENXIO)
494                                 goto next;
495                         sprintf(err_str, "SIOCGIFFLAGS error getting flags for interface %s: %s",
496                             ifr->ifr_name, strerror(errno));
497                         goto fail;
498                 }
499
500                 /*
501                  * Skip interfaces that aren't up.
502                  */
503                 if (!(ifrflags.ifr_flags & IFF_UP))
504                         goto next;
505
506                 /*
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.
511                  */
512                 pch = pcap_open_live(ifr->ifr_name, MIN_PACKET_SIZE, 0, 0,
513                     err_str);
514                 if (pch == NULL)
515                         goto next;
516                 pcap_close(pch);
517
518                 /*
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.
524                  */
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);
528                 else {
529                         il = g_list_insert(il, g_strdup(ifr->ifr_name),
530                             nonloopback_pos);
531                         /*
532                          * Insert the next non-loopback interface after this
533                          * one.
534                          */
535                         nonloopback_pos++;
536                 }
537
538         next:
539 #ifdef HAVE_SA_LEN
540                 ifr = (struct ifreq *) ((char *) ifr + ifr->ifr_addr.sa_len + IFNAMSIZ);
541 #else
542                 ifr = (struct ifreq *) ((char *) ifr + sizeof(struct ifreq));
543 #endif
544         }
545
546 #ifdef linux
547         /*
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.
552          */
553         pch = pcap_open_live("any", MIN_PACKET_SIZE, 0, 0, err_str);
554         if (pch != NULL) {
555                 /*
556                  * It worked; we can use the "any" device.
557                  */
558                 il = g_list_insert(il, g_strdup("any"), -1);
559                 pcap_close(pch);
560         }
561 #endif
562
563         g_free(ifc.ifc_buf);
564         close(sock);
565
566         if (il == NULL) {
567                 /*
568                  * No interfaces found.
569                  */
570                 *err = NO_INTERFACES_FOUND;
571         }
572         return il;
573
574 fail:
575         if (il != NULL) {
576                 g_list_foreach(il, free_if_cb, NULL);
577                 g_list_free(il);
578         }
579         g_free(ifc.ifc_buf);
580         close(sock);
581         *err = CANT_GET_INTERFACE_LIST;
582         return NULL;
583 }
584
585 static void
586 search_for_if_cb(gpointer data, gpointer user_data)
587 {
588         struct search_user_data *search_user_data = user_data;
589
590         if (strcmp((char *)data, search_user_data->name) == 0)
591                 search_user_data->found = TRUE;
592 }
593 #else
594 GList *
595 get_interface_list(int *err, char *err_str) {
596   GList  *il = NULL;
597   wchar_t *names;
598   char *win95names; 
599   char newname[255];
600   int i, j, done;
601   
602   names = (wchar_t *)pcap_lookupdev(err_str);
603   i = done = 0;
604
605   if (names) {
606           if (names[0]<256) { 
607                   /* If names[0] is less than 256 it means the first byte is 0
608                      This implies that we are using unicode characters */
609                   do 
610                   { 
611                           j = 0; 
612                           while (names[i] != 0) 
613                                   newname[j++] = names[i++]; 
614                           i++; 
615                           if (names[i] == 0) 
616                                   done = 1; 
617                           newname[j++] = 0; 
618                           il = g_list_append(il, g_strdup(newname)); 
619                   } while (!done); 
620           } 
621           else { 
622                   /* Otherwise we are in Windows 95/98 and using ascii(8 bit)
623                      characters */
624                   do 
625                   { 
626                           win95names=(char *)names; 
627                           j = 0; 
628                           while (win95names[i] != 0) 
629                                   newname[j++] = win95names[i++]; 
630                           i++; 
631                           if (win95names[i] == 0) 
632                                   done = 1; 
633                           newname[j++] = 0; 
634                           il = g_list_append(il, g_strdup(newname)); 
635                   } while (!done); 
636           } 
637   }
638   return(il);
639 }
640 #endif
641
642 static void
643 free_if_cb(gpointer data, gpointer user_data)
644 {
645         g_free(data);
646 }
647
648 void
649 free_interface_list(GList *if_list)
650 {
651         while (if_list != NULL) {
652                 g_free(if_list->data);
653                 if_list = g_list_remove_link(if_list, if_list);
654         }
655 }
656
657 #endif /* HAVE_LIBPCAP */
658
659
660 /* Compute the difference between two seconds/microseconds time stamps. */
661 void
662 compute_timestamp_diff(gint *diffsec, gint *diffusec,
663         guint32 sec1, guint32 usec1, guint32 sec2, guint32 usec2)
664 {
665   if (sec1 == sec2) {
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. */
674
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.
680
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;
688     } else {
689       *diffusec = (usec1 - 1000000) - usec2;
690       (*diffsec)++;
691     }
692   } else {
693     /* Oh, good, we're not caught in a chronosynclastic infindibulum. */
694     *diffsec = sec1 - sec2;
695     if (usec2 <= usec1) {
696       *diffusec = usec1 - usec2;
697     } else {
698       *diffusec = (usec1 + 1000000) - usec2;
699       (*diffsec)--;
700     }
701   }
702 }