xref: /freebsd/contrib/libpcap/testprogs/fuzz/fuzz_both.c (revision a50d73d5782a351ad83e8d1f84d11720a12e70d3)
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 
9 FILE * outfile = NULL;
10 
11 static 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 
32 void fuzz_openFile(const char * name) {
33     if (outfile != NULL) {
34         fclose(outfile);
35     }
36     outfile = fopen(name, "w");
37 }
38 
39 int 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