Пример #1
0
static int ssh_open_remote_connection(const char* hostname, const unsigned int port, const char* username, const char* password,
	const char* sshkey, const char* sshkey_passphrase, const char* iface, const char* cfilter, const char* capture_bin,
	const unsigned long int count, const char* fifo)
{
	ssh_session sshs = NULL;
	ssh_channel channel = NULL;
	int fd = STDOUT_FILENO;
	int ret = EXIT_FAILURE;
	char* err_info = NULL;

	if (g_strcmp0(fifo, "-")) {
		/* Open or create the output file */
		fd = ws_open(fifo, O_WRONLY, 0640);
		if (fd == -1) {
			fd = ws_open(fifo, O_WRONLY | O_CREAT, 0640);
			if (fd == -1) {
				errmsg_print("Error creating output file: %s", g_strerror(errno));
				return EXIT_FAILURE;
			}
		}
	}

	sshs = create_ssh_connection(hostname, port, username, password, sshkey, sshkey_passphrase, &err_info);

	if (!sshs) {
		errmsg_print("Error creating connection: %s", err_info);
		goto cleanup;
	}

	channel = run_ssh_command(sshs, capture_bin, iface, cfilter, count);
	if (!channel)
		goto cleanup;

	/* read from channel and write into fd */
	ssh_loop_read(channel, fd);

	ret = EXIT_SUCCESS;
cleanup:
	if (err_info)
		errmsg_print("%s", err_info);
	g_free(err_info);

	/* clean up and exit */
	ssh_cleanup(&sshs, &channel);

	if (g_strcmp0(fifo, "-"))
		ws_close(fd);
	return ret;
}
Пример #2
0
/* update the time and size of this file in the list */
void
fileset_update_file(const char *path)
{
    int fh, result;
    ws_statb64 buf;
    fileset_entry *entry = NULL;
    GList *entry_list;

    fh = ws_open( path, O_RDONLY, 0000 /* no creation so don't matter */);
    if(fh !=  -1) {

        /* Get statistics */
        result = ws_fstat64( fh, &buf );

        /* Show statistics if they are valid */
        if( result == 0 ) {
            entry_list = g_list_find_custom(set.entries, path,
                                            fileset_find_by_path);

            if (entry_list) {
                entry = (fileset_entry *) entry_list->data;
                entry->ctime    = buf.st_ctime;
                entry->mtime    = buf.st_mtime;
                entry->size     = buf.st_size;
            }
        }

        ws_close(fh);
    }
}
Пример #3
0
gboolean
eo_save_entry(const gchar *save_as_filename, export_object_entry_t *entry, gboolean show_err)
{
    int to_fd;
    gint64 bytes_left;
    int bytes_to_write;
    ssize_t bytes_written;
    guint8 *ptr;
    int err;

    to_fd = ws_open(save_as_filename, O_WRONLY | O_CREAT | O_EXCL |
             O_BINARY, 0644);
    if(to_fd == -1) { /* An error occurred */
        if (show_err)
            open_failure_alert_box(save_as_filename, errno, TRUE);
        return FALSE;
    }

    /*
     * The third argument to _write() on Windows is an unsigned int,
     * so, on Windows, that's the size of the third argument to
     * ws_write().
     *
     * The third argument to write() on UN*X is a size_t, although
     * the return value is an ssize_t, so one probably shouldn't
     * write more than the max value of an ssize_t.
     *
     * In either case, there's no guarantee that a gint64 such as
     * payload_len can be passed to ws_write(), so we write in
     * chunks of, at most 2^31 bytes.
     */
    ptr = entry->payload_data;
    bytes_left = entry->payload_len;
    while (bytes_left != 0) {
        if (bytes_left > 0x40000000)
            bytes_to_write = 0x40000000;
        else
            bytes_to_write = (int)bytes_left;
        bytes_written = ws_write(to_fd, ptr, bytes_to_write);
        if(bytes_written <= 0) {
            if (bytes_written < 0)
                err = errno;
            else
                err = WTAP_ERR_SHORT_WRITE;
            if (show_err)
                write_failure_alert_box(save_as_filename, err);
            ws_close(to_fd);
            return FALSE;
        }
        bytes_left -= bytes_written;
        ptr += bytes_written;
    }
    if (ws_close(to_fd) < 0) {
        if (show_err)
            write_failure_alert_box(save_as_filename, errno);
        return FALSE;
    }

    return TRUE;
}
Пример #4
0
void u3_register_pid()
{
  int	pid;
  int   pid_fd;
  char *u3hostexecpath;
  int   pf_size;

  if((u3hostexecpath =
#ifdef _WIN32
      getenv_utf8
#else
      getenv
#endif
      ("U3_HOST_EXEC_PATH")) != NULL) {

    pid = getpid();

    pf_size = (int) strlen(u3hostexecpath) + 32;
    pid_file = g_malloc(pf_size);

    g_snprintf(pid_file, pf_size, "%s\\%d.pid", u3hostexecpath, pid);

    pid_fd = ws_open(pid_file, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);

    if(pid_fd != -1)
      ws_close(pid_fd);
    else {
      g_free(pid_file);
      pid_file = NULL;
    }
  }
}
Пример #5
0
/* save the SSL Session Keys */
static gboolean
savesslkeys_save_clicked_cb(char *file, gchar *keylist)
{
    int fd;

    fd = ws_open(file, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666);
    if (fd == -1) {
        open_failure_alert_box(file, errno, TRUE);
        return FALSE;
    }
    /*
     * Thanks, Microsoft, for not using size_t for the third argument to
     * _write().  Presumably this string will be <= 4GiB long....
     */
    if (ws_write(fd, keylist, (unsigned int)strlen(keylist)) < 0) {
        write_failure_alert_box(file, errno);
        ws_close(fd);
        return FALSE;
    }
    if (ws_close(fd) < 0) {
        write_failure_alert_box(file, errno);
        return FALSE;
    }

    g_free(keylist);
    return TRUE;
}
Пример #6
0
/*  Initialize all the allocators here.
 *  This function should be called only once when Wireshark or TShark starts
 *  up.
 */
void
emem_init(void)
{
	ep_init_chunk();
	se_init_chunk();

	if (getenv("WIRESHARK_DEBUG_SCRUB_MEMORY"))
		debug_use_memory_scrubber  = TRUE;

#if defined (_WIN32)
	/* Set up our guard page info for Win32 */
	GetSystemInfo(&sysinfo);
	pagesize = sysinfo.dwPageSize;

#if (_MSC_VER >= 1800)
	/*
	 * On VS2103, GetVersionEx is deprecated. Microsoft recommend to
	 * use VerifyVersionInfo instead
	 */
	{
		OSVERSIONINFOEX osvi;
		DWORDLONG dwlConditionMask = 0;
		int op = VER_EQUAL;

		SecureZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
		osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
		osvi.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS;
		VER_SET_CONDITION(dwlConditionMask, VER_PLATFORMID, op);
		iswindowsplatform = VerifyVersionInfo(&osvi, VER_PLATFORMID, dwlConditionMask);
	}
#else
	/* calling GetVersionEx using the OSVERSIONINFO structure.
	 * OSVERSIONINFOEX requires Win NT4 with SP6 or newer NT Versions.
	 * OSVERSIONINFOEX will fail on Win9x and older NT Versions.
	 * See also:
	 * http://msdn.microsoft.com/library/en-us/sysinfo/base/getversionex.asp
	 * http://msdn.microsoft.com/library/en-us/sysinfo/base/osversioninfo_str.asp
	 * http://msdn.microsoft.com/library/en-us/sysinfo/base/osversioninfoex_str.asp
	 */
	{
		OSVERSIONINFO versinfo;

		SecureZeroMemory(&versinfo, sizeof(OSVERSIONINFO));
		versinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
		GetVersionEx(&versinfo);
		iswindowsplatform = (versinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
	}
#endif

#elif defined(USE_GUARD_PAGES)
	pagesize = sysconf(_SC_PAGESIZE);
	if (pagesize == -1)
		fprintf(stderr, "Warning: call to sysconf() for _SC_PAGESIZE has failed...\n");
#ifdef NEED_DEV_ZERO
	dev_zero_fd = ws_open("/dev/zero", O_RDWR);
	g_assert(dev_zero_fd != -1);
#endif
#endif /* _WIN32 / USE_GUARD_PAGES */
}
Пример #7
0
/* Seed the random-number generator */
void
randpkt_seed(void)
{
	unsigned int	randomness;
	time_t		now;
#ifndef _WIN32
	int 		fd;
	ssize_t		ret;

#define RANDOM_DEV "/dev/urandom"

	/*
	 * Assume it's at least worth trying /dev/urandom on UN*X.
	 * If it doesn't exist, fall back on time().
	 *
	 * XXX - Use CryptGenRandom on Windows?
	 */
	fd = ws_open(RANDOM_DEV, O_RDONLY);
	if (fd == -1) {
		if (errno != ENOENT) {
			fprintf(stderr,
				"randpkt: Could not open " RANDOM_DEV " for reading: %s\n",
				g_strerror(errno));
			exit(2);
		}
		goto fallback;
	}

	ret = ws_read(fd, &randomness, sizeof randomness);
	if (ret == -1) {
		fprintf(stderr,
			"randpkt: Could not read from " RANDOM_DEV ": %s\n",
			g_strerror(errno));
		exit(2);
	}
	if ((size_t)ret != sizeof randomness) {
		fprintf(stderr,
			"randpkt: Tried to read %lu bytes from " RANDOM_DEV ", got %ld\n",
			(unsigned long)sizeof randomness, (long)ret);
		exit(2);
	}
	srand(randomness);
	ws_close(fd);
	return;

fallback:
#endif
	now = time(NULL);
	randomness = (unsigned int) now;

	srand(randomness);
}
Пример #8
0
/*
 * create the next filename and open a new binary file with that name
 */
static int ringbuf_open_file(rb_file *rfile, int *err)
{
  char    filenum[5+1];
  char    timestr[14+1];
  time_t  current_time;

  if (rfile->name != NULL) {
    if (rb_data.unlimited == FALSE) {
      /* remove old file (if any, so ignore error) */
      ws_unlink(rfile->name);
    }
    g_free(rfile->name);
  }

#ifdef _WIN32
  _tzset();
#endif
  current_time = time(NULL);

  g_snprintf(filenum, sizeof(filenum), "%05u", (rb_data.curr_file_num + 1) % RINGBUFFER_MAX_NUM_FILES);
  /*
   * XXX - We trust Windows not to return a time before the Epoch, so
   * localtime() doesn't return a null pointer.  localtime() can probably
   * handle pre-Epoch times on most UN*X systems, and we trust them not
   * to return a time before the Epoch in any case.
   */
  strftime(timestr, sizeof(timestr), "%Y%m%d%H%M%S", localtime(&current_time));
  rfile->name = g_strconcat(rb_data.fprefix, "_", filenum, "_", timestr,
                            rb_data.fsuffix, NULL);

  if (rfile->name == NULL) {
    if (err != NULL)
      *err = ENOMEM;
    return -1;
  }

  rb_data.fd = ws_open(rfile->name, O_RDWR|O_BINARY|O_TRUNC|O_CREAT,
                            rb_data.group_read_access ? 0640 : 0600);

  if (rb_data.fd == -1 && err != NULL) {
    *err = errno;
  }

  return rb_data.fd;
}
Пример #9
0
/* download a complete file from the internet */
int
download_file(const char *url, const char *filename) {
    netio_ie5_t * conn;
    char buf[100];
    int chunk_len;
    int fd;
    int stream_len;
    int ret = 0;


    /* open output file */
    fd = ws_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
    if(fd == -1) {
        g_warning("Couldn't open output file %s!", filename);
        return -1;
    }

    /* connect to url */
    conn = netio_ie5_connect (url);
    if (conn == NULL) {
        g_warning("Couldn't connect to %s!", url);
        return -1;
    }

    do {
		/* XXX - maybe add a progress bar here */

        /* read some bytes from the url */
        chunk_len = netio_ie5_read (conn, buf, sizeof(buf));

        /* write bytes to the output file */
        stream_len = ws_write( fd, buf, chunk_len);
        if(stream_len != chunk_len) {
            g_warning("output failed: stream_len %u != chunk_len %u", stream_len, chunk_len);
            ret = -1;
            break;
        }
    } while(chunk_len > 0);

    netio_ie5_disconnect(conn);

    ws_close(fd);

    return ret;
}
Пример #10
0
/*
 * create the next filename and open a new binary file with that name
 */
static int ringbuf_open_file(rb_file *rfile, int *err)
{
  char    filenum[5+1];
  char    timestr[14+1];
  time_t  current_time;
  struct tm *tm;

  if (rfile->name != NULL) {
    if (rb_data.unlimited == FALSE) {
      /* remove old file (if any, so ignore error) */
      ws_unlink(rfile->name);
    }
    g_free(rfile->name);
  }

#ifdef _WIN32
  _tzset();
#endif
  current_time = time(NULL);

  g_snprintf(filenum, sizeof(filenum), "%05u", (rb_data.curr_file_num + 1) % RINGBUFFER_MAX_NUM_FILES);
  tm = localtime(&current_time);
  if (tm != NULL)
    strftime(timestr, sizeof(timestr), "%Y%m%d%H%M%S", tm);
  else
    g_strlcpy(timestr, "196912312359", sizeof(timestr)); /* second before the Epoch */
  rfile->name = g_strconcat(rb_data.fprefix, "_", filenum, "_", timestr,
                            rb_data.fsuffix, NULL);

  if (rfile->name == NULL) {
    if (err != NULL)
      *err = ENOMEM;
    return -1;
  }

  rb_data.fd = ws_open(rfile->name, O_RDWR|O_BINARY|O_TRUNC|O_CREAT,
                            rb_data.group_read_access ? 0640 : 0600);

  if (rb_data.fd == -1 && err != NULL) {
    *err = errno;
  }

  return rb_data.fd;
}
Пример #11
0
/* Initialize the packet-lifetime memory allocation pool.
 * This function should be called only once when Wireshark or TShark starts
 * up.
 */
void
ep_init_chunk(void)
{
	ep_packet_mem.free_list=NULL;
	ep_packet_mem.used_list=NULL;

	ep_debug_use_chunks = (gboolean) (!getenv("WIRESHARK_DEBUG_EP_NO_CHUNKS"));
	ep_debug_use_canary = (gboolean) (!getenv("WIRESHARK_DEBUG_EP_NO_CANARY"));

#ifdef DEBUG_INTENSE_CANARY_CHECKS
	intense_canary_checking = (gboolean)getenv("WIRESHARK_DEBUG_EP_INTENSE_CANARY");
#endif

	if (ep_debug_use_canary)
		emem_canary(ep_canary);

#if defined (_WIN32)
	/* Set up our guard page info for Win32 */
	GetSystemInfo(&sysinfo);
	pagesize = sysinfo.dwPageSize;

	/* calling GetVersionEx using the OSVERSIONINFO structure.
	 * OSVERSIONINFOEX requires Win NT4 with SP6 or newer NT Versions.
	 * OSVERSIONINFOEX will fail on Win9x and older NT Versions.
	 * See also:
	 * http://msdn.microsoft.com/library/en-us/sysinfo/base/getversionex.asp
	 * http://msdn.microsoft.com/library/en-us/sysinfo/base/osversioninfo_str.asp
	 * http://msdn.microsoft.com/library/en-us/sysinfo/base/osversioninfoex_str.asp
	 */
	versinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
	GetVersionEx(&versinfo);

#elif defined(USE_GUARD_PAGES)
	pagesize = sysconf(_SC_PAGESIZE);
#ifdef NEED_DEV_ZERO
	dev_zero_fd = ws_open("/dev/zero", O_RDWR);
	g_assert(dev_zero_fd != -1);
#endif
#endif /* _WIN32 / USE_GUARD_PAGES */
}
Пример #12
0
/* Generate a unique temporary file name from TEMPLATE.
   The last six characters before the suffix length of TEMPLATE
   must be TMP_FILE_SUFFIX; they are replaced with a string that
   makes the filename unique.
   Returns a file descriptor open on the file for reading and writing.  */
static int
mkstemps(char *path_template, int suffixlen)
{
  static const char letters[]
    = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  char uniqueness[6];
  size_t len;
  size_t i;

  len = strlen (path_template);
  if (len < 6 || strncmp (&path_template[len - 6 - suffixlen], TMP_FILE_SUFFIX, 6))
    {
      __set_errno (EINVAL);
      return -1;
    }

  if (g_snprintf (uniqueness, 6, "%.5u",
                  (unsigned int) ws_getpid () % 100000) != 5)
    /* Inconceivable lossage.  */
    return -1;

  memcpy(&path_template[len - 5 - suffixlen], uniqueness, 5);

  for (i = 0; i < sizeof (letters); ++i)
    {
      int fd;

      path_template[len - 6 - suffixlen] = letters[i];

      fd = ws_open (path_template, O_RDWR|O_BINARY|O_CREAT|O_EXCL, 0600);
      if (fd >= 0)
        return fd;
    }

  /* We return the null string if we can't find a unique file name.  */

  path_template[0] = '\0';
  return -1;
}
Пример #13
0
/* we know this file is part of the set, so add it */
static fileset_entry *
fileset_add_file(const char *dirname, const char *fname, gboolean current)
{
    int fh, result;
    struct stat buf;
    char *path;
    fileset_entry *entry = NULL;


    path = g_strdup_printf("%s%s", dirname, fname);

    fh = ws_open( path, O_RDONLY, 0000 /* no creation so don't matter */);
    if(fh !=  -1) {

        /* Get statistics */
        result = fstat( fh, &buf );

        /* Show statistics if they are valid */
        if( result == 0 ) {
            entry = (fileset_entry *)g_malloc(sizeof(fileset_entry));

            entry->fullname = g_strdup(path);
            entry->name     = g_strdup(fname);
            entry->ctime    = buf.st_ctime;
            entry->mtime    = buf.st_mtime;
            entry->size     = buf.st_size;
            entry->current  = current;

            set.entries = g_list_append(set.entries, entry);
        }

        ws_close(fh);
    }

    g_free(path);

    return entry;
}
Пример #14
0
/* Opens a file and prepares a wtap struct.
   If "do_random" is TRUE, it opens the file twice; the second open
   allows the application to do random-access I/O without moving
   the seek offset for sequential I/O, which is used by Wireshark
   so that it can do sequential I/O to a capture file that's being
   written to as new packets arrive independently of random I/O done
   to display protocol trees for packets when they're selected. */
wtap* wtap_open_offline(const char *filename, int *err, char **err_info,
			gboolean do_random)
{
	struct stat statb;
	wtap	*wth;
	unsigned int	i;
	gboolean use_stdin = FALSE;

	/* open standard input if filename is '-' */
	if (strcmp(filename, "-") == 0)
		use_stdin = TRUE;

	/* First, make sure the file is valid */
	if (use_stdin) {
		if (fstat(0, &statb) < 0) {
			*err = errno;
			return NULL;
		}
	} else {
		if (ws_stat(filename, &statb) < 0) {
			*err = errno;
			return NULL;
		}
	}
	if (S_ISFIFO(statb.st_mode)) {
		/*
		 * Opens of FIFOs are allowed only when not opening
		 * for random access.
		 *
		 * XXX - currently, we do seeking when trying to find
		 * out the file type, so we don't actually support
		 * opening FIFOs.  However, we may eventually
		 * do buffering that allows us to do at least some
		 * file type determination even on pipes, so we
		 * allow FIFO opens and let things fail later when
		 * we try to seek.
		 */
		if (do_random) {
			*err = WTAP_ERR_RANDOM_OPEN_PIPE;
			return NULL;
		}
	} else if (S_ISDIR(statb.st_mode)) {
		/*
		 * Return different errors for "this is a directory"
		 * and "this is some random special file type", so
		 * the user can get a potentially more helpful error.
		 */
		*err = EISDIR;
		return NULL;
	} else if (! S_ISREG(statb.st_mode)) {
		*err = WTAP_ERR_NOT_REGULAR_FILE;
		return NULL;
	}

	/*
	 * We need two independent descriptors for random access, so
	 * they have different file positions.  If we're opening the
	 * standard input, we can only dup it to get additional
	 * descriptors, so we can't have two independent descriptors,
	 * and thus can't do random access.
	 */
	if (use_stdin && do_random) {
		*err = WTAP_ERR_RANDOM_OPEN_STDIN;
		return NULL;
	}

	errno = ENOMEM;
	wth = (wtap *)g_malloc(sizeof(wtap));
	if (wth == NULL) {
		*err = errno;
		return NULL;
	}

	/* Open the file */
	errno = WTAP_ERR_CANT_OPEN;
	if (use_stdin) {
		/*
		 * We dup FD 0, so that we don't have to worry about
		 * an fclose or gzclose of wth->fh closing the standard
		 * input of the process.
		 */
		wth->fd = ws_dup(0);
#ifdef _WIN32
		_setmode(wth->fd, O_BINARY);
#endif
	} else
		wth->fd = ws_open(filename, O_RDONLY|O_BINARY, 0000 /* no creation so don't matter */);
	if (wth->fd < 0) {
		*err = errno;
		g_free(wth);
		return NULL;
	}
	if (!(wth->fh = filed_open(wth->fd, "rb"))) {
		*err = errno;
		ws_close(wth->fd);
		g_free(wth);
		return NULL;
	}

	if (do_random) {
		if (!(wth->random_fh = file_open(filename, "rb"))) {
			*err = errno;
			file_close(wth->fh);
			g_free(wth);
			return NULL;
		}
	} else
		wth->random_fh = NULL;

	/* initialization */
	wth->file_encap = WTAP_ENCAP_UNKNOWN;
	wth->data_offset = 0;
	wth->subtype_sequential_close = NULL;
	wth->subtype_close = NULL;
	wth->tsprecision = WTAP_FILE_TSPREC_USEC;
	wth->priv = NULL;

	init_open_routines();

	/* Try all file types */
	for (i = 0; i < open_routines_arr->len; i++) {
		/* Seek back to the beginning of the file; the open routine
		   for the previous file type may have left the file
		   position somewhere other than the beginning, and the
		   open routine for this file type will probably want
		   to start reading at the beginning.

		   Initialize the data offset while we're at it. */
		if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
			/* I/O error - give up */
			if (wth->random_fh != NULL)
				file_close(wth->random_fh);
			file_close(wth->fh);
			g_free(wth);
			return NULL;
		}
		wth->data_offset = 0;

		switch ((*open_routines[i])(wth, err, err_info)) {

		case -1:
			/* I/O error - give up */
			if (wth->random_fh != NULL)
				file_close(wth->random_fh);
			file_close(wth->fh);
			g_free(wth);
			return NULL;

		case 0:
			/* No I/O error, but not that type of file */
			break;

		case 1:
			/* We found the file type */
			goto success;
		}
	}

	/* Well, it's not one of the types of file we know about. */
	if (wth->random_fh != NULL)
		file_close(wth->random_fh);
	file_close(wth->fh);
	g_free(wth);
	*err = WTAP_ERR_FILE_UNKNOWN_FORMAT;
	return NULL;

success:
	wth->frame_buffer = (struct Buffer *)g_malloc(sizeof(struct Buffer));
	buffer_init(wth->frame_buffer, 1500);
	return wth;
}
Пример #15
0
/**
 * Open a pipe for raw input.  This is a stripped-down version of
 * pcap_loop.c:cap_pipe_open_live().
 * We check if "pipe_name" is "-" (stdin) or a FIFO, and open it.
 * @param pipe_name The name of the pipe or FIFO.
 * @return A POSIX file descriptor on success, or -1 on failure.
 */
static int
raw_pipe_open(const char *pipe_name)
{
#ifndef _WIN32
  struct stat pipe_stat;
#else
  char *pncopy, *pos;
  DWORD err;
  wchar_t *err_str;
  HANDLE hPipe = NULL;
#endif
  int          rfd;

  g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "open_raw_pipe: %s", pipe_name);

  /*
   * XXX Rawshark blocks until we return
   */
  if (strcmp(pipe_name, "-") == 0) {
    rfd = 0; /* read from stdin */
#ifdef _WIN32
    /*
     * This is needed to set the stdin pipe into binary mode, otherwise
     * CR/LF are mangled...
     */
    _setmode(0, _O_BINARY);
#endif  /* _WIN32 */
  } else {
#ifndef _WIN32
    if (ws_stat(pipe_name, &pipe_stat) < 0) {
      fprintf(stderr, "rawshark: The pipe %s could not be checked: %s\n",
              pipe_name, strerror(errno));
      return -1;
    }
    if (! S_ISFIFO(pipe_stat.st_mode)) {
      if (S_ISCHR(pipe_stat.st_mode)) {
        /*
         * Assume the user specified an interface on a system where
         * interfaces are in /dev.  Pretend we haven't seen it.
         */
      } else
      {
        fprintf(stderr, "rawshark: \"%s\" is neither an interface nor a pipe\n",
	        pipe_name);
      }
      return -1;
    }
    rfd = ws_open(pipe_name, O_RDONLY | O_NONBLOCK, 0000 /* no creation so don't matter */);
    if (rfd == -1) {
        fprintf(stderr, "rawshark: \"%s\" could not be opened: %s\n",
                pipe_name, strerror(errno));
      return -1;
    }
#else /* _WIN32 */
#define PIPE_STR "\\pipe\\"
    /* Under Windows, named pipes _must_ have the form
     * "\\<server>\pipe\<pipe_name>".  <server> may be "." for localhost.
     */
    pncopy = g_strdup(pipe_name);
    if (strstr(pncopy, "\\\\") == pncopy) {
      pos = strchr(pncopy + 3, '\\');
      if (pos && g_ascii_strncasecmp(pos, PIPE_STR, strlen(PIPE_STR)) != 0)
        pos = NULL;
    }

    g_free(pncopy);

    if (!pos) {
      fprintf(stderr, "rawshark: \"%s\" is neither an interface nor a pipe\n",
              pipe_name);
      return -1;
    }

    /* Wait for the pipe to appear */
    while (1) {
      hPipe = CreateFile(utf_8to16(pipe_name), GENERIC_READ, 0, NULL,
          OPEN_EXISTING, 0, NULL);

      if (hPipe != INVALID_HANDLE_VALUE)
        break;

      err = GetLastError();
      if (err != ERROR_PIPE_BUSY) {
        FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
          NULL, err, 0, (LPTSTR) &err_str, 0, NULL);
        fprintf(stderr, "rawshark: \"%s\" could not be opened: %s (error %d)\n",
	    pipe_name, utf_16to8(err_str), err);
        LocalFree(err_str);
        return -1;
      }

      if (!WaitNamedPipe(utf_8to16(pipe_name), 30 * 1000)) {
      	err = GetLastError();
        FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
          NULL, err, 0, (LPTSTR) &err_str, 0, NULL);
        fprintf(stderr, "rawshark: \"%s\" could not be waited for: %s (error %d)\n",
	    pipe_name, utf_16to8(err_str), err);
        LocalFree(err_str);
        return -1;
      }
    }

    rfd = _open_osfhandle((long) hPipe, _O_RDONLY);
    if (rfd == -1) {
      fprintf(stderr, "rawshark: \"%s\" could not be opened: %s\n",
              pipe_name, strerror(errno));
      return -1;
    }
#endif /* _WIN32 */
  }

  return rfd;
}
Пример #16
0
int
main(int argc, char *argv[])
{
  GString            *comp_info_str;
  GString            *runtime_info_str;
  int                 opt;
DIAG_OFF(cast-qual)
  static const struct option long_options[] = {
      {(char *)"help", no_argument, NULL, 'h'},
      {(char *)"version", no_argument, NULL, 'V'},
      {0, 0, 0, 0 }
  };
DIAG_ON(cast-qual)
  gboolean            do_append          = FALSE;
  gboolean            verbose            = FALSE;
  int                 in_file_count      = 0;
  guint               snaplen            = 0;
#ifdef PCAP_NG_DEFAULT
  int                 file_type          = WTAP_FILE_TYPE_SUBTYPE_PCAPNG; /* default to pcap format */
#else
  int                 file_type          = WTAP_FILE_TYPE_SUBTYPE_PCAP; /* default to pcapng format */
#endif
  int                 frame_type         = -2;
  int                 out_fd;
  merge_in_file_t    *in_files           = NULL, *in_file;
  int                 i;
  struct wtap_pkthdr *phdr, snap_phdr;
  wtap_dumper        *pdh;
  int                 open_err, read_err = 0, write_err, close_err;
  gchar              *err_info, *write_err_info = NULL;
  int                 err_fileno;
  char               *out_filename       = NULL;
  gboolean            got_read_error     = FALSE, got_write_error = FALSE;
  int                 count;

  cmdarg_err_init(mergecap_cmdarg_err, mergecap_cmdarg_err_cont);

#ifdef _WIN32
  arg_list_utf_16to8(argc, argv);
  create_app_running_mutex();
#endif /* _WIN32 */

  /* Get the compile-time version information string */
  comp_info_str = get_compiled_version_info(NULL, get_mergecap_compiled_info);

  /* Get the run-time version information string */
  runtime_info_str = get_runtime_version_info(get_mergecap_runtime_info);

  /* Add it to the information to be reported on a crash. */
  ws_add_crash_info("Mergecap (Wireshark) %s\n"
       "\n"
       "%s"
       "\n"
       "%s",
    get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str);

  /* Process the options first */
  while ((opt = getopt_long(argc, argv, "aF:hs:T:vVw:", long_options, NULL)) != -1) {

    switch (opt) {
    case 'a':
      do_append = !do_append;
      break;

    case 'F':
      file_type = wtap_short_string_to_file_type_subtype(optarg);
      if (file_type < 0) {
        fprintf(stderr, "mergecap: \"%s\" isn't a valid capture file type\n",
                optarg);
        list_capture_types();
        exit(1);
      }
      break;

    case 'h':
      printf("Mergecap (Wireshark) %s\n"
             "Merge two or more capture files into one.\n"
             "See http://www.wireshark.org for more information.\n",
             get_ws_vcs_version_info());
      print_usage(stdout);
      exit(0);
      break;

    case 's':
      snaplen = get_positive_int(optarg, "snapshot length");
      break;

    case 'T':
      frame_type = wtap_short_string_to_encap(optarg);
      if (frame_type < 0) {
        fprintf(stderr, "mergecap: \"%s\" isn't a valid encapsulation type\n",
                optarg);
        list_encap_types();
        exit(1);
      }
      break;

    case 'v':
      verbose = TRUE;
      break;

    case 'V':
      show_version("Mergecap (Wireshark)", comp_info_str, runtime_info_str);
      g_string_free(comp_info_str, TRUE);
      g_string_free(runtime_info_str, TRUE);
      exit(0);
      break;

    case 'w':
      out_filename = optarg;
      break;

    case '?':              /* Bad options if GNU getopt */
      switch(optopt) {
      case'F':
        list_capture_types();
        break;
      case'T':
        list_encap_types();
        break;
      default:
        print_usage(stderr);
      }
      exit(1);
      break;
    }
  }

  /* check for proper args; at a minimum, must have an output
   * filename and one input file
   */
  in_file_count = argc - optind;
  if (!out_filename) {
    fprintf(stderr, "mergecap: an output filename must be set with -w\n");
    fprintf(stderr, "          run with -h for help\n");
    return 1;
  }
  if (in_file_count < 1) {
    fprintf(stderr, "mergecap: No input files were specified\n");
    return 1;
  }

  /* open the input files */
  if (!merge_open_in_files(in_file_count, &argv[optind], &in_files,
                           &open_err, &err_info, &err_fileno)) {
    fprintf(stderr, "mergecap: Can't open %s: %s\n", argv[optind + err_fileno],
            wtap_strerror(open_err));
    if (err_info != NULL) {
      fprintf(stderr, "(%s)\n", err_info);
      g_free(err_info);
    }
    return 2;
  }

  if (verbose) {
    for (i = 0; i < in_file_count; i++)
      fprintf(stderr, "mergecap: %s is type %s.\n", argv[optind + i],
              wtap_file_type_subtype_string(wtap_file_type_subtype(in_files[i].wth)));
  }

  if (snaplen == 0) {
    /*
     * Snapshot length not specified - default to the maximum of the
     * snapshot lengths of the input files.
     */
    snaplen = merge_max_snapshot_length(in_file_count, in_files);
  }

  /* set the outfile frame type */
  if (frame_type == -2) {
    /*
     * Default to the appropriate frame type for the input files.
     */
    frame_type = merge_select_frame_type(in_file_count, in_files);
    if (verbose) {
      if (frame_type == WTAP_ENCAP_PER_PACKET) {
        /*
         * Find out why we had to choose WTAP_ENCAP_PER_PACKET.
         */
        int first_frame_type, this_frame_type;

        first_frame_type = wtap_file_encap(in_files[0].wth);
        for (i = 1; i < in_file_count; i++) {
          this_frame_type = wtap_file_encap(in_files[i].wth);
          if (first_frame_type != this_frame_type) {
            fprintf(stderr, "mergecap: multiple frame encapsulation types detected\n");
            fprintf(stderr, "          defaulting to WTAP_ENCAP_PER_PACKET\n");
            fprintf(stderr, "          %s had type %s (%s)\n",
                    in_files[0].filename,
                    wtap_encap_string(first_frame_type),
                    wtap_encap_short_string(first_frame_type));
            fprintf(stderr, "          %s had type %s (%s)\n",
                    in_files[i].filename,
                    wtap_encap_string(this_frame_type),
                    wtap_encap_short_string(this_frame_type));
            break;
          }
        }
      }
      fprintf(stderr, "mergecap: selected frame_type %s (%s)\n",
              wtap_encap_string(frame_type),
              wtap_encap_short_string(frame_type));
    }
  }

  /* open the outfile */
  if (strncmp(out_filename, "-", 2) == 0) {
    /* use stdout as the outfile */
    out_fd = 1 /*stdout*/;
  } else {
    /* open the outfile */
    out_fd = ws_open(out_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
    if (out_fd == -1) {
      fprintf(stderr, "mergecap: Couldn't open output file %s: %s\n",
              out_filename, g_strerror(errno));
      exit(1);
    }
  }

  /* prepare the outfile */
  if(file_type == WTAP_FILE_TYPE_SUBTYPE_PCAPNG ){
    wtapng_section_t *shb_hdr;
    GString *comment_gstr;

    shb_hdr = g_new(wtapng_section_t,1);
    comment_gstr = g_string_new("File created by merging: \n");

    for (i = 0; i < in_file_count; i++) {
      g_string_append_printf(comment_gstr, "File%d: %s \n",i+1,in_files[i].filename);
    }
    shb_hdr->section_length = -1;
    /* options */
    shb_hdr->opt_comment   = comment_gstr->str; /* NULL if not available */
    shb_hdr->shb_hardware  = NULL;              /* NULL if not available, UTF-8 string containing the description of the hardware used to create this section. */
    shb_hdr->shb_os        = NULL;              /* NULL if not available, UTF-8 string containing the name of the operating system used to create this section. */
    shb_hdr->shb_user_appl = g_strdup("mergecap"); /* NULL if not available, UTF-8 string containing the name of the application used to create this section. */

    pdh = wtap_dump_fdopen_ng(out_fd, file_type, frame_type, snaplen,
                              FALSE /* compressed */, shb_hdr, NULL /* wtapng_iface_descriptions_t *idb_inf */, &open_err);
    g_string_free(comment_gstr, TRUE);
  } else {
    pdh = wtap_dump_fdopen(out_fd, file_type, frame_type, snaplen, FALSE /* compressed */, &open_err);
  }
  if (pdh == NULL) {
    merge_close_in_files(in_file_count, in_files);
    g_free(in_files);
    fprintf(stderr, "mergecap: Can't open or create %s: %s\n", out_filename,
            wtap_strerror(open_err));
    exit(1);
  }

  /* do the merge (or append) */
  count = 1;
  for (;;) {
    if (do_append)
      in_file = merge_append_read_packet(in_file_count, in_files, &read_err,
                                         &err_info);
    else
      in_file = merge_read_packet(in_file_count, in_files, &read_err,
                                  &err_info);
    if (in_file == NULL) {
      /* EOF */
      break;
    }

    if (read_err != 0) {
      /* I/O error reading from in_file */
      got_read_error = TRUE;
      break;
    }

    if (verbose)
      fprintf(stderr, "Record: %d\n", count++);

    /* We simply write it, perhaps after truncating it; we could do other
     * things, like modify it. */
    phdr = wtap_phdr(in_file->wth);
    if (snaplen != 0 && phdr->caplen > snaplen) {
      snap_phdr = *phdr;
      snap_phdr.caplen = snaplen;
      phdr = &snap_phdr;
    }

    if (!wtap_dump(pdh, phdr, wtap_buf_ptr(in_file->wth), &write_err, &write_err_info)) {
      got_write_error = TRUE;
      break;
    }
  }

  merge_close_in_files(in_file_count, in_files);
  if (!got_write_error) {
    if (!wtap_dump_close(pdh, &write_err))
      got_write_error = TRUE;
  } else {
    /*
     * We already got a write error; no need to report another
     * write error on close.
     *
     * Don't overwrite the earlier write error.
     */
    (void)wtap_dump_close(pdh, &close_err);
  }

  if (got_read_error) {
    /*
     * Find the file on which we got the error, and report the error.
     */
    for (i = 0; i < in_file_count; i++) {
      if (in_files[i].state == GOT_ERROR) {
        fprintf(stderr, "mergecap: Error reading %s: %s\n",
                in_files[i].filename, wtap_strerror(read_err));
        if (err_info != NULL) {
          fprintf(stderr, "(%s)\n", err_info);
          g_free(err_info);
        }
      }
    }
  }

  if (got_write_error) {
    switch (write_err) {

    case WTAP_ERR_UNWRITABLE_ENCAP:
      /*
       * This is a problem with the particular frame we're writing and
       * the file type and subtype we're wwriting; note that, and
       * report the frame number and file type/subtype.
       */
      fprintf(stderr, "mergecap: Frame %u of \"%s\" has a network type that can't be saved in a \"%s\" file.\n",
              in_file ? in_file->packet_num : 0, in_file ? in_file->filename : "UNKNOWN",
              wtap_file_type_subtype_string(file_type));
      break;

    case WTAP_ERR_PACKET_TOO_LARGE:
      /*
       * This is a problem with the particular frame we're writing and
       * the file type and subtype we're wwriting; note that, and
       * report the frame number and file type/subtype.
       */
      fprintf(stderr, "mergecap: Frame %u of \"%s\" is too large for a \"%s\" file.\n",
              in_file ? in_file->packet_num : 0, in_file ? in_file->filename : "UNKNOWN",
              wtap_file_type_subtype_string(file_type));
      break;

    case WTAP_ERR_UNWRITABLE_REC_TYPE:
      /*
       * This is a problem with the particular record we're writing and
       * the file type and subtype we're wwriting; note that, and
       * report the record number and file type/subtype.
       */
      fprintf(stderr, "mergecap: Record %u of \"%s\" has a record type that can't be saved in a \"%s\" file.\n",
              in_file ? in_file->packet_num : 0, in_file ? in_file->filename : "UNKNOWN",
              wtap_file_type_subtype_string(file_type));
      break;

    case WTAP_ERR_UNWRITABLE_REC_DATA:
      /*
       * This is a problem with the particular record we're writing and
       * the file type and subtype we're wwriting; note that, and
       * report the record number and file type/subtype.
       */
      fprintf(stderr, "mergecap: Record %u of \"%s\" has data that can't be saved in a \"%s\" file.\n(%s)\n",
              in_file ? in_file->packet_num : 0, in_file ? in_file->filename : "UNKNOWN",
              wtap_file_type_subtype_string(file_type),
              write_err_info != NULL ? write_err_info : "no information supplied");
      g_free(write_err_info);
      break;

    default:
      fprintf(stderr, "mergecap: Error writing to outfile: %s\n",
              wtap_strerror(write_err));
      break;
    }
  }

  g_free(in_files);

  return (!got_read_error && !got_write_error) ? 0 : 2;
}
Пример #17
0
int
main(int argc, char *argv[])
{
  int          opt;
  gboolean     do_append = FALSE;
  gboolean     verbose = FALSE;
  int          in_file_count = 0;
  guint        snaplen = 0;
#ifdef PCAP_NG_DEFAULT
  int          file_type = WTAP_FILE_PCAPNG;    /* default to pcap format */
#else
  int          file_type = WTAP_FILE_PCAP;      /* default to pcapng format */
#endif
  int          frame_type = -2;
  int          out_fd;
  merge_in_file_t   *in_files = NULL, *in_file;
  int          i;
  struct wtap_pkthdr *phdr, snap_phdr;
  wtap_dumper *pdh;
  int          open_err, read_err = 0, write_err, close_err;
  gchar       *err_info;
  int          err_fileno;
  char        *out_filename = NULL;
  gboolean     got_read_error = FALSE, got_write_error = FALSE;
  int          count;

#ifdef _WIN32
  arg_list_utf_16to8(argc, argv);
  create_app_running_mutex();
#endif /* _WIN32 */

  /* Process the options first */
  while ((opt = getopt(argc, argv, "aF:hs:T:vw:")) != -1) {

    switch (opt) {
    case 'a':
      do_append = !do_append;
      break;

    case 'F':
      file_type = wtap_short_string_to_file_type(optarg);
      if (file_type < 0) {
        fprintf(stderr, "mergecap: \"%s\" isn't a valid capture file type\n",
                optarg);
        list_capture_types();
        exit(1);
      }
      break;

    case 'h':
      usage();
      exit(0);
      break;

    case 's':
      snaplen = get_positive_int(optarg, "snapshot length");
      break;

    case 'T':
      frame_type = wtap_short_string_to_encap(optarg);
      if (frame_type < 0) {
        fprintf(stderr, "mergecap: \"%s\" isn't a valid encapsulation type\n",
                optarg);
        list_encap_types();
        exit(1);
      }
      break;

    case 'v':
      verbose = TRUE;
      break;

    case 'w':
      out_filename = optarg;
      break;

    case '?':              /* Bad options if GNU getopt */
      switch(optopt) {
      case'F':
        list_capture_types();
        break;
      case'T':
        list_encap_types();
        break;
      default:
        usage();
      }
      exit(1);
      break;
    }
  }

  /* check for proper args; at a minimum, must have an output
   * filename and one input file
   */
  in_file_count = argc - optind;
  if (!out_filename) {
    fprintf(stderr, "mergecap: an output filename must be set with -w\n");
    fprintf(stderr, "          run with -h for help\n");
    return 1;
  }
  if (in_file_count < 1) {
    fprintf(stderr, "mergecap: No input files were specified\n");
    return 1;
  }

  /* open the input files */
  if (!merge_open_in_files(in_file_count, &argv[optind], &in_files,
                           &open_err, &err_info, &err_fileno)) {
    fprintf(stderr, "mergecap: Can't open %s: %s\n", argv[optind + err_fileno],
            wtap_strerror(open_err));
    switch (open_err) {

    case WTAP_ERR_UNSUPPORTED:
    case WTAP_ERR_UNSUPPORTED_ENCAP:
    case WTAP_ERR_BAD_FILE:
      fprintf(stderr, "(%s)\n", err_info);
      g_free(err_info);
      break;
    }
    return 2;
  }

  if (verbose) {
    for (i = 0; i < in_file_count; i++)
      fprintf(stderr, "mergecap: %s is type %s.\n", argv[optind + i],
              wtap_file_type_string(wtap_file_type(in_files[i].wth)));
  }

  if (snaplen == 0) {
    /*
     * Snapshot length not specified - default to the maximum of the
     * snapshot lengths of the input files.
     */
    snaplen = merge_max_snapshot_length(in_file_count, in_files);
  }

  /* set the outfile frame type */
  if (frame_type == -2) {
    /*
     * Default to the appropriate frame type for the input files.
     */
    frame_type = merge_select_frame_type(in_file_count, in_files);
    if (verbose) {
      if (frame_type == WTAP_ENCAP_PER_PACKET) {
        /*
         * Find out why we had to choose WTAP_ENCAP_PER_PACKET.
         */
        int first_frame_type, this_frame_type;

        first_frame_type = wtap_file_encap(in_files[0].wth);
        for (i = 1; i < in_file_count; i++) {
          this_frame_type = wtap_file_encap(in_files[i].wth);
          if (first_frame_type != this_frame_type) {
            fprintf(stderr, "mergecap: multiple frame encapsulation types detected\n");
            fprintf(stderr, "          defaulting to WTAP_ENCAP_PER_PACKET\n");
            fprintf(stderr, "          %s had type %s (%s)\n",
                    in_files[0].filename,
                    wtap_encap_string(first_frame_type),
                    wtap_encap_short_string(first_frame_type));
            fprintf(stderr, "          %s had type %s (%s)\n",
                    in_files[i].filename,
                    wtap_encap_string(this_frame_type),
                    wtap_encap_short_string(this_frame_type));
            break;
          }
        }
      }
      fprintf(stderr, "mergecap: selected frame_type %s (%s)\n",
              wtap_encap_string(frame_type),
              wtap_encap_short_string(frame_type));
    }
  }

  /* open the outfile */
  if (strncmp(out_filename, "-", 2) == 0) {
    /* use stdout as the outfile */
    out_fd = 1 /*stdout*/;
  } else {
    /* open the outfile */
    out_fd = ws_open(out_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
    if (out_fd == -1) {
      fprintf(stderr, "mergecap: Couldn't open output file %s: %s\n",
              out_filename, g_strerror(errno));
      exit(1);
    }
  }

  /* prepare the outfile */
  if(file_type == WTAP_FILE_PCAPNG ){
    wtapng_section_t *shb_hdr;
    GString *comment_gstr;

    shb_hdr = g_new(wtapng_section_t,1);
    comment_gstr = g_string_new("File created by merging: \n");

    for (i = 0; i < in_file_count; i++) {
      g_string_append_printf(comment_gstr, "File%d: %s \n",i+1,in_files[i].filename);
    }
    shb_hdr->section_length = -1;
    /* options */
    shb_hdr->opt_comment   = comment_gstr->str; /* NULL if not available */
    shb_hdr->shb_hardware  = NULL;              /* NULL if not available, UTF-8 string containing the description of the hardware used to create this section. */
    shb_hdr->shb_os        = NULL;              /* NULL if not available, UTF-8 string containing the name of the operating system used to create this section. */
    shb_hdr->shb_user_appl = "mergecap";        /* NULL if not available, UTF-8 string containing the name of the application used to create this section. */

    pdh = wtap_dump_fdopen_ng(out_fd, file_type, frame_type, snaplen,
                              FALSE /* compressed */, shb_hdr, NULL /* wtapng_iface_descriptions_t *idb_inf */, &open_err);
    g_string_free(comment_gstr, TRUE);
  } else {
    pdh = wtap_dump_fdopen(out_fd, file_type, frame_type, snaplen, FALSE /* compressed */, &open_err);
  }
  if (pdh == NULL) {
    merge_close_in_files(in_file_count, in_files);
    g_free(in_files);
    fprintf(stderr, "mergecap: Can't open or create %s: %s\n", out_filename,
            wtap_strerror(open_err));
    exit(1);
  }

  /* do the merge (or append) */
  count = 1;
  for (;;) {
    if (do_append)
      in_file = merge_append_read_packet(in_file_count, in_files, &read_err,
                                         &err_info);
    else
      in_file = merge_read_packet(in_file_count, in_files, &read_err,
                                  &err_info);
    if (in_file == NULL) {
      /* EOF */
      break;
    }

    if (read_err != 0) {
      /* I/O error reading from in_file */
      got_read_error = TRUE;
      break;
    }

    if (verbose)
      fprintf(stderr, "Record: %u\n", count++);

    /* We simply write it, perhaps after truncating it; we could do other
     * things, like modify it. */
    phdr = wtap_phdr(in_file->wth);
    if (snaplen != 0 && phdr->caplen > snaplen) {
      snap_phdr = *phdr;
      snap_phdr.caplen = snaplen;
      phdr = &snap_phdr;
    }

    if (!wtap_dump(pdh, phdr, wtap_buf_ptr(in_file->wth), &write_err)) {
      got_write_error = TRUE;
      break;
    }
  }

  merge_close_in_files(in_file_count, in_files);
  if (!got_read_error && !got_write_error) {
    if (!wtap_dump_close(pdh, &write_err))
      got_write_error = TRUE;
  } else
    wtap_dump_close(pdh, &close_err);

  if (got_read_error) {
    /*
     * Find the file on which we got the error, and report the error.
     */
    for (i = 0; i < in_file_count; i++) {
      if (in_files[i].state == GOT_ERROR) {
        fprintf(stderr, "mergecap: Error reading %s: %s\n",
                in_files[i].filename, wtap_strerror(read_err));
        switch (read_err) {

        case WTAP_ERR_UNSUPPORTED:
        case WTAP_ERR_UNSUPPORTED_ENCAP:
        case WTAP_ERR_BAD_FILE:
          fprintf(stderr, "(%s)\n", err_info);
          g_free(err_info);
          break;
        }
      }
    }
  }

  if (got_write_error) {
    switch (write_err) {

    case WTAP_ERR_UNSUPPORTED_ENCAP:
      /*
       * This is a problem with the particular frame we're writing;
       * note that, and give the frame number.
       */
      fprintf(stderr, "mergecap: Frame %u of \"%s\" has a network type that can't be saved in a file with that format\n.",
              in_file->packet_num, in_file->filename);
      break;

    default:
      fprintf(stderr, "mergecap: Error writing to outfile: %s\n",
              wtap_strerror(write_err));
      break;
    }
  }

  g_free(in_files);

  return (!got_read_error && !got_write_error) ? 0 : 2;
}