Exemplo n.º 1
0
static void
frame_write(FrameRecord_t *frame, wtap *wth, wtap_dumper *pdh)
{
    int    err;
    gchar  *errinfo;
    struct wtap_pkthdr phdr;
    guint8 buf[65535];

    DEBUG_PRINT("\nDumping frame (offset=%" G_GINT64_MODIFIER "u, length=%u)\n", 
                frame->offset, frame->length);

    /* Re-read the first frame from the stored location */
    wtap_seek_read(wth,
                   frame->offset,
                   &phdr,
                   buf,
                   frame->length,
                   &err,
                   &errinfo);
    DEBUG_PRINT("re-read: err is %d, buf is (%s)\n", err, buf);

    /* Copy, and set length and timestamp from item. */
    /* TODO: remove when wtap_seek_read() will read phdr */
    phdr.ts = frame->time;

    /* Dump frame to outfile */
    if (!wtap_dump(pdh, &phdr, buf, &err)) {
        printf("Error (%s) writing frame to outfile\n", wtap_strerror(err));
        exit(1);
    }
}
Exemplo n.º 2
0
/* Main entry point to the tap */
static gboolean
export_pdu_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt, const void *data)
{
    const exp_pdu_data_t *exp_pdu_data = (const exp_pdu_data_t *)data;
    exp_pdu_t  *exp_pdu_tap_data = (exp_pdu_t *)tapdata;
    wtap_rec rec;
    int err;
    gchar *err_info;
    int buffer_len;
    guint8 *packet_buf;

    memset(&rec, 0, sizeof rec);
    buffer_len = exp_pdu_data->tvb_captured_length + exp_pdu_data->tlv_buffer_len;
    packet_buf = (guint8 *)g_malloc(buffer_len);

    if(exp_pdu_data->tlv_buffer_len > 0){
        memcpy(packet_buf, exp_pdu_data->tlv_buffer, exp_pdu_data->tlv_buffer_len);
        g_free(exp_pdu_data->tlv_buffer);
    }
    if(exp_pdu_data->tvb_captured_length > 0){
        tvb_memcpy(exp_pdu_data->pdu_tvb, packet_buf+exp_pdu_data->tlv_buffer_len, 0, exp_pdu_data->tvb_captured_length);
    }
    rec.rec_type                           = REC_TYPE_PACKET;
    rec.presence_flags                     = WTAP_HAS_CAP_LEN|WTAP_HAS_INTERFACE_ID|WTAP_HAS_TS|WTAP_HAS_PACK_FLAGS;
    rec.ts.secs                            = pinfo->abs_ts.secs;
    rec.ts.nsecs                           = pinfo->abs_ts.nsecs;
    rec.rec_header.packet_header.caplen    = buffer_len;
    rec.rec_header.packet_header.len       = exp_pdu_data->tvb_reported_length + exp_pdu_data->tlv_buffer_len;

    rec.rec_header.packet_header.pkt_encap = exp_pdu_tap_data->pkt_encap;

    if (pinfo->fd->flags.has_user_comment) {
        rec.opt_comment = g_strdup(epan_get_user_comment(edt->session, pinfo->fd));
        rec.has_comment_changed = TRUE;
    } else if (pinfo->fd->flags.has_phdr_comment) {
        rec.opt_comment = g_strdup(pinfo->rec->opt_comment);
    }

    /* XXX: should the rec.rec_header.packet_header.pseudo_header be set to the pinfo's pseudo-header? */
    /* XXX: report errors! */
    if (!wtap_dump(exp_pdu_tap_data->wdh, &rec, packet_buf, &err, &err_info)) {
        switch (err) {

        case WTAP_ERR_UNWRITABLE_REC_DATA:
            g_free(err_info);
            break;

        default:
            break;
        }
    }

    g_free(packet_buf);
    g_free(rec.opt_comment);

    return FALSE; /* Do not redraw */
}
Exemplo n.º 3
0
static void
frame_write(FrameRecord_t *frame, wtap *wth, wtap_dumper *pdh, Buffer *buf,
            const char *infile)
{
    int    err;
    gchar  *err_info;
    struct wtap_pkthdr phdr;

    memset(&phdr, 0, sizeof(struct wtap_pkthdr));

    DEBUG_PRINT("\nDumping frame (offset=%" G_GINT64_MODIFIER "u)\n",
                frame->offset);


    /* Re-read the first frame from the stored location */
    if (!wtap_seek_read(wth, frame->offset, &phdr, buf, &err, &err_info)) {
        if (err != 0) {
            /* Print a message noting that the read failed somewhere along the line. */
            fprintf(stderr,
                    "reordercap: An error occurred while re-reading \"%s\": %s.\n",
                    infile, wtap_strerror(err));
            switch (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;
            }
            exit(1);
        }
    }

    /* Copy, and set length and timestamp from item. */
    /* TODO: remove when wtap_seek_read() will read phdr */
    phdr.ts = frame->time;

    /* Dump frame to outfile */
    if (!wtap_dump(pdh, &phdr, buffer_start_ptr(buf), &err)) {
        fprintf(stderr, "reordercap: Error (%s) writing frame to outfile\n",
                wtap_strerror(err));
        exit(1);
    }
}
Exemplo n.º 4
0
static void
frame_write(FrameRecord_t *frame, wtap *wth, wtap_dumper *pdh,
            struct wtap_pkthdr *phdr, Buffer *buf, const char *infile)
{
    int    err;
    gchar  *err_info;

    DEBUG_PRINT("\nDumping frame (offset=%" G_GINT64_MODIFIER "u)\n",
                frame->offset);


    /* Re-read the frame from the stored location */
    if (!wtap_seek_read(wth, frame->offset, phdr, buf, &err, &err_info)) {
        if (err != 0) {
            /* Print a message noting that the read failed somewhere along the line. */
            fprintf(stderr,
                    "reordercap: An error occurred while re-reading \"%s\": %s.\n",
                    infile, wtap_strerror(err));
            if (err_info != NULL) {
                fprintf(stderr, "(%s)\n", err_info);
                g_free(err_info);
            }
            exit(1);
        }
    }

    /* Copy, and set length and timestamp from item. */
    /* TODO: remove when wtap_seek_read() fills in phdr,
       including time stamps, for all file types  */
    phdr->ts = frame->frame_time;

    /* Dump frame to outfile */
    if (!wtap_dump(pdh, phdr, ws_buffer_start_ptr(buf), &err, &err_info)) {
        fprintf(stderr, "reordercap: Error (%s) writing frame to outfile\n",
                wtap_strerror(err));
        if (err_info != NULL) {
            fprintf(stderr, "(%s)\n", err_info);
            g_free(err_info);
        }
        exit(1);
    }
}
Exemplo n.º 5
0
static void
frame_write(FrameRecord_t *frame, wtap *wth, wtap_dumper *pdh,
            wtap_rec *rec, Buffer *buf, const char *infile,
            const char *outfile)
{
    int    err;
    gchar  *err_info;

    DEBUG_PRINT("\nDumping frame (offset=%" G_GINT64_MODIFIER "u)\n",
                frame->offset);


    /* Re-read the frame from the stored location */
    if (!wtap_seek_read(wth, frame->offset, rec, buf, &err, &err_info)) {
        if (err != 0) {
            /* Print a message noting that the read failed somewhere along the line. */
            fprintf(stderr,
                    "reordercap: An error occurred while re-reading \"%s\".\n",
                    infile);
            cfile_read_failure_message("reordercap", infile, err, err_info);
            exit(1);
        }
    }

    /* Copy, and set length and timestamp from item. */
    /* TODO: remove when wtap_seek_read() fills in rec,
       including time stamps, for all file types  */
    rec->ts = frame->frame_time;

    /* Dump frame to outfile */
    if (!wtap_dump(pdh, rec, ws_buffer_start_ptr(buf), &err, &err_info)) {
        cfile_write_failure_message("reordercap", infile, outfile, err,
                                    err_info, frame->num,
                                    wtap_file_type_subtype(wth));
        exit(1);
    }
}
Exemplo n.º 6
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;
}
Exemplo n.º 7
0
/*----------------------------------------------------------------------
 * Write current packet out
 */
void
write_current_packet (void)
{
    int prefix_length = 0;
    int proto_length = 0;
    int ip_length = 0;
    int eth_trailer_length = 0;
    int prefix_index = 0;
    int i, padding_length;

    if (curr_offset > 0) {
        /* Write the packet */

        /* Compute packet length */
        prefix_length = 0;
        if (hdr_data_chunk) {
            prefix_length += (int)sizeof(HDR_DATA_CHUNK);
        }
        if (hdr_sctp) {
            prefix_length += (int)sizeof(HDR_SCTP);
        }
        if (hdr_udp) {
            prefix_length += (int)sizeof(HDR_UDP);
            proto_length = prefix_length + curr_offset;
        }
        if (hdr_tcp) {
            prefix_length += (int)sizeof(HDR_TCP);
            proto_length = prefix_length + curr_offset;
        }
        if (hdr_ip) {
            prefix_length += (int)sizeof(HDR_IP);
            ip_length = prefix_length + curr_offset + ((hdr_data_chunk) ? number_of_padding_bytes(curr_offset) : 0);
        }
        if (hdr_ethernet) {
            prefix_length += (int)sizeof(HDR_ETHERNET);
        }

        /* Make room for dummy header */
        memmove(&packet_buf[prefix_length], packet_buf, curr_offset);

        if (hdr_ethernet) {
            /* Pad trailer */
            if (prefix_length + curr_offset < 60) {
                eth_trailer_length = 60 - (prefix_length + curr_offset);
            }
        }

        /* Write Ethernet header */
        if (hdr_ethernet) {
            HDR_ETHERNET.l3pid = g_htons(hdr_ethernet_proto);
            memcpy(&packet_buf[prefix_index], &HDR_ETHERNET, sizeof(HDR_ETHERNET));
            prefix_index += (int)sizeof(HDR_ETHERNET);
        }

        /* Write IP header */
        if (hdr_ip) {
            vec_t cksum_vector[1];

            HDR_IP.packet_length = g_htons(ip_length);
            HDR_IP.protocol = (guint8) hdr_ip_proto;
            HDR_IP.hdr_checksum = 0;
            cksum_vector[0].ptr = (guint8 *)&HDR_IP;
            cksum_vector[0].len = sizeof(HDR_IP);
            HDR_IP.hdr_checksum = in_cksum(cksum_vector, 1);

            memcpy(&packet_buf[prefix_index], &HDR_IP, sizeof(HDR_IP));
            prefix_index += (int)sizeof(HDR_IP);
        }

        /* initialize pseudo header for checksum calculation */
        pseudoh.src_addr    = HDR_IP.src_addr;
        pseudoh.dest_addr   = HDR_IP.dest_addr;
        pseudoh.zero        = 0;
        pseudoh.protocol    = (guint8) hdr_ip_proto;
        pseudoh.length      = g_htons(proto_length);

        /* Write UDP header */
        if (hdr_udp) {
            vec_t cksum_vector[3];

            HDR_UDP.source_port = g_htons(hdr_src_port);
            HDR_UDP.dest_port = g_htons(hdr_dest_port);
            HDR_UDP.length = g_htons(proto_length);

            HDR_UDP.checksum = 0;
            cksum_vector[0].ptr = (guint8 *)&pseudoh;
            cksum_vector[0].len = sizeof(pseudoh);
            cksum_vector[1].ptr = (guint8 *)&HDR_UDP;
            cksum_vector[1].len = sizeof(HDR_UDP);
            cksum_vector[2].ptr = &packet_buf[prefix_length];
            cksum_vector[2].len = curr_offset;
            HDR_UDP.checksum = in_cksum(cksum_vector, 3);

            memcpy(&packet_buf[prefix_index], &HDR_UDP, sizeof(HDR_UDP));
            prefix_index += (int)sizeof(HDR_UDP);
        }

        /* Write TCP header */
        if (hdr_tcp) {
            vec_t cksum_vector[3];

            HDR_TCP.source_port = g_htons(hdr_src_port);
            HDR_TCP.dest_port = g_htons(hdr_dest_port);
            /* HDR_TCP.seq_num already correct */
            HDR_TCP.window = g_htons(0x2000);

            HDR_TCP.checksum = 0;
            cksum_vector[0].ptr = (guint8 *)&pseudoh;
            cksum_vector[0].len = sizeof(pseudoh);
            cksum_vector[1].ptr = (guint8 *)&HDR_TCP;
            cksum_vector[1].len = sizeof(HDR_TCP);
            cksum_vector[2].ptr = &packet_buf[prefix_length];
            cksum_vector[2].len = curr_offset;
            HDR_TCP.checksum = in_cksum(cksum_vector, 3);

            memcpy(&packet_buf[prefix_index], &HDR_TCP, sizeof(HDR_TCP));
            prefix_index += (int)sizeof(HDR_TCP);
        }

        /* Compute DATA chunk header and append padding */
        if (hdr_data_chunk) {
            HDR_DATA_CHUNK.type   = hdr_data_chunk_type;
            HDR_DATA_CHUNK.bits   = hdr_data_chunk_bits;
            HDR_DATA_CHUNK.length = g_htons(curr_offset + sizeof(HDR_DATA_CHUNK));
            HDR_DATA_CHUNK.tsn    = g_htonl(hdr_data_chunk_tsn);
            HDR_DATA_CHUNK.sid    = g_htons(hdr_data_chunk_sid);
            HDR_DATA_CHUNK.ssn    = g_htons(hdr_data_chunk_ssn);
            HDR_DATA_CHUNK.ppid   = g_htonl(hdr_data_chunk_ppid);

            padding_length = number_of_padding_bytes(curr_offset);
            for (i=0; i<padding_length; i++)
                packet_buf[prefix_length+curr_offset+i] = 0;
            curr_offset += padding_length;
        }

        /* Write SCTP header */
        if (hdr_sctp) {
            HDR_SCTP.src_port  = g_htons(hdr_sctp_src);
            HDR_SCTP.dest_port = g_htons(hdr_sctp_dest);
            HDR_SCTP.tag       = g_htonl(hdr_sctp_tag);
            HDR_SCTP.checksum  = g_htonl(0);

            HDR_SCTP.checksum  = crc32c_calculate(&HDR_SCTP, sizeof(HDR_SCTP), CRC32C_PRELOAD);
            if (hdr_data_chunk)
                HDR_SCTP.checksum  = crc32c_calculate(&HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK), HDR_SCTP.checksum);
            HDR_SCTP.checksum  = g_htonl(~crc32c_calculate(&packet_buf[prefix_length], curr_offset, HDR_SCTP.checksum));

            memcpy(&packet_buf[prefix_index], &HDR_SCTP, sizeof(HDR_SCTP));
            prefix_index += (int)sizeof(HDR_SCTP);
        }

        /* Write DATA chunk header */
        if (hdr_data_chunk) {
            memcpy(&packet_buf[prefix_index], &HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK));
            /*prefix_index += (int)sizeof(HDR_DATA_CHUNK);*/
        }

        /* Write Ethernet trailer */
        if (hdr_ethernet && eth_trailer_length > 0) {
            memset(&packet_buf[prefix_length+curr_offset], 0, eth_trailer_length);
        }

        HDR_TCP.seq_num = g_ntohl(HDR_TCP.seq_num) + curr_offset;
        HDR_TCP.seq_num = g_htonl(HDR_TCP.seq_num);

        {
            /* Write the packet */
            struct wtap_pkthdr pkthdr;
            int err;
            gchar *err_info;

            memset(&pkthdr, 0, sizeof(struct wtap_pkthdr));

            pkthdr.rec_type = REC_TYPE_PACKET;
            pkthdr.ts.secs = (guint32)ts_sec;
            pkthdr.ts.nsecs = ts_usec * 1000;
            if (ts_fmt == NULL) {
                ts_usec++;    /* fake packet counter */
            }
            pkthdr.caplen = pkthdr.len = prefix_length + curr_offset + eth_trailer_length;
            pkthdr.pkt_encap = pcap_link_type;
            pkthdr.pack_flags |= direction;
            pkthdr.presence_flags = WTAP_HAS_CAP_LEN|WTAP_HAS_INTERFACE_ID|WTAP_HAS_TS|WTAP_HAS_PACK_FLAGS;

            /* XXX - report errors! */
            if (!wtap_dump(wdh, &pkthdr, packet_buf, &err, &err_info)) {
                switch (err) {

                case WTAP_ERR_UNWRITABLE_REC_DATA:
                    g_free(err_info);
                    break;

                default:
                    break;
                }
            }
        }
    }

    packet_start += curr_offset;
    curr_offset = 0;
}
Exemplo n.º 8
0
void randpkt_loop(randpkt_example* example, guint64 produce_count)
{
	guint i;
	int j;
	int err;
	int len_random;
	int len_this_pkt;
	gchar* err_info;
	union wtap_pseudo_header* ps_header;
	guint8 buffer[65536];
	struct wtap_pkthdr* pkthdr;

	pkthdr = g_new0(struct wtap_pkthdr, 1);

	pkthdr->rec_type = REC_TYPE_PACKET;
	pkthdr->presence_flags = WTAP_HAS_TS;
	pkthdr->pkt_encap = example->sample_wtap_encap;

	memset(pkthdr, 0, sizeof(struct wtap_pkthdr));
	memset(buffer, 0, sizeof(buffer));

	ps_header = &pkthdr->pseudo_header;

	/* Load the sample pseudoheader into our pseudoheader buffer */
	if (example->pseudo_buffer)
		memcpy(ps_header, example->pseudo_buffer, example->pseudo_length);

	/* Load the sample into our buffer */
	if (example->sample_buffer)
		memcpy(buffer, example->sample_buffer, example->sample_length);

	/* Produce random packets */
	for (i = 0; i < produce_count; i++) {
		if (example->produce_max_bytes > 0) {
			len_random = (rand() % example->produce_max_bytes + 1);
		}
		else {
			len_random = 0;
		}

		len_this_pkt = example->sample_length + len_random;

		pkthdr->caplen = len_this_pkt;
		pkthdr->len = len_this_pkt;
		pkthdr->ts.secs = i; /* just for variety */

		for (j = example->pseudo_length; j < (int) sizeof(*ps_header); j++) {
			((guint8*)ps_header)[j] = (rand() % 0x100);
		}

		for (j = example->sample_length; j < len_this_pkt; j++) {
			/* Add format strings here and there */
			if ((int) (100.0*rand()/(RAND_MAX+1.0)) < 3 && j < (len_random - 3)) {
				memcpy(&buffer[j], "%s", 3);
				j += 2;
			} else {
				buffer[j] = (rand() % 0x100);
			}
		}

		if (!wtap_dump(example->dump, pkthdr, buffer, &err, &err_info)) {
			fprintf(stderr, "randpkt: Error writing to %s: %s\n",
			    example->filename, wtap_strerror(err));
			switch (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 writing; note that,
				 * and report the file type/subtype.
				 */
				fprintf(stderr,
				    "Frame has a network type that can't be saved in a \"%s\" file.\n",
				    wtap_file_type_subtype_short_string(WTAP_FILE_TYPE_SUBTYPE_PCAP));
				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 writing; note that,
				 * and report the file type/subtype.
				 */
				fprintf(stderr,
					"Frame is too large for a \"%s\" file.\n",
					wtap_file_type_subtype_short_string(WTAP_FILE_TYPE_SUBTYPE_PCAP));
				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 writing; note that,
				 * and report the file type/subtype.
				 */
				fprintf(stderr,
					"Record has a record type that can't be saved in a \"%s\" file.\n",
					wtap_file_type_subtype_short_string(WTAP_FILE_TYPE_SUBTYPE_PCAP));
				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 writing; note that,
				 * and report the file type/subtype.
				 */
				fprintf(stderr,
					"Record has data that can't be saved in a \"%s\" file.\n(%s)\n",
					wtap_file_type_subtype_short_string(WTAP_FILE_TYPE_SUBTYPE_PCAP),
					err_info != NULL ? err_info : "no information supplied");
				g_free(err_info);
				break;

			default:
				break;
			}
		}
	}

	g_free(pkthdr);
}
Exemplo n.º 9
0
int
main(int argc, char **argv)
{

	wtap_dumper		*dump;
	struct wtap_pkthdr	pkthdr;
	union wtap_pseudo_header *ps_header = &pkthdr.pseudo_header;
	int 			i, j, len_this_pkt, len_random, err;
	gchar                   *err_info;
	guint8			buffer[65536];

	int			opt;

	int			produce_count = 1000; /* number of pkts to produce */
	int			produce_type = PKT_ETHERNET;
	char			*produce_filename = NULL;
	int			produce_max_bytes = 5000;
	pkt_example		*example;
	static const struct option long_options[] = {
		{(char *)"help", no_argument, NULL, 'h'},
		{0, 0, 0, 0 }
	};

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

	while ((opt = getopt_long(argc, argv, "b:c:ht:", long_options, NULL)) != -1) {
		switch (opt) {
			case 'b':	/* max bytes */
				produce_max_bytes = atoi(optarg);
				if (produce_max_bytes > 65536) {
					fprintf(stderr,
					    "randpkt: Max bytes is 65536\n");
					exit(1);
				}
				break;

			case 'c':	/* count */
				produce_count = atoi(optarg);
				break;

			case 't':	/* type of packet to produce */
				produce_type = parse_type(optarg);
				break;

			case 'h':
				usage(FALSE);
				break;
			default:
				usage(TRUE);
				break;
		}
	}

	/* any more command line parameters? */
	if (argc > optind) {
		produce_filename = argv[optind];
	}
	else {
		usage(TRUE);
	}

	example = find_example(produce_type);


	dump = wtap_dump_open(produce_filename, WTAP_FILE_TYPE_SUBTYPE_PCAP,
		example->sample_wtap_encap, produce_max_bytes, FALSE /* compressed */, &err);
	if (!dump) {
		fprintf(stderr,
		    "randpkt: Error writing to %s\n", produce_filename);
		exit(2);
	}

	seed();

	/* reduce max_bytes by # of bytes already in sample */
	if (produce_max_bytes <= example->sample_length) {
		fprintf(stderr,
		    "randpkt: Sample packet length is %d, which is greater than or equal to\n",
		    example->sample_length);
		fprintf(stderr, "your requested max_bytes value of %d\n",
		    produce_max_bytes);
		exit(1);
	}
	else {
		produce_max_bytes -= example->sample_length;
	}

	memset(&pkthdr, 0, sizeof(pkthdr));
	memset(buffer, 0, sizeof(buffer));

	pkthdr.rec_type = REC_TYPE_PACKET;
	pkthdr.presence_flags = WTAP_HAS_TS;
	pkthdr.pkt_encap = example->sample_wtap_encap;

	/* Load the sample pseudoheader into our pseudoheader buffer */
	if (example->pseudo_buffer)
		memcpy(ps_header, example->pseudo_buffer, example->pseudo_length);

	/* Load the sample into our buffer */
	if (example->sample_buffer)
		memcpy(&buffer[0], example->sample_buffer, example->sample_length);

	/* Produce random packets */
	for (i = 0; i < produce_count; i++) {
		if (produce_max_bytes > 0) {
			len_random = (rand() % produce_max_bytes + 1);
		}
		else {
			len_random = 0;
		}

		len_this_pkt = example->sample_length + len_random;

		pkthdr.caplen = len_this_pkt;
		pkthdr.len = len_this_pkt;
		pkthdr.ts.secs = i; /* just for variety */

		for (j = example->pseudo_length; j < (int) sizeof(*ps_header); j++) {
			((guint8*)ps_header)[j] = (rand() % 0x100);
		}

		for (j = example->sample_length; j < len_this_pkt; j++) {
			/* Add format strings here and there */
			if ((int) (100.0*rand()/(RAND_MAX+1.0)) < 3 && j < (len_random - 3)) {
				memcpy(&buffer[j], "%s", 3);
				j += 2;
			} else {
				buffer[j] = (rand() % 0x100);
			}
		}

		/* XXX - report errors! */
		if (!wtap_dump(dump, &pkthdr, &buffer[0], &err, &err_info)) {
			if (err_info != NULL)
				g_free(err_info);
		}
	}

	wtap_dump_close(dump, &err);

	return 0;

}
Exemplo n.º 10
0
/*
 * Opens an .xml file with Trace data formated according to 3GPP TS 32.423 and converts it to
 * an "Exported PDU type file with the entire xml file as the first "packet" appending the
 * raw messages as subsequent packages to be dissected by wireshark.
 */
static wtap_open_return_val
create_temp_pcapng_file(wtap *wth, int *err, gchar **err_info, nettrace_3gpp_32_423_file_info_t *file_info)
{
	int import_file_fd;
	wtap_dumper* wdh_exp_pdu;
	int   exp_pdu_file_err;

	/* pcapng defs */
	wtapng_section_t            *shb_hdr;
	wtapng_iface_descriptions_t *idb_inf;
	wtapng_if_descr_t            int_data;
	GString                     *os_info_str;
	char                        *appname;
	gint64 file_size;
	int packet_size;
	guint8 *packet_buf;
	int wrt_err;
	gchar *wrt_err_info;
	struct wtap_pkthdr phdr;

	gboolean do_random = FALSE;
	char *curr_pos, *next_pos;

	import_file_fd = create_tempfile(&(file_info->tmpname), "Wireshark_PDU_");

	/* Now open a file and dump to it */
	/* Create data for SHB  */
	os_info_str = g_string_new("");
	get_os_version_info(os_info_str);

	appname = g_strdup_printf("Wireshark %s", get_ws_vcs_version_info());

	shb_hdr = g_new(wtapng_section_t, 1);
	shb_hdr->section_length = -1;
	/* options */
	shb_hdr->opt_comment = g_strdup_printf("File converted to Exported PDU format during opening");
	/*
	* UTF-8 string containing the description of the hardware used to create
	* this section.
	*/
	shb_hdr->shb_hardware = NULL;
	/*
	* UTF-8 string containing the name of the operating system used to create
	* this section.
	*/
	shb_hdr->shb_os = g_string_free(os_info_str, FALSE);
	/*
	* UTF-8 string containing the name of the application used to create
	* this section.
	*/
	shb_hdr->shb_user_appl = appname;

	/* Create fake IDB info */
	idb_inf = g_new(wtapng_iface_descriptions_t, 1);
	idb_inf->interface_data = g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));

	/* create the fake interface data */
	int_data.wtap_encap = WTAP_ENCAP_WIRESHARK_UPPER_PDU;
	int_data.time_units_per_second = 1000000; /* default microsecond resolution */
	int_data.link_type = wtap_wtap_encap_to_pcap_encap(WTAP_ENCAP_WIRESHARK_UPPER_PDU);
	int_data.snap_len = WTAP_MAX_PACKET_SIZE;
	int_data.if_name = g_strdup("Fake IF");
	int_data.opt_comment = NULL;
	int_data.if_description = NULL;
	int_data.if_speed = 0;
	int_data.if_tsresol = 6;
	int_data.if_filter_str = NULL;
	int_data.bpf_filter_len = 0;
	int_data.if_filter_bpf_bytes = NULL;
	int_data.if_os = NULL;
	int_data.if_fcslen = -1;
	int_data.num_stat_entries = 0;          /* Number of ISB:s */
	int_data.interface_statistics = NULL;

	g_array_append_val(idb_inf->interface_data, int_data);

	wdh_exp_pdu = wtap_dump_fdopen_ng(import_file_fd, WTAP_FILE_TYPE_SUBTYPE_PCAPNG, WTAP_ENCAP_WIRESHARK_UPPER_PDU,
					  WTAP_MAX_PACKET_SIZE, FALSE, shb_hdr, idb_inf, NULL, &exp_pdu_file_err);
	if (wdh_exp_pdu == NULL) {
		return WTAP_OPEN_ERROR;
	}

	g_free(shb_hdr);
	g_free(appname);

	/* OK we've opend a new pcap-ng file and written the headers, time to do the packets, strt by finding the file size */

	if ((file_size = wtap_file_size(wth, err)) == -1)
		return WTAP_OPEN_ERROR;

	if (file_size > MAX_FILE_SIZE) {
		/*
		* Don't blow up trying to allocate space for an
		* immensely-large file.
		*/
		*err = WTAP_ERR_BAD_FILE;
		*err_info = g_strdup_printf("mime_file: File has %" G_GINT64_MODIFIER "d-byte packet, bigger than maximum of %u",
			file_size, MAX_FILE_SIZE);
		return WTAP_OPEN_ERROR;
	}
	packet_size = (int)file_size;
	/* Allocate the packet buffer
	* (the whole file + Exported PDU tag "protocol" and
	* the string "xml" + 1 filler to end on 4 byte boundary for the tag
	* + End of options 4 bytes
	*/
	/* XXX add the length of exported bdu tag(s) here */
	packet_buf = (guint8 *)g_malloc(packet_size + 12);

	packet_buf[0] = 0;
	packet_buf[1] = 12; /* EXP_PDU_TAG_PROTO_NAME */
	packet_buf[2] = 0;
	packet_buf[3] = 4;
	packet_buf[4] = 0x78; /* "x" */
	packet_buf[5] = 0x6d; /* "m" */
	packet_buf[6] = 0x6c; /* "l" */
	packet_buf[7] = 0;
	/* End of options */
	packet_buf[8] = 0;
	packet_buf[9] = 0;
	packet_buf[10] = 0;
	packet_buf[11] = 0;


	if (!wtap_read_bytes(wth->fh, packet_buf + 12, packet_size, &wrt_err, &wrt_err_info)){
		return WTAP_OPEN_ERROR;
	}

	/* Create the packet header */
	memset(&phdr, 0, sizeof(struct wtap_pkthdr));
	phdr.rec_type = REC_TYPE_PACKET;
	phdr.presence_flags = 0; /* yes, we have no bananas^Wtime stamp */

	phdr.caplen = packet_size + 12;
	phdr.len = packet_size + 12;

	phdr.ts.secs = 0;
	phdr.ts.nsecs = 0;

	/* XXX: report errors! */
	if (!wtap_dump(wdh_exp_pdu, &phdr, packet_buf, &wrt_err, &wrt_err_info)) {
		switch (wrt_err) {

		case WTAP_ERR_UNWRITABLE_REC_DATA:
			g_free(wrt_err_info);
			break;

		default:
			break;
		}
		g_free(packet_buf);
		return WTAP_OPEN_ERROR;
	}

	/* Advance *packet_buf to point at the raw file data */
	curr_pos = packet_buf + 12;
	/* Lets add the raw messages as packets after the main "packet" with the whole file */
	while ((curr_pos = strstr(curr_pos, "<msg")) != NULL){
		wtap_open_return_val temp_val;

		curr_pos = curr_pos + 4;
		next_pos = strstr(curr_pos, "</msg>");
		if (!next_pos){
			/* Somethings wrong, bail out */
			break;
		}
		next_pos = next_pos + 6;
		/* Do we have a raw msg?) */
		curr_pos = strstr(curr_pos, "<rawMsg");
		if (!curr_pos){
			/* No rawMsg, continue */
			curr_pos = next_pos;
			continue;
		}
		curr_pos = curr_pos + 7;
		/* Add the raw msg*/
		temp_val = write_packet_data(wdh_exp_pdu, &phdr, &wrt_err, &wrt_err_info, curr_pos);
		if (temp_val != WTAP_OPEN_MINE){
			g_free(packet_buf);
			return temp_val;
		}
		curr_pos = next_pos;
	}

	/* Close the written file*/
	if (!wtap_dump_close(wdh_exp_pdu, err)){
		g_free(packet_buf);
		return WTAP_OPEN_ERROR;
	}

	g_free(packet_buf);
	/* Now open the file for reading */

	/* Find out if random read was requested */
	if (wth->random_fh){
		do_random = TRUE;
	}
	file_info->wth_tmp_file =
		wtap_open_offline(file_info->tmpname, WTAP_TYPE_AUTO, err, err_info, do_random);

	if (!file_info->wth_tmp_file){
		return WTAP_OPEN_ERROR;
	}

	return WTAP_OPEN_MINE;
}
Exemplo n.º 11
0
/* Parsing something like
 * <rawMsg
 *   protocol="Diameter"
 *   version="1">
 *    [truncated]010001244000012C01000...
 * </rawMsg>
 */
static wtap_open_return_val
write_packet_data(wtap_dumper *wdh, struct wtap_pkthdr *phdr, int *err, gchar **err_info, guint8 *file_buf)
{
	char *curr_pos, *next_pos;
	char proto_name_str[16];
	int tag_str_len = 0;
	int proto_str_len, raw_data_len, pkt_data_len,  exp_pdu_tags_len, i, j;
	guint8 *packet_buf;
	gchar chr;
	gint val1, val2;

	memset(proto_name_str, 0, sizeof(proto_name_str));
	/* Extract the protocol name */
	curr_pos = strstr(file_buf, "protocol=\"");
	if (!curr_pos){
		return WTAP_OPEN_ERROR;
	}
	curr_pos = curr_pos + 10;
	next_pos = strstr(curr_pos, "\"");
	proto_str_len = (int)(next_pos - curr_pos);
	if (proto_str_len > 15){
		return WTAP_OPEN_ERROR;
	}

	g_strlcpy(proto_name_str, curr_pos, proto_str_len+1);
	ascii_strdown_inplace(proto_name_str);

	/* Do string matching and replace with Wiresharks protocol name */
	if (strcmp(proto_name_str, "gtpv2-c") == 0){
		/* Change to gtpv2 */
		proto_name_str[5] = '\0';
		proto_name_str[6] = '\0';
		proto_str_len = 5;
	}
	/* XXX Do we need to check for function="S1" */
	if (strcmp(proto_name_str, "nas") == 0){
		/* Change to nas-eps_plain */
		g_strlcpy(proto_name_str, "nas-eps_plain", 14);
		proto_name_str[13] = '\0';
		proto_str_len = 13;
	}
	/* Find the start of the raw data*/
	curr_pos = strstr(next_pos, ">") + 1;
	next_pos = strstr(next_pos, "<");

	raw_data_len = (int)(next_pos - curr_pos);

	/* Calculate the space needed for exp pdu tags*/
	tag_str_len = (proto_str_len + 3) & 0xfffffffc;
	exp_pdu_tags_len = tag_str_len + 4;


	/* Allocate the packet buf */
	pkt_data_len = raw_data_len / 2;
	packet_buf = (guint8 *)g_malloc0(pkt_data_len + exp_pdu_tags_len +4);

	/* Fill packet buff */
	packet_buf[0] = 0;
	packet_buf[1] = 12; /* EXP_PDU_TAG_PROTO_NAME */
	packet_buf[2] = 0;
	packet_buf[3] = tag_str_len;
	for (i = 4, j = 0; j < tag_str_len; i++, j++){
		packet_buf[i] = proto_name_str[j];
	}

	/* Add end of options */
	packet_buf[i] = 0;
	i++;
	packet_buf[i] = 0;
	i++;
	packet_buf[i] = 0;
	i++;
	packet_buf[i] = 0;
	i++;
	exp_pdu_tags_len = exp_pdu_tags_len + 4;

	/* Convert the hex raw msg data to binary and write to the packet buf*/
	for (; i < (pkt_data_len + exp_pdu_tags_len); i++){
		chr = *curr_pos;
		val1 = g_ascii_xdigit_value(chr);
		curr_pos++;
		chr = *curr_pos;
		val2 = g_ascii_xdigit_value(chr);
		if ((val1 != -1) && (val2 != -1)){
			packet_buf[i] = ((guint8)val1 * 16) + val2;
		}
		else{
			/* Something wrong, bail out */
			g_free(packet_buf);
			return WTAP_OPEN_ERROR;
		}
		curr_pos++;
	}
	/* Construct the phdr */
	memset(phdr, 0, sizeof(struct wtap_pkthdr));
	phdr->rec_type = REC_TYPE_PACKET;
	phdr->presence_flags = 0; /* yes, we have no bananas^Wtime stamp */

	phdr->caplen = pkt_data_len + exp_pdu_tags_len;
	phdr->len = pkt_data_len + exp_pdu_tags_len;

	phdr->ts.secs = 0;
	phdr->ts.nsecs = 0;

	if (!wtap_dump(wdh, phdr, packet_buf, err, err_info)) {
		switch (*err) {

		case WTAP_ERR_UNWRITABLE_REC_DATA:
			g_free(err_info);
			break;

		default:
			break;
		}
		g_free(packet_buf);
		return WTAP_OPEN_ERROR;
	}

	g_free(packet_buf);
	return WTAP_OPEN_MINE;
}
Exemplo n.º 12
0
/*
 * Merges the files based on given input, and invokes callback during
 * execution. Returns MERGE_OK on success, or a MERGE_ERR_XXX on failure; note
 * that the passed-in 'err' variable will be more specific to what failed, and
 * err_info will have pretty output.
 */
merge_result
merge_files(int out_fd, const gchar* out_filename, const int file_type,
            const char *const *in_filenames, const guint in_file_count,
            const gboolean do_append, const idb_merge_mode mode,
            guint snaplen, const gchar *app_name, merge_progress_callback_t* cb,
            int *err, gchar **err_info, guint *err_fileno)
{
    merge_in_file_t    *in_files = NULL, *in_file = NULL;
    int                 frame_type = WTAP_ENCAP_PER_PACKET;
    merge_result        status = MERGE_OK;
    wtap_dumper        *pdh;
    struct wtap_pkthdr *phdr, snap_phdr;
    int                 count = 0;
    gboolean            stop_flag = FALSE;
    GArray             *shb_hdrs = NULL;
    wtapng_iface_descriptions_t *idb_inf = NULL;

    g_assert(out_fd > 0);
    g_assert(in_file_count > 0);
    g_assert(in_filenames != NULL);
    g_assert(err != NULL);
    g_assert(err_info != NULL);
    g_assert(err_fileno != NULL);

    /* if a callback was given, it has to have a callback function ptr */
    g_assert((cb != NULL) ? (cb->callback_func != NULL) : TRUE);

    merge_debug("merge_files: begin");

    /* open the input files */
    if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
                             err, err_info, err_fileno)) {
        merge_debug("merge_files: merge_open_in_files() failed with err=%d", *err);
        return MERGE_ERR_CANT_OPEN_INFILE;
    }

    if (cb)
        cb->callback_func(MERGE_EVENT_INPUT_FILES_OPENED, 0, in_files, in_file_count, cb->data);

    if (snaplen == 0) {
        /* Snapshot length not specified - default to the maximum. */
        snaplen = WTAP_MAX_PACKET_SIZE;
    }

    /*
     * This doesn't tell us that much. It tells us what to set the outfile's
     * encap type to, but that's all - for example, it does *not* tells us
     * whether the input files had the same number of IDBs, for the same exact
     * interfaces, and only one IDB each, so it doesn't actually tell us
     * whether we can merge IDBs into one or not.
     */
    frame_type = merge_select_frame_type(in_file_count, in_files);
    merge_debug("merge_files: got frame_type=%d", frame_type);

    if (cb)
        cb->callback_func(MERGE_EVENT_FRAME_TYPE_SELECTED, frame_type, in_files, in_file_count, cb->data);

    /* prepare the outfile */
    if (file_type == WTAP_FILE_TYPE_SUBTYPE_PCAPNG) {
        shb_hdrs = create_shb_header(in_files, in_file_count, app_name);
        merge_debug("merge_files: SHB created");

        idb_inf = generate_merged_idb(in_files, in_file_count, mode);
        merge_debug("merge_files: IDB merge operation complete, got %u IDBs", idb_inf ? idb_inf->interface_data->len : 0);

        pdh = wtap_dump_fdopen_ng(out_fd, file_type, frame_type, snaplen,
                                  FALSE /* compressed */, shb_hdrs, idb_inf,
                                  NULL, err);
    }
    else {
        pdh = wtap_dump_fdopen(out_fd, file_type, frame_type, snaplen, FALSE /* compressed */, err);
    }

    if (pdh == NULL) {
        merge_close_in_files(in_file_count, in_files);
        g_free(in_files);
        wtap_block_array_free(shb_hdrs);
        wtap_free_idb_info(idb_inf);
        return MERGE_ERR_CANT_OPEN_OUTFILE;
    }

    if (cb)
        cb->callback_func(MERGE_EVENT_READY_TO_MERGE, 0, in_files, in_file_count, cb->data);

    for (;;) {
        *err = 0;

        if (do_append) {
            in_file = merge_append_read_packet(in_file_count, in_files, err,
                                               err_info);
        }
        else {
            in_file = merge_read_packet(in_file_count, in_files, err,
                                        err_info);
        }

        if (in_file == NULL) {
            /* EOF */
            break;
        }

        if (*err != 0) {
            /* I/O error reading from in_file */
            status = MERGE_ERR_CANT_READ_INFILE;
            break;
        }

        count++;
        if (cb)
            stop_flag = cb->callback_func(MERGE_EVENT_PACKET_WAS_READ, count, in_files, in_file_count, cb->data);

        if (stop_flag) {
            /* The user decided to abort the merge. */
            status = MERGE_USER_ABORTED;
            break;
        }

        phdr = wtap_phdr(in_file->wth);

        if (snaplen != 0 && phdr->caplen > snaplen) {
            /*
             * The dumper will only write up to caplen bytes out, so we only
             * need to change that value, instead of cloning the whole packet
             * with fewer bytes.
             *
             * XXX: but do we need to change the IDBs' snap_len?
             */
            snap_phdr = *phdr;
            snap_phdr.caplen = snaplen;
            phdr = &snap_phdr;
        }

        if (file_type == WTAP_FILE_TYPE_SUBTYPE_PCAPNG) {
            /*
             * XXX - We should do this only for record types
             * that pertain to a particular interface; for
             * now, we hardcode that, but we need to figure
             * out a more general way to handle this.
             */
            if (phdr->rec_type == REC_TYPE_PACKET) {
                if (!map_phdr_interface_id(phdr, in_file)) {
                    status = MERGE_ERR_BAD_PHDR_INTERFACE_ID;
                    break;
                }
            }
        }

        if (!wtap_dump(pdh, phdr, wtap_buf_ptr(in_file->wth), err, err_info)) {
            status = MERGE_ERR_CANT_WRITE_OUTFILE;
            break;
        }
    }

    if (cb)
        cb->callback_func(MERGE_EVENT_DONE, count, in_files, in_file_count, cb->data);

    merge_close_in_files(in_file_count, in_files);

    if (status == MERGE_OK || status == MERGE_USER_ABORTED) {
        if (!wtap_dump_close(pdh, err))
            status = MERGE_ERR_CANT_CLOSE_OUTFILE;
    } else {
        /*
         * We already got some error; no need to report another error on
         * close.
         *
         * Don't overwrite the earlier error.
         */
        int close_err = 0;
        (void)wtap_dump_close(pdh, &close_err);
    }

    if (status != MERGE_OK) {
        GString *err_message = NULL;
        gchar   *display_basename = NULL;

        switch(status) {

            case MERGE_ERR_CANT_READ_INFILE:
                *err_info = get_read_error_string(in_files, in_file_count, err, err_info);
                break;

            case MERGE_ERR_CANT_WRITE_OUTFILE: /* fall through */
            case MERGE_ERR_CANT_CLOSE_OUTFILE:
                *err_info = get_write_error_string(in_file, file_type, out_filename, err, err_info);
                break;

            case MERGE_ERR_BAD_PHDR_INTERFACE_ID:
                display_basename = g_filename_display_basename(in_file ? in_file->filename : "UNKNOWN");
                if (*err_info != NULL)
                    g_free(*err_info);
                err_message = g_string_new("");
                g_string_printf(err_message,
                    "Record %u of \"%s\" has an interface ID which does not match any IDB in its file.",
                    in_file ? in_file->packet_num : 0, display_basename);
                g_free(display_basename);
                *err_info = g_string_free(err_message, FALSE);
                break;

            case MERGE_USER_ABORTED: /* not really an error */
            default:
                break;
        }
    }

    g_free(in_files);
    wtap_block_array_free(shb_hdrs);
    wtap_free_idb_info(idb_inf);

    return status;
}
Exemplo n.º 13
0
static merge_result
merge_process_packets(wtap_dumper *pdh, const int file_type,
                      merge_in_file_t *in_files, const guint in_file_count,
                      const gboolean do_append, guint snaplen,
                      merge_progress_callback_t* cb,
                      int *err, gchar **err_info, guint *err_fileno,
                      guint32 *err_framenum)
{
    merge_result        status = MERGE_OK;
    merge_in_file_t    *in_file;
    int                 count = 0;
    gboolean            stop_flag = FALSE;
    struct wtap_pkthdr *phdr, snap_phdr;

    for (;;) {
        *err = 0;

        if (do_append) {
            in_file = merge_append_read_packet(in_file_count, in_files, err,
                                               err_info);
        }
        else {
            in_file = merge_read_packet(in_file_count, in_files, err,
                                        err_info);
        }

        if (in_file == NULL) {
            /* We're at EOF on all input files */
            break;
        }

        if (*err != 0) {
            /* I/O error reading from in_file */
            status = MERGE_ERR_CANT_READ_INFILE;
            break;
        }

        count++;
        if (cb)
            stop_flag = cb->callback_func(MERGE_EVENT_PACKET_WAS_READ, count, in_files, in_file_count, cb->data);

        if (stop_flag) {
            /* The user decided to abort the merge. */
            status = MERGE_USER_ABORTED;
            break;
        }

        phdr = wtap_phdr(in_file->wth);

        if (snaplen != 0 && phdr->caplen > snaplen) {
            /*
             * The dumper will only write up to caplen bytes out, so we only
             * need to change that value, instead of cloning the whole packet
             * with fewer bytes.
             *
             * XXX: but do we need to change the IDBs' snap_len?
             */
            snap_phdr = *phdr;
            snap_phdr.caplen = snaplen;
            phdr = &snap_phdr;
        }

        if (file_type == WTAP_FILE_TYPE_SUBTYPE_PCAPNG) {
            /*
             * XXX - We should do this only for record types
             * that pertain to a particular interface; for
             * now, we hardcode that, but we need to figure
             * out a more general way to handle this.
             */
            if (phdr->rec_type == REC_TYPE_PACKET) {
                if (!map_phdr_interface_id(phdr, in_file)) {
                    status = MERGE_ERR_BAD_PHDR_INTERFACE_ID;
                    break;
                }
            }
        }

        if (!wtap_dump(pdh, phdr, wtap_buf_ptr(in_file->wth), err, err_info)) {
            status = MERGE_ERR_CANT_WRITE_OUTFILE;
            break;
        }
    }

    if (cb)
        cb->callback_func(MERGE_EVENT_DONE, count, in_files, in_file_count, cb->data);

    merge_close_in_files(in_file_count, in_files);

    if (status == MERGE_OK || status == MERGE_USER_ABORTED) {
        if (!wtap_dump_close(pdh, err))
            status = MERGE_ERR_CANT_CLOSE_OUTFILE;
    } else {
        /*
         * We already got some error; no need to report another error on
         * close.
         *
         * Don't overwrite the earlier error.
         */
        int close_err = 0;
        (void)wtap_dump_close(pdh, &close_err);
    }

    if (status == MERGE_OK || in_file == NULL) {
        *err_fileno = 0;
        *err_framenum = 0;
    } else {
        *err_fileno = (guint)(in_file - in_files);
        *err_framenum = in_file->packet_num;
    }

    return status;
}
Exemplo n.º 14
0
int
main(int argc, char **argv)
{

	wtap_dumper		*dump;
	struct wtap_pkthdr	pkthdr;
	union wtap_pseudo_header	ps_header;
	int 			i, j, len_this_pkt, len_random, err;
	guint8			buffer[65536];

	int			opt;
	int			produce_count = 1000; /* number of pkts to produce */
	int			produce_type = PKT_ETHERNET;
	char			*produce_filename = NULL;
	int			produce_max_bytes = 5000;
	pkt_example		*example;

	while ((opt = getopt(argc, argv, "b:c:ht:")) != -1) {
		switch (opt) {
			case 'b':	/* max bytes */
				produce_max_bytes = atoi(optarg);
				if (produce_max_bytes > 65536) {
					fprintf(stderr,
					    "randpkt: Max bytes is 65536\n");
					exit(1);
				}
				break;

			case 'c':	/* count */
				produce_count = atoi(optarg);
				break;

			case 't':	/* type of packet to produce */
				produce_type = parse_type(optarg);
				break;

			case 'h':
			default:
				usage();
				break;
		}
	}

	/* any more command line parameters? */
	if (argc > optind) {
		produce_filename = argv[optind];
	}
	else {
		usage();
	}

	example = find_example(produce_type);


	dump = wtap_dump_open(produce_filename, WTAP_FILE_PCAP,
		example->sample_wtap_encap, produce_max_bytes, FALSE /* compressed */, &err);
	if (!dump) {
		fprintf(stderr,
		    "randpkt: Error writing to %s\n", produce_filename);
		exit(2);
	}

	seed();

	/* reduce max_bytes by # of bytes already in sample */
	if (produce_max_bytes <= example->sample_length) {
		fprintf(stderr,
		    "randpkt: Sample packet length is %d, which is greater than or equal to\n",
		    example->sample_length);
		fprintf(stderr, "your requested max_bytes value of %d\n",
		    produce_max_bytes);
		exit(1);
	}
	else {
		produce_max_bytes -= example->sample_length;
	}

	memset(&pkthdr, 0, sizeof(pkthdr));
	memset(&ps_header, 0, sizeof(ps_header));
	memset(buffer, 0, sizeof(buffer));

	pkthdr.pkt_encap = example->sample_wtap_encap;

	/* Load the sample pseudoheader into our pseudoheader buffer */
	if (example->pseudo_buffer)
		memcpy(&ps_header, example->pseudo_buffer, example->pseudo_length);

	/* Load the sample into our buffer */
	if (example->sample_buffer)
		memcpy(&buffer[0], example->sample_buffer, example->sample_length);

	/* Produce random packets */
	for (i = 0; i < produce_count; i++) {
		if (produce_max_bytes > 0) {
			len_random = (rand() % produce_max_bytes + 1);
		}
		else {
			len_random = 0;
		}

		len_this_pkt = example->sample_length + len_random;

		pkthdr.caplen = len_this_pkt;
		pkthdr.len = len_this_pkt;
		pkthdr.ts.secs = i; /* just for variety */

		for (j = example->pseudo_length; j < (int) sizeof(ps_header); j++) {
			((guint8*)&ps_header)[j] = (rand() % 0x100);
		}

		for (j = example->sample_length; j < len_this_pkt; j++) {
			/* Add format strings here and there */
			if ((int) (100.0*rand()/(RAND_MAX+1.0)) < 3 && j < (len_random - 3)) {
				memcpy(&buffer[j], "%s", 3);
				j += 2;
			} else {
				buffer[j] = (rand() % 0x100);
			}
		}

		wtap_dump(dump, &pkthdr, &ps_header, &buffer[0], &err);
	}

	wtap_dump_close(dump, &err);

	return 0;

}
Exemplo n.º 15
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;
}