Update the Win32 Nmakefiles to reflect the move of the color code into
[obnox/wireshark/wip.git] / util.c
1 /* util.c
2  * Utility routines
3  *
4  * $Id: util.c,v 1.36 2000/02/09 19:17:52 gram 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 #ifndef WIN32
420 GList *
421 get_interface_list(int *err, char *err_str)
422 {
423         GList  *il = NULL;
424         gint    nonloopback_pos = 0;
425         struct  ifreq *ifr, *last;
426         struct  ifconf ifc;
427         struct  ifreq ifrflags;
428         int     sock = socket(AF_INET, SOCK_DGRAM, 0);
429         struct search_user_data user_data;
430         pcap_t *pch;
431
432         if (sock < 0) {
433                 sprintf(err_str, "Error opening socket: %s",
434                     strerror(errno));
435                 return NULL;
436         }
437
438         /*
439          * Since we have to grab the interface list all at once, we'll
440          * make plenty of room.
441          */
442         ifc.ifc_len = 1024 * sizeof(struct ifreq);
443         ifc.ifc_buf = malloc(ifc.ifc_len);
444
445         if (ioctl(sock, SIOCGIFCONF, &ifc) < 0 ||
446             ifc.ifc_len < sizeof(struct ifreq)) {
447                 sprintf(err_str, "SIOCGIFCONF error getting list of interfaces: %s",
448                     strerror(errno));
449                 goto fail;
450          }
451
452         ifr = (struct ifreq *) ifc.ifc_req;
453         last = (struct ifreq *) ((char *) ifr + ifc.ifc_len);
454         while (ifr < last) {
455                 /*
456                  * Skip addresses that begin with "dummy", or that include
457                  * a ":" (the latter are Solaris virtuals).
458                  */
459                 if (strncmp(ifr->ifr_name, "dummy", 5) == 0 ||
460                     strchr(ifr->ifr_name, ':') != NULL)
461                         goto next;
462
463                 /*
464                  * If we already have this interface name on the list,
465                  * don't add it (SIOCGIFCONF returns, at least on
466                  * BSD-flavored systems, one entry per interface *address*;
467                  * if an interface has multiple addresses, we get multiple
468                  * entries for it).
469                  */
470                 user_data.name = ifr->ifr_name;
471                 user_data.found = FALSE;
472                 g_list_foreach(il, search_for_if_cb, &user_data);
473                 if (user_data.found)
474                         goto next;
475
476                 /*
477                  * Get the interface flags.
478                  */
479                 memset(&ifrflags, 0, sizeof ifrflags);
480                 strncpy(ifrflags.ifr_name, ifr->ifr_name,
481                     sizeof ifrflags.ifr_name);
482                 if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifrflags) < 0) {
483                         if (errno == ENXIO)
484                                 goto next;
485                         sprintf(err_str, "SIOCGIFFLAGS error getting flags for interface %s: %s",
486                             ifr->ifr_name, strerror(errno));
487                         goto fail;
488                 }
489
490                 /*
491                  * Skip interfaces that aren't up.
492                  */
493                 if (!(ifrflags.ifr_flags & IFF_UP))
494                         goto next;
495
496                 /*
497                  * Skip interfaces that we can't open with "libpcap".
498                  * Open with the minimum packet size - it appears that the
499                  * IRIX SIOCSNOOPLEN "ioctl" may fail if the capture length
500                  * supplied is too large, rather than just truncating it.
501                  */
502                 pch = pcap_open_live(ifr->ifr_name, MIN_PACKET_SIZE, 0, 0,
503                     err_str);
504                 if (pch == NULL)
505                         goto next;
506                 pcap_close(pch);
507
508                 /*
509                  * If it's a loopback interface, add it at the end of the
510                  * list, otherwise add it after the last non-loopback
511                  * interface, so all loopback interfaces go at the end - we
512                  * don't want a loopback interface to be the default capture
513                  * device unless there are no non-loopback devices.
514                  */
515                 if ((ifrflags.ifr_flags & IFF_LOOPBACK) ||
516                     strncmp(ifr->ifr_name, "lo", 2) == 0)
517                         il = g_list_insert(il, g_strdup(ifr->ifr_name), -1);
518                 else {
519                         il = g_list_insert(il, g_strdup(ifr->ifr_name),
520                             nonloopback_pos);
521                         /*
522                          * Insert the next non-loopback interface after this
523                          * one.
524                          */
525                         nonloopback_pos++;
526                 }
527
528         next:
529 #ifdef HAVE_SA_LEN
530                 ifr = (struct ifreq *) ((char *) ifr + ifr->ifr_addr.sa_len + IFNAMSIZ);
531 #else
532                 ifr = (struct ifreq *) ((char *) ifr + sizeof(struct ifreq));
533 #endif
534         }
535
536         free(ifc.ifc_buf);
537         close(sock);
538
539         if (il == NULL) {
540                 /*
541                  * No interfaces found.
542                  */
543                 *err = NO_INTERFACES_FOUND;
544         }
545         return il;
546
547 fail:
548         if (il != NULL) {
549                 g_list_foreach(il, free_if_cb, NULL);
550                 g_list_free(il);
551         }
552         free(ifc.ifc_buf);
553         close(sock);
554         *err = CANT_GET_INTERFACE_LIST;
555         return NULL;
556 }
557
558 static void
559 search_for_if_cb(gpointer data, gpointer user_data)
560 {
561         struct search_user_data *search_user_data = user_data;
562
563         if (strcmp((char *)data, search_user_data->name) == 0)
564                 search_user_data->found = TRUE;
565 }
566 #else
567 GList *
568 get_interface_list(int *err, char *err_str) {
569   GList  *il = NULL;
570   wchar_t *names;
571   char newname[255];
572   int i, j, done;
573   
574   names = (wchar_t *)pcap_lookupdev(err_str);
575   i = done = 0;
576
577   if (names)
578      do
579      {
580         j = 0;
581         while (names[i] != 0)
582            newname[j++] = names[i++];
583         i++;
584         if (names[i] == 0)
585            done = 1;
586         newname[j++] = 0;
587         il = g_list_append(il, g_strdup(newname));
588      } while (!done);
589   
590   return(il);
591 }
592 #endif
593
594 static void
595 free_if_cb(gpointer data, gpointer user_data)
596 {
597         g_free(data);
598 }
599
600 void
601 free_interface_list(GList *if_list)
602 {
603         while (if_list != NULL) {
604                 g_free(if_list->data);
605                 if_list = g_list_remove_link(if_list, if_list);
606         }
607 }
608
609 #endif /* HAVE_LIBPCAP */
610
611 const char*
612 get_home_dir(void)
613 {
614         char *env_value;
615         static const char *home = NULL;
616 #ifndef WIN32
617         struct passwd *pwd;
618 #endif
619
620         /* Return the cached value, if available */
621         if (home)
622                 return home;
623
624         env_value = getenv("HOME");
625
626         if (env_value) {
627                 home = env_value;
628         }
629         else {
630 #ifdef WIN32
631                 /* XXX - on NT, get the user name and append it to
632                    "C:\winnt\profiles\"?
633                    What about Windows 9x? */
634                 home = "C:";
635 #else
636                 pwd = getpwuid(getuid());
637                 if (pwd != NULL) {
638                         /* This is cached, so we don't need to worry
639                            about allocating multiple ones of them. */
640                         home = g_strdup(pwd->pw_dir);
641                 }
642                 else
643                         home = "/tmp";
644 #endif
645         }
646
647         return home;
648 }