summaryrefslogtreecommitdiffstats
path: root/src/bin/perfdhcp/pkt_transform.h
blob: 99cdb19d1850537a7f2ce7cb73011519a925f8e6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// Copyright (C) 2012-2019 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef PKT_TRANSFORM_H
#define PKT_TRANSFORM_H

#include <perfdhcp/localized_option.h>

#include <dhcp/option.h>

namespace isc {
namespace perfdhcp {

/// \brief Read and write raw data to DHCP packets.
///
/// This class provides static functions to read/write raw data from/to the
/// packet buffer. When reading data with the unpack() method, the
/// corresponding options objects are updated.  When writing to the packet
/// buffer with pack(), options objects carry input data to be written.
///
/// This class is used both by \ref PerfPkt4 and
/// \ref PerfPkt6 classes in case DHCP packets are created
/// from template files. In this case, some of the template
/// packet's options are replaced before sending it to the
/// server. Offset of specific options are provided from the
/// command line by the perfdhcp tool user, and passed in an
/// options collection.
class PktTransform {
public:

    /// \brief Prepares on-wire format from raw buffer.
    ///
    /// The method copies the input buffer and options contents
    /// to the output buffer. The input buffer must contain whole
    /// initial packet data. Parts of this data will be
    /// overridden by options data specified in an options
    /// collection. Such options must have their offsets within
    /// a packet specified (see \ref LocalizedOption to find out
    /// how to specify options offset).
    ///
    /// \note The specified options must fit into the size of the
    /// initial packet data. A call to this method will fail
    /// if the option's offset + its size is beyond the packet's size.
    ///
    /// \param universe Universe used, V4 or V6
    /// \param in_buffer Input buffer holding initial packet
    /// data, this can be directly read from template file
    /// \param options Options collection with offsets
    /// \param transid_offset offset of transaction id in a packet,
    /// transaction ID will be written to output buffer at this
    /// offset
    /// \param transid Transaction ID value
    /// \param out_buffer Output buffer holding "packed" data
    ///
    /// \return false, if pack operation failed.
    static bool pack(const dhcp::Option::Universe universe,
                     const dhcp::OptionBuffer& in_buffer,
                     const dhcp::OptionCollection& options,
                     const size_t transid_offset,
                     const uint32_t transid,
                     util::OutputBuffer& out_buffer);

    /// \brief Handles selective binary packet parsing.
    ///
    /// This method handles the parsing of packets that have non-default
    /// options or transaction ID offsets. The client class has to use
    /// \ref isc::dhcp::Pkt6::addOption to specify which options to parse.
    /// Each option should be of the \ref isc::perfdhcp::LocalizedOption
    /// type with the offset value specified.
    ///
    /// \param universe universe used, V4 or V6
    /// \param in_buffer input buffer to be parsed
    /// \param options options collection with options offsets
    /// \param transid_offset offset of transaction id in input buffer
    /// \param transid transaction id value read from input buffer
    ///
    /// \return false, if unpack operation failed.
    static bool unpack(const dhcp::Option::Universe universe,
                       const dhcp::OptionBuffer& in_buffer,
                       const dhcp::OptionCollection& options,
                       const size_t transid_offset,
                       uint32_t& transid);

    /// \brief Replace contents of buffer with vector.
    ///
    /// Function replaces data of the buffer with data from vector.
    ///
    /// \param in_buffer destination buffer.
    /// \param dest_pos position in destination buffer.
    /// \param first beginning of data range in source vector.
    /// \param last end of data range in source vector.
    static void writeAt(dhcp::OptionBuffer& in_buffer, size_t dest_pos,
                        std::vector<uint8_t>::iterator first,
                        std::vector<uint8_t>::iterator last);

    /// \brief Replace contents of one vector with uint16 value.
    ///
    /// Function replaces data inside one vector with uint16_t value.
    ///
    /// \param in_buffer destination buffer.
    /// \param dest_pos position in destination buffer.
    /// \param val value to be written.
    template<typename T>
    static void writeValueAt(dhcp::OptionBuffer& in_buffer, size_t dest_pos,
                        T val) {
        // @todo consider replacing the loop with switch statement
        // checking sizeof(T).
        for (int i = 0; i < sizeof(T); ++i) {
            in_buffer[dest_pos + i] = (val >> 8 * (sizeof(T) - i - 1)) & 0xFF;
        }
    }

private:
    /// \brief Replaces contents of options in a buffer.
    ///
    /// The method uses a localized options collection to
    /// replace parts of packet data (e.g. data read
    /// from template file).
    /// This private method is called from \ref PktTransform::pack
    ///
    /// \param in_buffer input buffer holding initial packet data.
    /// \param out_buffer output buffer with "packed" options.
    /// \param options options collection with actual data and offsets.
    ///
    /// \throw isc::Unexpected if options update failed.
    static void packOptions(const dhcp::OptionBuffer& in_buffer,
                            const dhcp::OptionCollection& options,
                            util::OutputBuffer& out_buffer);

    /// \brief Reads contents of specified options from buffer.
    ///
    /// The method reads options data from the input buffer
    /// and stores it in options objects. Offsets of the options
    /// must be specified (see \ref LocalizedOption to find out how to specify
    /// the option offset).
    /// This private method is called by \ref PktTransform::unpack.
    ///
    /// \note This method iterates through all options in an
    /// options collection, checks the offset of the option
    /// in input buffer and reads data from the buffer to
    /// update the option's buffer. If the provided options collection
    /// is empty, a call to this method will have no effect.
    ///
    /// \param universe universe used, V4 or V6
    /// \param in_buffer input buffer to be parsed.
    /// \param options options collection with their offsets
    /// in input buffer specified.
    ///
    /// \throw isc::Unexpected if options unpack failed.
    static void unpackOptions(const dhcp::OptionBuffer& in_buffer,
                              const dhcp::OptionCollection& options);

};

} // namespace perfdhcp
} // namespace isc

#endif // PKT_TRANSFORM_H