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