1 // 2 // Copyright (C) 2015 The Android Open Source Project 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #include "dhcp_client/dhcp_options_writer.h" 18 19 #include <netinet/in.h> 20 21 #include <string> 22 #include <utility> 23 #include <vector> 24 25 #include <base/logging.h> 26 #include <base/macros.h> 27 28 #include "dhcp_client/dhcp_options.h" 29 30 using shill::ByteString; 31 namespace { 32 base::LazyInstance<dhcp_client::DHCPOptionsWriter> g_dhcp_options_writer 33 = LAZY_INSTANCE_INITIALIZER; 34 } // namespace 35 36 namespace dhcp_client { 37 38 DHCPOptionsWriter* DHCPOptionsWriter::GetInstance() { 39 return g_dhcp_options_writer.Pointer(); 40 } 41 42 int DHCPOptionsWriter::WriteUInt8Option(ByteString* buffer, 43 uint8_t option_code, 44 uint8_t value) { 45 uint8_t length = sizeof(uint8_t); 46 buffer->Append(ByteString(reinterpret_cast<const char*>(&option_code), 47 sizeof(uint8_t))); 48 buffer->Append(ByteString(reinterpret_cast<const char*>(&length), 49 sizeof(uint8_t))); 50 buffer->Append(ByteString(reinterpret_cast<const char*>(&value), 51 sizeof(uint8_t))); 52 return length + 2; 53 } 54 55 int DHCPOptionsWriter::WriteUInt16Option(ByteString* buffer, 56 uint8_t option_code, 57 uint16_t value) { 58 uint8_t length = sizeof(uint16_t); 59 uint16_t value_net = htons(value); 60 buffer->Append(ByteString(reinterpret_cast<const char*>(&option_code), 61 sizeof(uint8_t))); 62 buffer->Append(ByteString(reinterpret_cast<const char*>(&length), 63 sizeof(uint8_t))); 64 buffer->Append(ByteString(reinterpret_cast<const char*>(&value_net), 65 sizeof(uint16_t))); 66 return length + 2; 67 } 68 69 int DHCPOptionsWriter::WriteUInt32Option(ByteString* buffer, 70 uint8_t option_code, 71 uint32_t value) { 72 uint8_t length = sizeof(uint32_t); 73 uint32_t value_net = htonl(value); 74 buffer->Append(ByteString(reinterpret_cast<const char*>(&option_code), 75 sizeof(uint8_t))); 76 buffer->Append(ByteString(reinterpret_cast<const char*>(&length), 77 sizeof(uint8_t))); 78 buffer->Append(ByteString(reinterpret_cast<const char*>(&value_net), 79 sizeof(uint32_t))); 80 return length + 2; 81 } 82 83 int DHCPOptionsWriter::WriteUInt8ListOption(ByteString* buffer, 84 uint8_t option_code, 85 const std::vector<uint8_t>& value) { 86 if (value.size() == 0) { 87 LOG(ERROR) << "Faild to write option: " << static_cast<int>(option_code) 88 << ", because value size cannot be 0"; 89 return -1; 90 } 91 uint8_t length = value.size() * sizeof(uint8_t); 92 buffer->Append(ByteString(reinterpret_cast<const char*>(&option_code), 93 sizeof(uint8_t))); 94 buffer->Append(ByteString(reinterpret_cast<const char*>(&length), 95 sizeof(uint8_t))); 96 buffer->Append(ByteString(reinterpret_cast<const char*>(&value.front()), 97 length * sizeof(uint8_t))); 98 return length + 2; 99 } 100 101 int DHCPOptionsWriter::WriteUInt16ListOption(ByteString* buffer, 102 uint8_t option_code, 103 const std::vector<uint16_t>& value) { 104 if (value.size() == 0) { 105 LOG(ERROR) << "Faild to write option: " << static_cast<int>(option_code) 106 << ", because value size cannot be 0"; 107 return -1; 108 } 109 uint8_t length = value.size() * sizeof(uint16_t); 110 buffer->Append(ByteString(reinterpret_cast<const char*>(&option_code), 111 sizeof(uint8_t))); 112 buffer->Append(ByteString(reinterpret_cast<const char*>(&length), 113 sizeof(uint8_t))); 114 for (uint16_t element : value) { 115 uint16_t element_net = htons(element); 116 buffer->Append(ByteString(reinterpret_cast<const char *>(&element_net), 117 sizeof(uint16_t))); 118 } 119 return length + 2; 120 } 121 122 int DHCPOptionsWriter::WriteUInt32ListOption(ByteString* buffer, 123 uint8_t option_code, 124 const std::vector<uint32_t>& value) { 125 if (value.size() == 0) { 126 LOG(ERROR) << "Faild to write option: " << static_cast<int>(option_code) 127 << ", because value size cannot be 0"; 128 return -1; 129 } 130 uint8_t length = value.size() * sizeof(uint32_t); 131 buffer->Append(ByteString(reinterpret_cast<const char*>(&option_code), 132 sizeof(uint8_t))); 133 buffer->Append(ByteString(reinterpret_cast<const char*>(&length), 134 sizeof(uint8_t))); 135 for (uint32_t element : value) { 136 uint32_t element_net = htonl(element); 137 buffer->Append(ByteString(reinterpret_cast<const char*>(&element_net), 138 sizeof(uint32_t))); 139 } 140 return length + 2; 141 } 142 143 int DHCPOptionsWriter::WriteUInt32PairListOption(ByteString* buffer, 144 uint8_t option_code, 145 const std::vector<std::pair<uint32_t, uint32_t>>& value) { 146 if (value.size() == 0) { 147 LOG(ERROR) << "Faild to write option: " << static_cast<int>(option_code) 148 << ", because value size cannot be 0"; 149 return -1; 150 } 151 uint8_t length = value.size() * sizeof(uint32_t) * 2; 152 buffer->Append(ByteString(reinterpret_cast<const char*>(&option_code), 153 sizeof(uint8_t))); 154 buffer->Append(ByteString(reinterpret_cast<const char*>(&length), 155 sizeof(uint8_t))); 156 for (auto element : value) { 157 uint32_t first_net = htonl(element.first); 158 uint32_t second_net = htonl(element.second); 159 buffer->Append(ByteString(reinterpret_cast<const char*>(&first_net), 160 sizeof(uint32_t))); 161 buffer->Append(ByteString(reinterpret_cast<const char*>(&second_net), 162 sizeof(uint32_t))); 163 } 164 return length + 2; 165 } 166 167 int DHCPOptionsWriter::WriteBoolOption(ByteString* buffer, 168 uint8_t option_code, 169 const bool value) { 170 uint8_t length = sizeof(uint8_t); 171 uint8_t value_uint8 = value ? 1 : 0; 172 buffer->Append(ByteString(reinterpret_cast<const char*>(&option_code), 173 sizeof(uint8_t))); 174 buffer->Append(ByteString(reinterpret_cast<const char*>(&length), 175 sizeof(uint8_t))); 176 buffer->Append(ByteString(reinterpret_cast<const char*>(&value_uint8), 177 sizeof(uint8_t))); 178 return length + 2; 179 } 180 181 int DHCPOptionsWriter::WriteStringOption(ByteString* buffer, 182 uint8_t option_code, 183 const std::string& value) { 184 if (value.size() == 0) { 185 LOG(ERROR) << "Faild to write option: " << static_cast<int>(option_code) 186 << ", because value size cannot be 0"; 187 return -1; 188 } 189 uint8_t length = value.size(); 190 buffer->Append(ByteString(reinterpret_cast<const char*>(&option_code), 191 sizeof(uint8_t))); 192 buffer->Append(ByteString(reinterpret_cast<const char*>(&length), 193 sizeof(uint8_t))); 194 buffer->Append(ByteString(reinterpret_cast<const char*>(&value.front()), 195 length * sizeof(uint8_t))); 196 return length + 2; 197 } 198 199 int DHCPOptionsWriter::WriteByteArrayOption(ByteString* buffer, 200 uint8_t option_code, 201 const ByteString& value) { 202 uint8_t length = value.GetLength(); 203 buffer->Append(ByteString(reinterpret_cast<const char*>(&option_code), 204 sizeof(uint8_t))); 205 buffer->Append(ByteString(reinterpret_cast<const char*>(&length), 206 sizeof(uint8_t))); 207 208 buffer->Append(value); 209 return length + 2; 210 } 211 212 int DHCPOptionsWriter::WriteEndTag(ByteString* buffer) { 213 uint8_t tag = kDHCPOptionEnd; 214 buffer->Append(ByteString(reinterpret_cast<const char*>(&tag), 215 sizeof(uint8_t))); 216 return 1; 217 } 218 219 } // namespace dhcp_client 220