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