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; }
/* 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); } }
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; }
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; } } }
/* 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; }
/* 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 */ }
/* 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); }
/* * 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(¤t_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; }
/* 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; }
/* * 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(¤t_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; }
/* 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 */ }
/* 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; }
/* 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; }
/* 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; }
/** * 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; }
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; }
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; }