4 * $Id: util.c,v 1.77 2004/02/07 04:25:16 guy Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
40 #ifdef HAVE_SYS_STAT_H
44 #ifdef NEED_SNPRINTF_H
45 # include "snprintf.h"
55 typedef int mode_t; /* for win32 */
56 #endif /* __MINGW32__ */
57 #endif /* HAVE_IO_H */
60 * This has to come after the include of <pcap.h>, as the include of
61 * <pcap.h> might cause <winsock2.h> to be included, and if we've
62 * already included <winsock.h> as a result of including <windows.h>,
63 * we get a bunch of redefinitions.
72 * Collect command-line arguments as a string consisting of the arguments,
73 * separated by spaces.
76 get_args_as_string(int argc, char **argv, int optind)
83 * Find out how long the string will be.
86 for (i = optind; i < argc; i++) {
87 len += strlen(argv[i]);
88 len++; /* space, or '\0' if this is the last argument */
92 * Allocate the buffer for the string.
94 argstring = g_malloc(len);
97 * Now construct the string.
99 strcpy(argstring, "");
102 strcat(argstring, argv[i]);
106 strcat(argstring, " ");
112 setup_tmpdir(char *dir)
114 int len = strlen(dir);
117 /* Append slash if necessary */
118 if (dir[len - 1] == '/') {
122 newdir = g_malloc(len + 2);
130 try_tempfile(char *namebuf, int namebuflen, const char *dir, const char *pfx)
132 static const char suffix[] = "XXXXXXXXXX";
133 int namelen = strlen(dir) + strlen(pfx) + sizeof suffix;
137 if (namebuflen < namelen) {
138 /* Stick in a truncated name, so that if this error is
139 reported with the file name, you at least get
141 snprintf(namebuf, namebuflen, "%s%s%s", dir, pfx, suffix);
142 errno = ENAMETOOLONG;
145 strcpy(namebuf, dir);
146 strcat(namebuf, pfx);
147 strcat(namebuf, suffix);
149 /* The Single UNIX Specification doesn't say that "mkstemp()"
150 creates the temporary file with mode rw-------, so we
151 won't assume that all UNIXes will do so; instead, we set
152 the umask to 0077 to take away all group and other
153 permissions, attempt to create the file, and then put
155 old_umask = umask(0077);
156 tmp_fd = mkstemp(namebuf);
161 static char *tmpdir = NULL;
163 static char *temp = NULL;
165 static char *E_tmpdir;
168 #define P_tmpdir "/var/tmp"
172 create_tempfile(char *namebuf, int namebuflen, const char *pfx)
176 static gboolean initialized;
179 if ((dir = getenv("TMPDIR")) != NULL)
180 tmpdir = setup_tmpdir(dir);
182 if ((dir = getenv("TEMP")) != NULL)
183 temp = setup_tmpdir(dir);
186 E_tmpdir = setup_tmpdir(P_tmpdir);
190 if (tmpdir != NULL) {
191 fd = try_tempfile(namebuf, namebuflen, tmpdir, pfx);
198 fd = try_tempfile(namebuf, namebuflen, temp, pfx);
204 fd = try_tempfile(namebuf, namebuflen, E_tmpdir, pfx);
208 return try_tempfile(namebuf, namebuflen, G_DIR_SEPARATOR_S "tmp", pfx);
211 /* ASCII/EBCDIC conversion tables from
212 * http://www.room42.com/store/computer_center/code_tables.shtml
215 static guint8 ASCII_translate_EBCDIC [ 256 ] = {
216 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
217 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
218 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
219 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
220 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, 0x4D,
221 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
222 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
223 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
224 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8,
225 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
226 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
227 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D,
228 0x7D, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
229 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
230 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
231 0xA8, 0xA9, 0xC0, 0x6A, 0xD0, 0xA1, 0x4B,
232 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
233 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
234 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
235 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
236 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
237 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
238 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
239 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
240 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
241 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
242 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
243 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
244 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
245 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
246 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
247 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B
251 ASCII_to_EBCDIC(guint8 *buf, guint bytes)
258 for (i = 0; i < bytes; i++, bufptr++) {
259 *bufptr = ASCII_translate_EBCDIC[*bufptr];
264 ASCII_to_EBCDIC1(guint8 c)
266 return ASCII_translate_EBCDIC[c];
270 static guint8 EBCDIC_translate_ASCII [ 256 ] = {
271 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
272 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
273 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
274 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
275 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
276 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
277 0x2E, 0x2E, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
278 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x2E, 0x3F,
279 0x20, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
280 0x2E, 0x2E, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
281 0x26, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
282 0x2E, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E,
283 0x2D, 0x2F, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
284 0x2E, 0x7C, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
285 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
286 0x2E, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
287 0x2E, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
288 0x69, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
289 0x2E, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71,
290 0x72, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
291 0x2E, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
292 0x7A, 0x2E, 0x2E, 0x2E, 0x5B, 0x2E, 0x2E,
293 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
294 0x2E, 0x2E, 0x2E, 0x2E, 0x5D, 0x2E, 0x2E,
295 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
296 0x49, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
297 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51,
298 0x52, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
299 0x5C, 0x2E, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
300 0x5A, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
301 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
302 0x39, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E
306 EBCDIC_to_ASCII(guint8 *buf, guint bytes)
313 for (i = 0; i < bytes; i++, bufptr++) {
314 *bufptr = EBCDIC_translate_ASCII[*bufptr];
319 EBCDIC_to_ASCII1(guint8 c)
321 return EBCDIC_translate_ASCII[c];
324 /* Compute the difference between two seconds/microseconds time stamps. */
326 compute_timestamp_diff(gint *diffsec, gint *diffusec,
327 guint32 sec1, guint32 usec1, guint32 sec2, guint32 usec2)
330 /* The seconds part of the first time is the same as the seconds
331 part of the second time, so if the microseconds part of the first
332 time is less than the microseconds part of the second time, the
333 first time is before the second time. The microseconds part of
334 the delta should just be the difference between the microseconds
335 part of the first time and the microseconds part of the second
336 time; don't adjust the seconds part of the delta, as it's OK if
337 the microseconds part is negative. */
339 *diffsec = sec1 - sec2;
340 *diffusec = usec1 - usec2;
341 } else if (sec1 <= sec2) {
342 /* The seconds part of the first time is less than the seconds part
343 of the second time, so the first time is before the second time.
345 Both the "seconds" and "microseconds" value of the delta
346 should have the same sign, so if the difference between the
347 microseconds values would be *positive*, subtract 1,000,000
348 from it, and add one to the seconds value. */
349 *diffsec = sec1 - sec2;
350 if (usec2 >= usec1) {
351 *diffusec = usec1 - usec2;
353 *diffusec = (usec1 - 1000000) - usec2;
357 /* Oh, good, we're not caught in a chronosynclastic infindibulum. */
358 *diffsec = sec1 - sec2;
359 if (usec2 <= usec1) {
360 *diffusec = usec1 - usec2;
362 *diffusec = (usec1 + 1000000) - usec2;
368 /* Decode a base64 string in-place - simple and slow algorithm.
369 Return length of result. Taken from rproxy/librsync/base64.c by
372 size_t base64_decode(char *s)
374 static const char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
375 int bit_offset, byte_offset, idx, i, n;
376 unsigned char *d = (unsigned char *)s;
381 while (*s && (p=strchr(b64, *s))) {
382 idx = (int)(p - b64);
383 byte_offset = (i*6)/8;
384 bit_offset = (i*6)%8;
385 d[byte_offset] &= ~((1<<(8-bit_offset))-1);
386 if (bit_offset < 3) {
387 d[byte_offset] |= (idx << (2-bit_offset));
390 d[byte_offset] |= (idx >> (bit_offset-2));
391 d[byte_offset+1] = 0;
392 d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF;
401 /* Try to figure out if we're remotely connected, e.g. via ssh or
402 Terminal Server, and create a capture filter that matches aspects of the
403 connection. We match the following environment variables:
405 SSH_CONNECTION (ssh): <remote IP> <remote port> <local IP> <local port>
406 SSH_CLIENT (ssh): <remote IP> <remote port> <local port>
407 REMOTEHOST (tcsh, others?): <remote name>
408 DISPLAY (x11): [remote name]:<display num>
409 CLIENTNAME (terminal server): <remote name>
412 gchar *get_conn_cfilter(void) {
413 static GString *filter_str = NULL;
414 gchar *env, **tokens;
416 if (filter_str == NULL) {
417 filter_str = g_string_new("");
419 if ((env = getenv("SSH_CONNECTION")) != NULL) {
420 tokens = g_strsplit(env, " ", 4);
422 g_string_sprintf(filter_str, "not (tcp port %s and ip host %s "
423 "and tcp port %s and ip host %s)", tokens[1], tokens[0],
424 tokens[3], tokens[2]);
425 return filter_str->str;
427 } else if ((env = getenv("SSH_CLIENT")) != NULL) {
428 tokens = g_strsplit(env, " ", 3);
429 g_string_sprintf(filter_str, "not (tcp port %s and ip host %s "
430 "and tcp port %s)", tokens[1], tokens[0], tokens[2]);
431 return filter_str->str;
432 } else if ((env = getenv("REMOTEHOST")) != NULL) {
433 g_string_sprintf(filter_str, "not ip host %s", env);
434 return filter_str->str;
435 } else if ((env = getenv("DISPLAY")) != NULL) {
436 tokens = g_strsplit(env, ":", 2);
437 if (tokens[0] && tokens[0][0] != 0) {
438 g_string_sprintf(filter_str, "not ip host %s",
440 return filter_str->str;
442 } else if ((env = getenv("CLIENTNAME")) != NULL) {
443 if (g_strcasecmp("console", env) != 0) {
444 g_string_sprintf(filter_str, "not ip host %s", env);
445 return filter_str->str;