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