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_parser.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#include <shill/net/byte_string.h> 28 29using shill::ByteString; 30 31namespace dhcp_client { 32 33bool UInt8Parser::GetOption(const uint8_t* buffer, 34 uint8_t length, 35 void* value) { 36 if (length != sizeof(uint8_t)) { 37 LOG(ERROR) << "Invalid option length field"; 38 return false; 39 } 40 uint8_t* value_uint8 = static_cast<uint8_t*>(value); 41 *value_uint8 = *buffer; 42 return true; 43} 44 45bool UInt16Parser::GetOption(const uint8_t* buffer, 46 uint8_t length, 47 void* value) { 48 if (length != sizeof(uint16_t)) { 49 LOG(ERROR) << "Invalid option length field"; 50 return false; 51 } 52 uint16_t* value_uint16 = static_cast<uint16_t*>(value); 53 *value_uint16 = ntohs(*reinterpret_cast<const uint16_t*>(buffer)); 54 return true; 55} 56 57bool UInt32Parser::GetOption(const uint8_t* buffer, 58 uint8_t length, 59 void* value) { 60 if (length != sizeof(uint32_t)) { 61 LOG(ERROR) << "Invalid option length field"; 62 return false; 63 } 64 uint32_t* value_uint32 = static_cast<uint32_t*>(value); 65 *value_uint32 = ntohl(*reinterpret_cast<const uint32_t*>(buffer)); 66 return true; 67} 68 69bool UInt8ListParser::GetOption(const uint8_t* buffer, 70 uint8_t length, 71 void* value) { 72 if (length == 0) { 73 LOG(ERROR) << "Invalid option length field"; 74 return false; 75 } 76 std::vector<uint8_t>* value_vector = 77 static_cast<std::vector<uint8_t>*>(value); 78 for (int i = 0; i < length; i++) { 79 uint8_t content = *reinterpret_cast<const uint8_t*>(buffer); 80 value_vector->push_back(content); 81 buffer += sizeof(uint8_t); 82 } 83 return true; 84} 85 86bool UInt16ListParser::GetOption(const uint8_t* buffer, 87 uint8_t length, 88 void* value) { 89 if (length == 0 || length % sizeof(uint16_t)) { 90 LOG(ERROR) << "Invalid option length field"; 91 return false; 92 } 93 int num_int16s = length / sizeof(uint16_t); 94 std::vector<uint16_t>* value_vector = 95 static_cast<std::vector<uint16_t>*>(value); 96 for (int i = 0; i < num_int16s; i++) { 97 uint16_t content = *reinterpret_cast<const uint16_t*>(buffer); 98 content = ntohs(content); 99 value_vector->push_back(content); 100 buffer += sizeof(uint16_t); 101 } 102 return true; 103} 104 105bool UInt32ListParser::GetOption(const uint8_t* buffer, 106 uint8_t length, 107 void* value) { 108 if (length == 0 || length % sizeof(uint32_t)) { 109 LOG(ERROR) << "Invalid option length field"; 110 return false; 111 } 112 int num_int32s = length / sizeof(uint32_t); 113 std::vector<uint32_t>* value_vector = 114 static_cast<std::vector<uint32_t>*>(value); 115 for (int i = 0; i < num_int32s; i++) { 116 uint32_t content = *reinterpret_cast<const uint32_t*>(buffer); 117 content = ntohl(content); 118 value_vector->push_back(content); 119 buffer += sizeof(uint32_t); 120 } 121 return true; 122} 123 124bool UInt32PairListParser::GetOption(const uint8_t* buffer, 125 uint8_t length, 126 void* value) { 127 if (length == 0 || length % (2 * sizeof(uint32_t))) { 128 LOG(ERROR) << "Invalid option length field"; 129 return false; 130 } 131 int num_int32pairs = length / (2 * sizeof(uint32_t)); 132 std::vector<std::pair<uint32_t, uint32_t>>* value_vector = 133 static_cast<std::vector<std::pair<uint32_t, uint32_t>>*>(value); 134 for (int i = 0; i < num_int32pairs; i++) { 135 uint32_t first = *reinterpret_cast<const uint32_t*>(buffer); 136 first = ntohl(first); 137 buffer += sizeof(uint32_t); 138 uint32_t second = *reinterpret_cast<const uint32_t*>(buffer); 139 second = ntohl(second); 140 value_vector->push_back(std::pair<uint32_t, uint32_t>(first, second)); 141 buffer += sizeof(uint32_t); 142 } 143 return true; 144} 145 146bool BoolParser::GetOption(const uint8_t* buffer, 147 uint8_t length, 148 void* value) { 149 if (length != sizeof(uint8_t)) { 150 LOG(ERROR) << "Invalid option length field"; 151 return false; 152 } 153 uint8_t content = *buffer; 154 bool* enable = static_cast<bool*>(value); 155 if (content == 1) { 156 *enable = true; 157 } else if (content == 0) { 158 *enable = false; 159 } else { 160 LOG(ERROR) << "Invalid option value field"; 161 return false; 162 } 163 return true; 164} 165 166bool StringParser::GetOption(const uint8_t* buffer, 167 uint8_t length, 168 void* value) { 169 if (length == 0) { 170 LOG(ERROR) << "Invalid option length field"; 171 return false; 172 } 173 std::string* option_string = static_cast<std::string*>(value); 174 option_string->assign(reinterpret_cast<const char*>(buffer), length); 175 return true; 176} 177 178bool ByteArrayParser::GetOption(const uint8_t* buffer, 179 uint8_t length, 180 void* value) { 181 if (length == 0) { 182 LOG(ERROR) << "Invalid option length field"; 183 return false; 184 } 185 ByteString* byte_array = 186 static_cast<ByteString*>(value); 187 *byte_array = ByteString(buffer, length); 188 return true; 189} 190 191} // namespace dhcp_client 192