Changeset d9ca546 for lib


Ignore:
Timestamp:
01/07/19 10:31:16 (21 months ago)
Author:
Jacob Van Walraven <jcv9@…>
Branches:
develop
Children:
ebd6275
Parents:
1668208
git-author:
Jacob Van Walraven <jcv9@…> (12/11/18 16:28:53)
git-committer:
Jacob Van Walraven <jcv9@…> (01/07/19 10:31:16)
Message:

Add write support for pcapng

Location:
lib
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • lib/format_pcapng.c

    rd439067 rd9ca546  
    133133typedef struct pcapng_interface_t pcapng_interface_t;
    134134
     135struct pcapng_timestamp {
     136        uint32_t timehigh;
     137        uint32_t timelow;
     138};
     139
    135140struct pcapng_interface_t {
    136141
     
    160165        uint16_t allocatedinterfaces;
    161166        uint16_t nextintid;
     167
     168};
     169
     170struct pcapng_format_data_out_t {
     171        iow_t *file;
     172        int compress_level;
     173        int compress_type;
     174        int flag;
     175
     176        /* Section data */
     177        bool byteswapped;
     178
     179        /* Interface data */
     180        uint16_t nextintid;
     181        libtrace_dlt_t lastdlt;
    162182};
    163183
     
    174194typedef struct pcapng_peeker pcapng_hdr_t;
    175195
    176 
    177196#define DATA(x) ((struct pcapng_format_data_t *)((x)->format_data))
     197#define DATAOUT(x) ((struct pcapng_format_data_out_t*)((x)->format_data))
    178198
    179199static pcapng_interface_t *lookup_interface(libtrace_t *libtrace,
     
    194214
    195215        if (DATA(packet->trace)->byteswapped)
    196                 return byteswap32(*btype);
     216                return byteswap32(*btype);
    197217        return *btype;
     218}
     219
     220static inline uint32_t pcapng_get_header_type(const libtrace_packet_t *packet) {
     221        uint32_t *type = (uint32_t *)packet->buffer;
     222        if (DATAOUT(packet->trace)->byteswapped)
     223                return byteswap32(*type);
     224        return *type;
     225}
     226static inline uint32_t pcapng_get_blocklen(const libtrace_packet_t *packet) {
     227        struct pcapng_peeker *hdr = (struct pcapng_peeker *)packet->buffer;
     228
     229        if (DATAOUT(packet->trace)->byteswapped) {
     230                return byteswap32(hdr->blocklen);
     231        } else {
     232                return hdr->blocklen;
     233        }
    198234}
    199235
     
    212248        }
    213249        return 0;
     250}
     251
     252static struct pcapng_timestamp pcapng_get_timestamp(libtrace_packet_t *packet) {
     253        struct timespec ts = trace_get_timespec(packet);
     254        uint64_t time = (((uint64_t) ts.tv_sec) * 1000000LL) + ts.tv_nsec / 1000;
     255
     256        struct pcapng_timestamp timestamp;
     257        timestamp.timehigh = time >> 32;
     258        timestamp.timelow = time & 0xFFFFFFFF;
     259
     260        return timestamp;
    214261}
    215262
     
    232279
    233280        return 0;
     281}
     282
     283static int pcapng_config_output(libtrace_out_t *libtrace, trace_option_output_t option,
     284        void *value) {
     285
     286        switch (option) {
     287                case TRACE_OPTION_OUTPUT_COMPRESS:
     288                        DATAOUT(libtrace)->compress_level = *(int *)value;
     289                        return 0;
     290                case TRACE_OPTION_OUTPUT_COMPRESSTYPE:
     291                        DATAOUT(libtrace)->compress_type = *(int *)value;
     292                        return 0;
     293                case TRACE_OPTION_OUTPUT_FILEFLAGS:
     294                        DATAOUT(libtrace)->flag = *(int *)value;
     295                        return 0;
     296                default:
     297                        trace_set_err_out(libtrace, TRACE_ERR_UNKNOWN_OPTION,
     298                                "Unknown option");
     299                        return -1;
     300        }
    234301}
    235302
     
    272339}
    273340
     341static int pcapng_init_output(libtrace_out_t *libtrace) {
     342        libtrace->format_data = malloc(sizeof(struct pcapng_format_data_out_t));
     343
     344        DATAOUT(libtrace)->file = NULL;
     345        DATAOUT(libtrace)->compress_level = 0;
     346        DATAOUT(libtrace)->compress_type = TRACE_OPTION_COMPRESSTYPE_NONE;
     347        DATAOUT(libtrace)->flag = O_CREAT|O_WRONLY;
     348
     349        DATAOUT(libtrace)->byteswapped = false;
     350
     351        DATAOUT(libtrace)->nextintid = 0;
     352        DATAOUT(libtrace)->lastdlt = 0;
     353
     354        return 0;
     355}
     356
    274357static int pcapng_fin_input(libtrace_t *libtrace) {
    275358
     
    287370        free(libtrace->format_data);
    288371        return 0;
     372}
     373
     374static int pcapng_fin_output(libtrace_out_t *libtrace) {
     375        if (DATAOUT(libtrace)->file) {
     376                wandio_wdestroy(DATAOUT(libtrace)->file);
     377        }
     378        free(libtrace->format_data);
     379        libtrace->format_data = NULL;
     380        return 0;
    289381}
    290382
     
    432524}
    433525
     526static int pcapng_write_packet(libtrace_out_t *libtrace, libtrace_packet_t *packet) {
     527
     528        if (!libtrace) {
     529                fprintf(stderr, "NULL trace passed into pcapng_write_packet()\n");
     530                return TRACE_ERR_NULL_TRACE;
     531        }
     532        if (!packet) {
     533                trace_set_err_out(libtrace, TRACE_ERR_NULL_PACKET, "NULL packet passed "
     534                        "into pcapng_write_packet()\n");
     535                return -1;
     536        }
     537
     538        uint32_t blocklen;
     539        libtrace_linktype_t linktype;
     540        uint32_t remaining;
     541        void *link;
     542
     543        /* If the file is not open, open it. First item must be SBH header */
     544        if (!DATAOUT(libtrace)->file) {
     545                /* open output file */
     546                DATAOUT(libtrace)->file = trace_open_file_out(libtrace,
     547                                        DATAOUT(libtrace)->compress_type,
     548                                        DATAOUT(libtrace)->compress_level,
     549                                        DATAOUT(libtrace)->flag);
     550
     551                /* If packet is a section block header just output it */
     552                pcapng_sec_t *hdr = (pcapng_sec_t *)packet->buffer;
     553                if (hdr->blocktype == PCAPNG_SECTION_TYPE) {
     554
     555                        pcapng_sec_t *sechdr = (pcapng_sec_t *)packet->buffer;
     556
     557                        /* now we need to determine the byte ordering so we know
     558                         * how much to write out */
     559                        if (sechdr->ordering == 0x1A2B3C4D) {
     560                                DATAOUT(libtrace)->byteswapped = false;
     561                        } else if (sechdr->ordering == 0x4D3C2B1A) {
     562                                DATAOUT(libtrace)->byteswapped = true;
     563                        }
     564
     565                        wandio_wwrite(DATAOUT(libtrace)->file, packet->buffer,
     566                                pcapng_get_blocklen(packet));
     567
     568                        return 0;
     569                }
     570
     571                /* Create section block */
     572                pcapng_sec_t sechdr;
     573                sechdr.blocktype = PCAPNG_SECTION_TYPE;
     574                sechdr.blocklen = 28;
     575                sechdr.ordering = 0x1A2B3C4D;
     576                sechdr.majorversion = 1;
     577                sechdr.minorversion = 0;
     578                sechdr.sectionlen = 0xFFFFFFFFFFFFFFFF;
     579
     580                wandio_wwrite(DATAOUT(libtrace)->file, &sechdr, sizeof(sechdr));
     581                wandio_wwrite(DATAOUT(libtrace)->file, &sechdr.blocklen, sizeof(sechdr.blocklen));
     582
     583        }
     584
     585        /* Output interface type if we have not already */
     586        if (DATAOUT(libtrace)->nextintid == 0) {
     587
     588                if (pcapng_get_header_type(packet) == PCAPNG_INTERFACE_TYPE) {
     589                        wandio_wwrite(DATAOUT(libtrace)->file, packet->buffer,
     590                                pcapng_get_blocklen(packet));
     591                        /* increment the interface counter */
     592                        DATAOUT(libtrace)->nextintid += 1;
     593                        return 0;
     594                }
     595
     596                /* Create interface block*/
     597                pcapng_int_t inthdr;
     598                inthdr.blocktype = PCAPNG_INTERFACE_TYPE;
     599                inthdr.blocklen = 20;
     600                inthdr.linktype = libtrace_to_pcap_dlt(trace_get_link_type(packet));
     601                inthdr.reserved = 0;
     602                inthdr.snaplen = 0;
     603
     604                wandio_wwrite(DATAOUT(libtrace)->file, &inthdr, sizeof(inthdr));
     605                wandio_wwrite(DATAOUT(libtrace)->file, &inthdr.blocklen, sizeof(inthdr.blocklen));
     606
     607                /* increment the interface counter */
     608                DATAOUT(libtrace)->nextintid += 1;
     609        }
     610
     611        switch (pcapng_get_header_type(packet)) {
     612                case PCAPNG_OLD_PACKET_TYPE: {
     613                        wandio_wwrite(DATAOUT(libtrace)->file, packet->buffer,
     614                                pcapng_get_blocklen(packet));
     615                        return 0;
     616                }
     617                case PCAPNG_SIMPLE_PACKET_TYPE: {
     618                        wandio_wwrite(DATAOUT(libtrace)->file, packet->buffer,
     619                                pcapng_get_blocklen(packet));
     620                        return 0;
     621                }
     622                case PCAPNG_NAME_RESOLUTION_TYPE: {
     623                        wandio_wwrite(DATAOUT(libtrace)->file, packet->buffer,
     624                                pcapng_get_blocklen(packet));
     625                        return 0;
     626                }
     627                case PCAPNG_INTERFACE_STATS_TYPE: {
     628                        wandio_wwrite(DATAOUT(libtrace)->file, packet->buffer,
     629                                pcapng_get_blocklen(packet));
     630                        return 0;
     631                }
     632                case PCAPNG_ENHANCED_PACKET_TYPE: {
     633                        wandio_wwrite(DATAOUT(libtrace)->file, packet->buffer,
     634                                pcapng_get_blocklen(packet));
     635                        return 0;
     636                }
     637                case PCAPNG_CUSTOM_TYPE: {
     638                        wandio_wwrite(DATAOUT(libtrace)->file, packet->buffer,
     639                                pcapng_get_blocklen(packet));
     640                        return 0;
     641                }
     642                default: {
     643                        /* not a pcapng format libtrace knows */
     644                        break;
     645                }
     646        }
     647
     648        /* If we made it this far constuct a enhanced packet */
     649        link = trace_get_packet_buffer(packet, &linktype, &remaining);
     650
     651        /* convert packet into enhanced packet */
     652        pcapng_epkt_t epkthdr;
     653
     654        epkthdr.wlen = trace_get_wire_length(packet);
     655        epkthdr.caplen = trace_get_capture_length(packet);
     656
     657        /* capture length should always be less than the wirelength */
     658        if (epkthdr.caplen > epkthdr.wlen) {
     659                epkthdr.caplen = epkthdr.wlen;
     660        }
     661
     662        /* calculate padding to 32bits */
     663        uint32_t padding = epkthdr.caplen % 4;
     664        if (padding) { padding = 4 - padding; }
     665        void *padding_data = calloc(1, padding);
     666
     667        /* calculate the block length */
     668        blocklen = sizeof(epkthdr) + sizeof(epkthdr.blocklen) + epkthdr.caplen + padding;
     669
     670        epkthdr.blocktype = PCAPNG_ENHANCED_PACKET_TYPE;
     671        epkthdr.blocklen = blocklen;
     672        epkthdr.interfaceid = DATAOUT(libtrace)->nextintid-1;
     673
     674        /* get pcapng_timestamp */
     675        struct pcapng_timestamp ts = pcapng_get_timestamp(packet);
     676        epkthdr.timestamp_high = ts.timehigh;
     677        epkthdr.timestamp_low = ts.timelow;
     678
     679        /* output enhanced packet header */
     680        wandio_wwrite(DATAOUT(libtrace)->file, &epkthdr, sizeof(epkthdr));
     681        /* output the packet */
     682        wandio_wwrite(DATAOUT(libtrace)->file, link, (size_t)epkthdr.caplen);
     683        /* output padding */
     684        wandio_wwrite(DATAOUT(libtrace)->file, padding_data, (size_t)padding);
     685        /* output rest of the enhanced packet */
     686        wandio_wwrite(DATAOUT(libtrace)->file, &epkthdr.blocklen, sizeof(epkthdr.blocklen));
     687
     688        /* release padding memory */
     689        free(padding_data);
     690
     691        return 0;
     692}
     693
     694static int pcapng_flush_output(libtrace_out_t *libtrace) {
     695        return wandio_wflush(DATAOUT(libtrace)->file);
     696}
     697
    434698static int pcapng_read_section(libtrace_t *libtrace,
    435699                libtrace_packet_t *packet, uint32_t flags) {
     
    14361700        pcapng_start_input,             /* start_input */
    14371701        NULL,                           /* pause_input */
    1438         NULL,                           /* init_output */
    1439         NULL,                           /* config_output */
     1702        pcapng_init_output,             /* init_output */
     1703        pcapng_config_output,           /* config_output */
    14401704        NULL,                           /* start_output */
    14411705        pcapng_fin_input,               /* fin_input */
    1442         NULL,                           /* fin_output */
     1706        pcapng_fin_output,              /* fin_output */
    14431707        pcapng_read_packet,             /* read_packet */
    14441708        pcapng_prepare_packet,          /* prepare_packet */
    14451709        NULL,                           /* fin_packet */
    1446         NULL,                           /* write_packet */
    1447         NULL,                           /* flush_output */
     1710        pcapng_write_packet,            /* write_packet */
     1711        pcapng_flush_output,            /* flush_output */
    14481712        pcapng_get_link_type,           /* get_link_type */
    14491713        pcapng_get_direction,           /* get_direction */
     
    14741738        register_format(&pcapng);
    14751739}
    1476 
  • lib/libtrace.h.in

    rd439067 rd9ca546  
    346346        /** NULL passed misc **/
    347347        TRACE_ERR_NULL = -31,
     348        /** Err with trace output file **/
     349        TRACE_ERR_OUTPUT_FILE = -32,
    348350};
    349351
Note: See TracChangeset for help on using the changeset viewer.