/src/kea/src/lib/dhcpsrv/packet_fuzzer.h
Line | Count | Source |
1 | | // Copyright (C) 2016-2024 Internet Systems Consortium, Inc. ("ISC") |
2 | | // |
3 | | // This Source Code Form is subject to the terms of the Mozilla Public |
4 | | // License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | // file, You can obtain one at http://mozilla.org/MPL/2.0/. |
6 | | |
7 | | #ifndef DHCPSRV_PACKET_FUZZER_H |
8 | | #define DHCPSRV_PACKET_FUZZER_H |
9 | | |
10 | | #ifdef FUZZING |
11 | | |
12 | | #include <asiolink/io_address.h> |
13 | | #include <exceptions/exceptions.h> |
14 | | |
15 | | #include <arpa/inet.h> |
16 | | #include <net/if.h> |
17 | | #include <sys/socket.h> |
18 | | #include <unistd.h> |
19 | | |
20 | | #include <string> |
21 | | |
22 | | namespace isc { |
23 | | |
24 | | /// @brief AFL Fuzzing |
25 | | /// |
26 | | /// Persistent-mode AFL fuzzing has the AFL fuzzer send packets of data to |
27 | | /// stdin of the program being tested. The program processes the data and |
28 | | /// signals to AFL that it is complete. |
29 | | /// |
30 | | /// To reduce the code changes required, the scheme adopted for Kea is that |
31 | | /// the AFL data read from stdin is written to an address/port on which Kea |
32 | | /// is listening. Kea then reads the data from that port and processes it |
33 | | /// in the usual way. |
34 | | /// |
35 | | /// The PacketFuzzer class handles the transfer of data between AFL and Kea. After |
36 | | /// suitable initialization, its transfer() method is called in the main |
37 | | /// processing loop, right before Kea waits for input. The method handles the |
38 | | /// read from stdin and the write to the selected address port. |
39 | | |
40 | | class PacketFuzzer { |
41 | | public: |
42 | | /// @brief size of the buffer used to transfer data between AFL and Kea. |
43 | | /// |
44 | | /// This is much larger than the data that will be sent to Kea (so AFL |
45 | | /// data may be trimmed). However, it does allow for AFL to send quite |
46 | | /// large packets without resulting in AFL synchronization problems because |
47 | | /// Kea has not read all the data sent. |
48 | | static constexpr size_t BUFFER_SIZE = 256 * 1024; |
49 | | |
50 | | /// @brief maximum size of packets fuzzing thread will send to Kea |
51 | | /// |
52 | | /// This is below the maximum size of data that we will allow Kea to put |
53 | | /// into a single UDP datagram so as to avoid any "data too big" errors |
54 | | /// when trying to send it to the port on which Kea listens. |
55 | | static constexpr size_t MAX_SEND_SIZE = 64000; |
56 | | |
57 | | /// @brief Number of packets Kea will process before shutting down. |
58 | | /// |
59 | | /// After the shutdown, AFL will restart it. This safety switch is here for |
60 | | /// eliminating cases where Kea goes into a weird state and stops |
61 | | /// processing packets properly. This can be overridden by setting the |
62 | | /// environment variable KEA_AFL_LOOP_MAX. |
63 | | static constexpr long MAX_LOOP_COUNT = 1000; |
64 | | |
65 | | /// @brief Constructor |
66 | | /// |
67 | | /// Sets up data structures to access the address/port being used to |
68 | | /// transfer data from AFL to Kea. |
69 | | /// |
70 | | /// @param port Port on which the server is listening, and hence the |
71 | | /// port to which the fuzzer will send input from AFL. |
72 | | PacketFuzzer(uint16_t const port, |
73 | | std::string const interface, |
74 | | std::string const address); |
75 | | |
76 | | /// @brief Destructor |
77 | | /// |
78 | | /// Closes the socket used for transferring data from stdin to the selected |
79 | | /// interface. |
80 | | ~PacketFuzzer(); |
81 | | |
82 | | /// @brief Transfer Data |
83 | | /// |
84 | | /// Called immediately prior to Kea reading data, this reads stdin (where |
85 | | /// AFL will have sent the packet being tested) and copies the data to the |
86 | | /// interface on which Kea is listening. |
87 | | void transfer() const; |
88 | | void transfer(uint8_t const* data, size_t size) const; |
89 | | |
90 | | /// @brief Return Max Loop Count |
91 | | /// |
92 | | /// Returns the maximum number of loops (i.e. AFL packets processed) before |
93 | | /// Kea exits. This is the value of the environment variable |
94 | | /// FUZZ_AFL_LOOP_MAX, or the class constant MAX_LOOP_COUNT if that is not |
95 | | /// defined. |
96 | | /// |
97 | | /// @return Maximum loop count |
98 | 0 | long maxLoopCount() const { |
99 | 0 | return loop_max_; |
100 | 0 | } |
101 | | |
102 | | private: |
103 | | /// @brief Create address structures |
104 | | /// |
105 | | /// Create the address structures describing the address/port on whick Kea |
106 | | /// is listening for packets from AFL. |
107 | | /// |
108 | | /// @param port Port to be used. |
109 | | /// @param interface Interface through which the fuzzer is sending packets to Kea. |
110 | | /// @param io_address Address on the interface that will be used. |
111 | | /// |
112 | | /// @throws FuzzInitFail Thrown if the address is not in the expected |
113 | | /// format. |
114 | | void createAddressStructures(uint16_t const port, |
115 | | std::string const& interface, |
116 | | isc::asiolink::IOAddress const& io_address); |
117 | | |
118 | | // Other member variables. |
119 | | long loop_max_; //< Maximum number of loop iterations |
120 | | size_t sockaddr_len_; //< Length of the structure |
121 | | struct sockaddr* sockaddr_ptr_; //< Pointer to structure used |
122 | | struct sockaddr_in servaddr4_; //< IPv6 address information |
123 | | struct sockaddr_in6 servaddr6_; //< IPv6 address information |
124 | | int sockfd_; //< Socket used to transfer data |
125 | | }; // class PacketFuzzer |
126 | | |
127 | | /// @brief Exception thrown if fuzzing initialization fails. |
128 | | class FuzzInitFail : public Exception { |
129 | | public: |
130 | | FuzzInitFail(const char* file, size_t line, const char* what) : |
131 | 0 | isc::Exception(file, line, what) { } |
132 | | }; // class FuzzInitFail |
133 | | |
134 | | } // namespace isc |
135 | | |
136 | | #endif // FUZZING |
137 | | |
138 | | #endif // DHCPSRV_PACKET_FUZZER_H |