Manipulate pcap file

Yesterday, to debug a tricky issue, I need to implement 2 utilities to manipulate pcap files through pcap library. The framework is simple: open source and destination files:

    ......
    char err[PCAP_ERRBUF_SIZE];
    src_handle = pcap_open_offline(src_file, err);
    if (src_handle == NULL) {
        printf("Open %s failed: %s\n", src_file, err);
        return EXIT_FAILURE;
    }

    dst_handle = pcap_open_dead(DLT_EN10MB, 262144);
    pcap_dumper_t *dst_dump = pcap_dump_open(dst_handle, dst_file);
    if (dst_dump == NULL) {
        printf("pcap_dump_open error: %s\n", pcap_geterr(dst_handle));
        return EXIT_FAILURE;
    }
    ......
    pcap_dump_close(dst_dump);
    pcap_close(dst_handle);
    pcap_close(src_handle);

    return EXIT_SUCCESS;

The first tool was creating out-of-order packets which I cached the previous packet and inserted it after other one:

......
    while (1)
    {
        struct pcap_pkthdr *hdr = NULL;
        static struct pcap_pkthdr src_index_hdr;

        const u_char *data = NULL;
        static u_char *src_index_data = NULL;

        static int count = 0;

        int ret = pcap_next_ex(src_handle, &hdr, &data);
        if (ret == 1) {
            if (++count == src_index) {
                memcpy(&src_index_hdr, hdr, sizeof(struct pcap_pkthdr));
                src_index_data = malloc(hdr->caplen);
                if (src_index_data == NULL) {
                    printf("malloc failed\n");
                    return EXIT_FAILURE;
                }
                memcpy(src_index_data, data, hdr->caplen);
            } else {
                pcap_dump((u_char *)dst_dump, hdr, data);
                if (count == dst_index) {
                    pcap_dump((u_char *)dst_dump, &src_index_hdr, src_index_data);
                }
            }
        } else if (ret == PCAP_ERROR_BREAK) {
            break;
        } else {
            printf("pcap_next_ex error: %s\n", pcap_geterr(src_handle));
            return EXIT_FAILURE;
        }
    }
......

The second was simple, just dumped the first 1200 packets into another file.

P.S., the full code is here.

Empty struct in C

Empty struct in C is undefined behaviour (refer C17 spec, section 6.7.2.1):

If the struct-declaration-list does not contain any named members, either directly or via an anonymous structure or anonymous union, the behavior is undefined.

On my Linux, I use both gcc (v9.1.0) and clang (v8.0.0) to compile following code:

$ cat test.c
#include <stdio.h>

typedef struct A {} A;

int main()
{
    printf("%zu\n", sizeof(A));
}

No warnings, and both ouput:
0

Reference:
C empty struct — what does this mean/do?.

Configure uncrustify in Visual Studio Code

Visual Studio Code already has uncrustify extension:

After installing it, you can modify the uncrustify‘s configuration file path. On macOS: Code -> Preferences -> Settings-> Extensions -> Uncrusify configuration -> Configure Path: Osx:

Then edit settings.json:

{
    ......
    "uncrustify.configPath.osx": "/Users/nanxiao/Documents/uncrustify.cfg",
} 

Now you can format your code through “Option + shift + F” command.(You should disable C/C++ extension‘s formatting function, please refer troubleshooting . Update in 2023: for currentVisual Studio Code, it will prompt you select uncrustify or other extensions as the format tool)

BTW, you can enable formatting code when saving file function:

{
    ......
    "editor.formatOnSave": true,
}