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 */
59 #include <epan/address.h>
60 #include <epan/addr_resolv.h>
63 * This has to come after the include of <pcap.h>, as the include of
64 * <pcap.h> might cause <winsock2.h> to be included, and if we've
65 * already included <winsock.h> as a result of including <windows.h>,
66 * we get a bunch of redefinitions.
75 * Collect command-line arguments as a string consisting of the arguments,
76 * separated by spaces.
79 get_args_as_string(int argc, char **argv, int optind)
86 * Find out how long the string will be.
89 for (i = optind; i < argc; i++) {
90 len += strlen(argv[i]);
91 len++; /* space, or '\0' if this is the last argument */
95 * Allocate the buffer for the string.
97 argstring = g_malloc(len);
100 * Now construct the string.
102 strcpy(argstring, "");
105 strcat(argstring, argv[i]);
109 strcat(argstring, " ");
115 setup_tmpdir(char *dir)
117 int len = strlen(dir);
120 /* Append path separator if necessary */
121 if (dir[len - 1] == G_DIR_SEPARATOR) {
125 newdir = g_malloc(len + 2);
127 strcat(newdir, G_DIR_SEPARATOR_S);
133 try_tempfile(char *namebuf, int namebuflen, const char *dir, const char *pfx)
135 static const char suffix[] = "XXXXXXXXXX";
136 int namelen = strlen(dir) + strlen(pfx) + sizeof suffix;
140 if (namebuflen < namelen) {
141 /* Stick in a truncated name, so that if this error is
142 reported with the file name, you at least get
144 snprintf(namebuf, namebuflen, "%s%s%s", dir, pfx, suffix);
145 errno = ENAMETOOLONG;
148 strcpy(namebuf, dir);
149 strcat(namebuf, pfx);
150 strcat(namebuf, suffix);
152 /* The Single UNIX Specification doesn't say that "mkstemp()"
153 creates the temporary file with mode rw-------, so we
154 won't assume that all UNIXes will do so; instead, we set
155 the umask to 0077 to take away all group and other
156 permissions, attempt to create the file, and then put
158 old_umask = umask(0077);
159 tmp_fd = mkstemp(namebuf);
164 static char *tmpdir = NULL;
166 static char *temp = NULL;
168 static char *E_tmpdir;
171 #define P_tmpdir "/var/tmp"
175 create_tempfile(char *namebuf, int namebuflen, const char *pfx)
179 static gboolean initialized;
182 if ((dir = getenv("TMPDIR")) != NULL)
183 tmpdir = setup_tmpdir(dir);
185 if ((dir = getenv("TEMP")) != NULL)
186 temp = setup_tmpdir(dir);
189 E_tmpdir = setup_tmpdir(P_tmpdir);
193 if (tmpdir != NULL) {
194 fd = try_tempfile(namebuf, namebuflen, tmpdir, pfx);
201 fd = try_tempfile(namebuf, namebuflen, temp, pfx);
207 fd = try_tempfile(namebuf, namebuflen, E_tmpdir, pfx);
211 return try_tempfile(namebuf, namebuflen, G_DIR_SEPARATOR_S "tmp", pfx);
214 /* Compute the difference between two seconds/microseconds time stamps. */
216 compute_timestamp_diff(gint *diffsec, gint *diffusec,
217 guint32 sec1, guint32 usec1, guint32 sec2, guint32 usec2)
220 /* The seconds part of the first time is the same as the seconds
221 part of the second time, so if the microseconds part of the first
222 time is less than the microseconds part of the second time, the
223 first time is before the second time. The microseconds part of
224 the delta should just be the difference between the microseconds
225 part of the first time and the microseconds part of the second
226 time; don't adjust the seconds part of the delta, as it's OK if
227 the microseconds part is negative. */
229 *diffsec = sec1 - sec2;
230 *diffusec = usec1 - usec2;
231 } else if (sec1 <= sec2) {
232 /* The seconds part of the first time is less than the seconds part
233 of the second time, so the first time is before the second time.
235 Both the "seconds" and "microseconds" value of the delta
236 should have the same sign, so if the difference between the
237 microseconds values would be *positive*, subtract 1,000,000
238 from it, and add one to the seconds value. */
239 *diffsec = sec1 - sec2;
240 if (usec2 >= usec1) {
241 *diffusec = usec1 - usec2;
243 *diffusec = (usec1 - 1000000) - usec2;
247 /* Oh, good, we're not caught in a chronosynclastic infindibulum. */
248 *diffsec = sec1 - sec2;
249 if (usec2 <= usec1) {
250 *diffusec = usec1 - usec2;
252 *diffusec = (usec1 + 1000000) - usec2;
258 /* Try to figure out if we're remotely connected, e.g. via ssh or
259 Terminal Server, and create a capture filter that matches aspects of the
260 connection. We match the following environment variables:
262 SSH_CONNECTION (ssh): <remote IP> <remote port> <local IP> <local port>
263 SSH_CLIENT (ssh): <remote IP> <remote port> <local port>
264 REMOTEHOST (tcsh, others?): <remote name>
265 DISPLAY (x11): [remote name]:<display num>
266 CLIENTNAME (terminal server): <remote name>
269 gchar *get_conn_cfilter(void) {
270 static GString *filter_str = NULL;
271 gchar *env, **tokens;
273 if (filter_str == NULL) {
274 filter_str = g_string_new("");
276 if ((env = getenv("SSH_CONNECTION")) != NULL) {
277 tokens = g_strsplit(env, " ", 4);
279 g_string_sprintf(filter_str, "not (tcp port %s and %s host %s "
280 "and tcp port %s and %s host %s)", tokens[1], host_ip_af(tokens[0]), tokens[0],
281 tokens[3], host_ip_af(tokens[2]), tokens[2]);
282 return filter_str->str;
284 } else if ((env = getenv("SSH_CLIENT")) != NULL) {
285 tokens = g_strsplit(env, " ", 3);
286 g_string_sprintf(filter_str, "not (tcp port %s and %s host %s "
287 "and tcp port %s)", tokens[1], host_ip_af(tokens[0]), tokens[0], tokens[2]);
288 return filter_str->str;
289 } else if ((env = getenv("REMOTEHOST")) != NULL) {
290 if (strcasecmp(env, "localhost") == 0 || strcmp(env, "127.0.0.1") == 0) {
293 g_string_sprintf(filter_str, "not %s host %s", host_ip_af(env), env);
294 return filter_str->str;
295 } else if ((env = getenv("DISPLAY")) != NULL) {
296 tokens = g_strsplit(env, ":", 2);
297 if (tokens[0] && tokens[0][0] != 0) {
298 if (strcasecmp(tokens[0], "localhost") == 0 ||
299 strcmp(tokens[0], "127.0.0.1") == 0) {
302 g_string_sprintf(filter_str, "not %s host %s",
303 host_ip_af(tokens[0]), tokens[0]);
304 return filter_str->str;
306 } else if ((env = getenv("CLIENTNAME")) != NULL) {
307 if (g_strcasecmp("console", env) != 0) {
308 g_string_sprintf(filter_str, "not %s host %s", host_ip_af(env), env);
309 return filter_str->str;