1#include <stdio.h>
2#include <stdlib.h>
3#include <fcntl.h>
4#include <errno.h>
5#include <string.h>
6
7#include <pcap/pcap.h>
8
9FILE * outfile = NULL;
10
11static int bufferToFile(const char * name, const uint8_t *Data, size_t Size) {
12    FILE * fd;
13    if (remove(name) != 0) {
14        if (errno != ENOENT) {
15            printf("failed remove, errno=%d\n", errno);
16            return -1;
17        }
18    }
19    fd = fopen(name, "wb");
20    if (fd == NULL) {
21        printf("failed open, errno=%d\n", errno);
22        return -2;
23    }
24    if (fwrite (Data, 1, Size, fd) != Size) {
25        fclose(fd);
26        return -3;
27    }
28    fclose(fd);
29    return 0;
30}
31
32void fuzz_openFile(const char * name) {
33    if (outfile != NULL) {
34        fclose(outfile);
35    }
36    outfile = fopen(name, "w");
37}
38
39int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
40    pcap_t * pkts;
41    char errbuf[PCAP_ERRBUF_SIZE];
42    const u_char *pkt;
43    struct pcap_pkthdr *header;
44    int r;
45    size_t filterSize;
46    char * filter;
47    struct bpf_program bpf;
48
49
50    //initialize output file
51    if (outfile == NULL) {
52        outfile = fopen("/dev/null", "w");
53        if (outfile == NULL) {
54            return 0;
55        }
56    }
57
58    if (Size < 1) {
59        return 0;
60    }
61    filterSize = Data[0];
62    if (Size < 1+filterSize || filterSize == 0) {
63        return 0;
64    }
65
66    //rewrite buffer to a file as libpcap does not have buffer inputs
67    if (bufferToFile("/tmp/fuzz.pcap", Data+1+filterSize, Size-(1+filterSize)) < 0) {
68        return 0;
69    }
70
71    //initialize structure
72    pkts = pcap_open_offline("/tmp/fuzz.pcap", errbuf);
73    if (pkts == NULL) {
74        fprintf(outfile, "Couldn't open pcap file %s\n", errbuf);
75        return 0;
76    }
77
78    filter = malloc(filterSize);
79    memcpy(filter, Data+1, filterSize);
80    //null terminate string
81    filter[filterSize-1] = 0;
82
83    if (pcap_compile(pkts, &bpf, filter, 1, PCAP_NETMASK_UNKNOWN) == 0) {
84        //loop over packets
85        r = pcap_next_ex(pkts, &header, &pkt);
86        while (r > 0) {
87            //checks filter
88            fprintf(outfile, "packet length=%d/%d filter=%d\n",header->caplen, header->len, pcap_offline_filter(&bpf, header, pkt));
89            r = pcap_next_ex(pkts, &header, &pkt);
90        }
91        //close structure
92        pcap_close(pkts);
93        pcap_freecode(&bpf);
94    }
95    else {
96        pcap_close(pkts);
97    }
98    free(filter);
99
100    return 0;
101}
102