In Win32, treat both '/' and '\' as pathname separators.
[obnox/wireshark/wip.git] / util.c
1 /* util.c
2  * Utility routines
3  *
4  * $Id: util.c,v 1.30 2000/01/26 04:56:14 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 # ifdef HAVE_STDARG_H
51 #  include <stdarg.h>
52 # else
53 #  include <varargs.h>
54 # endif
55 # include "snprintf.h"
56 #endif
57
58 #ifdef NEED_MKSTEMP
59 #include "mkstemp.h"
60 #endif
61
62 #include "util.h"
63
64 #ifdef HAVE_IO_H
65 #include <io.h>
66 typedef int mode_t;     /* for win32 */
67 #endif
68
69 #ifdef HAVE_LIBPCAP
70
71 #ifdef HAVE_SYS_SOCKET_H
72 #include <sys/socket.h>
73 #endif
74
75 #ifdef HAVE_SYS_IOCTL_H
76 #include <sys/ioctl.h>
77 #endif
78
79 #ifdef HAVE_NET_IF_H
80 #include <net/if.h>
81 #endif
82
83 #ifdef HAVE_SYS_SOCKIO_H
84 # include <sys/sockio.h>
85 #endif
86
87 #include "globals.h"
88
89 #endif
90
91 /*
92  * Given a pathname, return a pointer to the last pathname separator
93  * character in the pathname, or NULL if the pathname contains no
94  * separators.
95  */
96 static char *
97 find_last_pathname_separator(char *path)
98 {
99         char *separator;
100
101 #ifdef WIN32
102         char c;
103
104         /*
105          * We have to scan for '\' or '/'.
106          * Get to the end of the string.
107          */
108         separator = path + strlen(path);        /* points to ending '\0' */
109         while (separator > path) {
110                 c = *--separator;
111                 if (c == '\\' || c == '/')
112                         return separator;       /* found it */
113         }
114
115         /*
116          * OK, we didn't find any, so no directories - but there might
117          * be a drive letter....
118          */
119         return strchr(path, ':');
120 #else
121         separator = strrchr(path, '/');
122 #endif
123         return separator;
124 }
125
126 /*
127  * Given a pathname, return the last component.
128  */
129 char *
130 get_basename(char *path)
131 {
132         char *filename;
133
134         filename = find_last_pathname_separator(path);
135         if (filename == NULL) {
136                 /*
137                  * There're no directories, drive letters, etc. in the
138                  * name; the pathname *is* the file name.
139                  */
140                 filename = path;
141         } else {
142                 /*
143                  * Skip past the pathname or drive letter separator.
144                  */
145                 filename++;
146         }
147         return filename;
148 }
149
150 /*
151  * Given a pathname, return a string containing everything but the
152  * last component.  NOTE: this overwrites the pathname handed into
153  * it....
154  */
155 char *
156 get_dirname(char *path)
157 {
158         char *separator;
159
160         separator = find_last_pathname_separator(path);
161         if (separator == NULL) {
162                 /*
163                  * There're no directories, drive letters, etc. in the
164                  * name; there is no directory path to return.
165                  */
166                 return NULL;
167         }
168
169         /*
170          * Get rid of the last pathname separator and the final file
171          * name following it.
172          */
173         *separator = '\0';
174
175         /*
176          * "path" now contains the pathname of the directory containing
177          * the file/directory to which it referred.
178          */
179         return path;
180 }
181
182 static char *
183 setup_tmpdir(char *dir)
184 {
185         int len = strlen(dir);
186         char *newdir;
187
188         /* Append slash if necessary */
189         if (dir[len - 1] == '/') {
190                 newdir = dir;
191         }
192         else {
193                 newdir = g_malloc(len + 2);
194                 strcpy(newdir, dir);
195                 strcat(newdir, "/");
196         }
197         return newdir;
198 }
199
200 static int
201 try_tempfile(char *namebuf, int namebuflen, const char *dir, const char *pfx)
202 {
203         static const char suffix[] = "XXXXXXXXXX";
204         int namelen = strlen(dir) + strlen(pfx) + sizeof suffix;
205         mode_t old_umask;
206         int tmp_fd;
207
208         if (namebuflen < namelen) {
209                 /* Stick in a truncated name, so that if this error is
210                    reported with the file name, you at least get
211                    something. */
212                 snprintf(namebuf, namebuflen, "%s%s%s", dir, pfx, suffix);
213                 errno = ENAMETOOLONG;
214                 return -1;
215         }
216         strcpy(namebuf, dir);
217         strcat(namebuf, pfx);
218         strcat(namebuf, suffix);
219
220         /* The Single UNIX Specification doesn't say that "mkstemp()"
221            creates the temporary file with mode rw-------, so we
222            won't assume that all UNIXes will do so; instead, we set
223            the umask to 0077 to take away all group and other
224            permissions, attempt to create the file, and then put
225            the umask back. */
226         old_umask = umask(0077);
227         tmp_fd = mkstemp(namebuf);
228         umask(old_umask);
229         return tmp_fd;
230 }
231
232 static char *tmpdir = NULL;
233 #ifdef WIN32
234 static char *temp = NULL;
235 #endif
236 static char *E_tmpdir;
237
238 #ifndef P_tmpdir
239 #define P_tmpdir "/var/tmp"
240 #endif
241
242 int
243 create_tempfile(char *namebuf, int namebuflen, const char *pfx)
244 {
245         char *dir;
246         int fd;
247         static gboolean initialized;
248
249         if (!initialized) {
250                 if ((dir = getenv("TMPDIR")) != NULL)
251                         tmpdir = setup_tmpdir(dir);
252 #ifdef WIN32
253                 if ((dir = getenv("TEMP")) != NULL)
254                         temp = setup_tmpdir(dir);
255 #endif
256
257                 E_tmpdir = setup_tmpdir(P_tmpdir);
258                 initialized = TRUE;
259         }
260
261         if (tmpdir != NULL) {
262                 fd = try_tempfile(namebuf, namebuflen, tmpdir, pfx);
263                 if (fd != -1)
264                         return fd;
265         }
266
267 #ifdef WIN32
268         if (temp != NULL) {
269                 fd = try_tempfile(namebuf, namebuflen, temp, pfx);
270                 if (fd != -1)
271                         return fd;
272         }
273 #endif
274
275         fd = try_tempfile(namebuf, namebuflen, E_tmpdir, pfx);
276         if (fd != -1)
277                 return fd;
278
279         return try_tempfile(namebuf, namebuflen, "/tmp", pfx);
280 }
281
282 /* ASCII/EBCDIC conversion tables from
283  * http://www.room42.com/store/computer_center/code_tables.shtml
284  */
285 static guint8 ASCII_translate_EBCDIC [ 256 ] = {
286     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
287     0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
288     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
289     0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
290     0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, 0x4D,
291     0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
292     0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
293     0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
294     0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8,
295     0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
296     0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
297     0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D,
298     0x7D, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
299     0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
300     0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
301     0xA8, 0xA9, 0xC0, 0x6A, 0xD0, 0xA1, 0x4B,
302     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
303     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
304     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
305     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
306     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
307     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
308     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
309     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
310     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
311     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
312     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
313     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
314     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
315     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
316     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
317     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B
318 };
319
320 void
321 ASCII_to_EBCDIC(guint8 *buf, guint bytes)
322 {
323         guint   i;
324         guint8  *bufptr;
325
326         bufptr = buf;
327
328         for (i = 0; i < bytes; i++, bufptr++) {
329                 *bufptr = ASCII_translate_EBCDIC[*bufptr];
330         }
331 }
332
333 guint8
334 ASCII_to_EBCDIC1(guint8 c)
335 {
336         return ASCII_translate_EBCDIC[c];
337 }
338
339 static guint8 EBCDIC_translate_ASCII [ 256 ] = {
340     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
341     0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
342     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
343     0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
344     0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
345     0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
346     0x2E, 0x2E, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
347     0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x2E, 0x3F,
348     0x20, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
349     0x2E, 0x2E, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
350     0x26, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
351     0x2E, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E,
352     0x2D, 0x2F, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
353     0x2E, 0x7C, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
354     0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
355     0x2E, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
356     0x2E, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
357     0x69, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
358     0x2E, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71,
359     0x72, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
360     0x2E, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
361     0x7A, 0x2E, 0x2E, 0x2E, 0x5B, 0x2E, 0x2E,
362     0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
363     0x2E, 0x2E, 0x2E, 0x2E, 0x5D, 0x2E, 0x2E,
364     0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
365     0x49, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
366     0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51,                                             
367     0x52, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
368     0x5C, 0x2E, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
369     0x5A, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
370     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,                 
371     0x39, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E
372 };
373
374 void
375 EBCDIC_to_ASCII(guint8 *buf, guint bytes)
376 {
377         guint   i;
378         guint8  *bufptr;
379
380         bufptr = buf;
381
382         for (i = 0; i < bytes; i++, bufptr++) {
383                 *bufptr = EBCDIC_translate_ASCII[*bufptr];
384         }
385 }
386
387 guint8
388 EBCDIC_to_ASCII1(guint8 c)
389 {
390         return EBCDIC_translate_ASCII[c];
391 }
392
393 #ifdef HAVE_LIBPCAP
394
395 /*
396  * If the ability to capture packets is added to Wiretap, these
397  * routines should be moved to the Wiretap source (with
398  * "get_interface_list()" and "free_interface_list()" renamed to
399  * "wtap_get_interface_list()" and "wtap_free_interface_list()",
400  * and modified to use Wiretap routines to attempt to open the
401  * interface.
402  */
403
404 struct search_user_data {
405         char    *name;
406         int     found;
407 };
408
409 static void
410 search_for_if_cb(gpointer data, gpointer user_data);
411
412 static void
413 free_if_cb(gpointer data, gpointer user_data);
414
415 GList *
416 get_interface_list(int *err, char *err_str)
417 {
418         GList  *il = NULL;
419         gint    nonloopback_pos = 0;
420         struct  ifreq *ifr, *last;
421         struct  ifconf ifc;
422         struct  ifreq ifrflags;
423         int     sock = socket(AF_INET, SOCK_DGRAM, 0);
424         struct search_user_data user_data;
425         pcap_t *pch;
426
427         if (sock < 0) {
428                 sprintf(err_str, "Error opening socket: %s",
429                     strerror(errno));
430                 return NULL;
431         }
432
433         /*
434          * Since we have to grab the interface list all at once, we'll
435          * make plenty of room.
436          */
437         ifc.ifc_len = 1024 * sizeof(struct ifreq);
438         ifc.ifc_buf = malloc(ifc.ifc_len);
439
440         if (ioctl(sock, SIOCGIFCONF, &ifc) < 0 ||
441             ifc.ifc_len < sizeof(struct ifreq)) {
442                 sprintf(err_str, "SIOCGIFCONF error getting list of interfaces: %s",
443                     strerror(errno));
444                 goto fail;
445          }
446
447         ifr = (struct ifreq *) ifc.ifc_req;
448         last = (struct ifreq *) ((char *) ifr + ifc.ifc_len);
449         while (ifr < last) {
450                 /*
451                  * Skip addresses that begin with "dummy", or that include
452                  * a ":" (the latter are Solaris virtuals).
453                  */
454                 if (strncmp(ifr->ifr_name, "dummy", 5) == 0 ||
455                     strchr(ifr->ifr_name, ':') != NULL)
456                         goto next;
457
458                 /*
459                  * If we already have this interface name on the list,
460                  * don't add it (SIOCGIFCONF returns, at least on
461                  * BSD-flavored systems, one entry per interface *address*;
462                  * if an interface has multiple addresses, we get multiple
463                  * entries for it).
464                  */
465                 user_data.name = ifr->ifr_name;
466                 user_data.found = FALSE;
467                 g_list_foreach(il, search_for_if_cb, &user_data);
468                 if (user_data.found)
469                         goto next;
470
471                 /*
472                  * Get the interface flags.
473                  */
474                 memset(&ifrflags, 0, sizeof ifrflags);
475                 strncpy(ifrflags.ifr_name, ifr->ifr_name,
476                     sizeof ifrflags.ifr_name);
477                 if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifrflags) < 0) {
478                         if (errno == ENXIO)
479                                 goto next;
480                         sprintf(err_str, "SIOCGIFFLAGS error getting flags for interface %s: %s",
481                             ifr->ifr_name, strerror(errno));
482                         goto fail;
483                 }
484
485                 /*
486                  * Skip interfaces that aren't up.
487                  */
488                 if (!(ifrflags.ifr_flags & IFF_UP))
489                         goto next;
490
491                 /*
492                  * Skip interfaces that we can't open with "libpcap".
493                  * Open with the minimum packet size - it appears that the
494                  * IRIX SIOCSNOOPLEN "ioctl" may fail if the capture length
495                  * supplied is too large, rather than just truncating it.
496                  */
497                 pch = pcap_open_live(ifr->ifr_name, MIN_PACKET_SIZE, 0, 0,
498                     err_str);
499                 if (pch == NULL)
500                         goto next;
501                 pcap_close(pch);
502
503                 /*
504                  * If it's a loopback interface, add it at the end of the
505                  * list, otherwise add it after the last non-loopback
506                  * interface, so all loopback interfaces go at the end - we
507                  * don't want a loopback interface to be the default capture
508                  * device unless there are no non-loopback devices.
509                  */
510                 if ((ifrflags.ifr_flags & IFF_LOOPBACK) ||
511                     strncmp(ifr->ifr_name, "lo", 2) == 0)
512                         il = g_list_insert(il, g_strdup(ifr->ifr_name), -1);
513                 else {
514                         il = g_list_insert(il, g_strdup(ifr->ifr_name),
515                             nonloopback_pos);
516                         /*
517                          * Insert the next non-loopback interface after this
518                          * one.
519                          */
520                         nonloopback_pos++;
521                 }
522
523         next:
524 #ifdef HAVE_SA_LEN
525                 ifr = (struct ifreq *) ((char *) ifr + ifr->ifr_addr.sa_len + IFNAMSIZ);
526 #else
527                 ifr = (struct ifreq *) ((char *) ifr + sizeof(struct ifreq));
528 #endif
529         }
530
531         free(ifc.ifc_buf);
532         close(sock);
533
534         if (il == NULL) {
535                 /*
536                  * No interfaces found.
537                  */
538                 *err = NO_INTERFACES_FOUND;
539         }
540         return il;
541
542 fail:
543         if (il != NULL) {
544                 g_list_foreach(il, free_if_cb, NULL);
545                 g_list_free(il);
546         }
547         free(ifc.ifc_buf);
548         close(sock);
549         *err = CANT_GET_INTERFACE_LIST;
550         return NULL;
551 }
552
553 static void
554 search_for_if_cb(gpointer data, gpointer user_data)
555 {
556         struct search_user_data *search_user_data = user_data;
557
558         if (strcmp((char *)data, search_user_data->name) == 0)
559                 search_user_data->found = TRUE;
560 }
561
562 static void
563 free_if_cb(gpointer data, gpointer user_data)
564 {
565         g_free(data);
566 }
567
568 void
569 free_interface_list(GList *if_list)
570 {
571         while (if_list != NULL) {
572                 g_free(if_list->data);
573                 if_list = g_list_remove_link(if_list, if_list);
574         }
575 }
576
577 #endif /* HAVE_LIBPCAP */