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