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 30using shill::ByteString; 31namespace { 32base::LazyInstance<dhcp_client::DHCPOptionsWriter> g_dhcp_options_writer 33 = LAZY_INSTANCE_INITIALIZER; 34} // namespace 35 36namespace dhcp_client { 37 38DHCPOptionsWriter* DHCPOptionsWriter::GetInstance() { 39 return g_dhcp_options_writer.Pointer(); 40} 41 42int 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 55int 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 69int 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 83int 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 101int 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 122int 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 143int 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 167int 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 181int 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 199int 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 212int 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