1fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang// 2fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang// Copyright (C) 2015 The Android Open Source Project 3fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang// 4fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang// Licensed under the Apache License, Version 2.0 (the "License"); 5fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang// you may not use this file except in compliance with the License. 6fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang// You may obtain a copy of the License at 7fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang// 8fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang// http://www.apache.org/licenses/LICENSE-2.0 9fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang// 10fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang// Unless required by applicable law or agreed to in writing, software 11fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang// distributed under the License is distributed on an "AS IS" BASIS, 12fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang// See the License for the specific language governing permissions and 14fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang// limitations under the License. 15fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang// 16fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang 17fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang#include "dhcp_client/dhcp_options_parser.h" 18fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang 19fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang#include <netinet/in.h> 20fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang 21fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang#include <string> 22fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang#include <utility> 23fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang#include <vector> 24fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang 25fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang#include <base/logging.h> 26fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang#include <base/macros.h> 2757c5f54dae6f34e5569e6e343a7793f7db365debNingyuan Wang#include <shill/net/byte_string.h> 2857c5f54dae6f34e5569e6e343a7793f7db365debNingyuan Wang 2957c5f54dae6f34e5569e6e343a7793f7db365debNingyuan Wangusing shill::ByteString; 30fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang 31fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wangnamespace dhcp_client { 32fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang 33fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wangbool UInt8Parser::GetOption(const uint8_t* buffer, 34fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang uint8_t length, 35fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang void* value) { 36fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang if (length != sizeof(uint8_t)) { 37fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang LOG(ERROR) << "Invalid option length field"; 38fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang return false; 39fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang } 40fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang uint8_t* value_uint8 = static_cast<uint8_t*>(value); 41fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang *value_uint8 = *buffer; 42fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang return true; 43fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang} 44fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang 45fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wangbool UInt16Parser::GetOption(const uint8_t* buffer, 46fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang uint8_t length, 47fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang void* value) { 48fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang if (length != sizeof(uint16_t)) { 49fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang LOG(ERROR) << "Invalid option length field"; 50fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang return false; 51fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang } 52fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang uint16_t* value_uint16 = static_cast<uint16_t*>(value); 53fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang *value_uint16 = ntohs(*reinterpret_cast<const uint16_t*>(buffer)); 54fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang return true; 55fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang} 56fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang 57fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wangbool UInt32Parser::GetOption(const uint8_t* buffer, 58fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang uint8_t length, 59fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang void* value) { 60fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang if (length != sizeof(uint32_t)) { 61fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang LOG(ERROR) << "Invalid option length field"; 62fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang return false; 63fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang } 64fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang uint32_t* value_uint32 = static_cast<uint32_t*>(value); 65fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang *value_uint32 = ntohl(*reinterpret_cast<const uint32_t*>(buffer)); 66fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang return true; 67fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang} 68fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang 69fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wangbool UInt8ListParser::GetOption(const uint8_t* buffer, 70fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang uint8_t length, 71fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang void* value) { 72fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang if (length == 0) { 73fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang LOG(ERROR) << "Invalid option length field"; 74fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang return false; 75fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang } 76fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang std::vector<uint8_t>* value_vector = 77fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang static_cast<std::vector<uint8_t>*>(value); 78fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang for (int i = 0; i < length; i++) { 79fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang uint8_t content = *reinterpret_cast<const uint8_t*>(buffer); 80fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang value_vector->push_back(content); 81fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang buffer += sizeof(uint8_t); 82fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang } 83fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang return true; 84fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang} 85fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang 86fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wangbool UInt16ListParser::GetOption(const uint8_t* buffer, 87fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang uint8_t length, 88fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang void* value) { 89fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang if (length == 0 || length % sizeof(uint16_t)) { 90fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang LOG(ERROR) << "Invalid option length field"; 91fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang return false; 92fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang } 93fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang int num_int16s = length / sizeof(uint16_t); 94fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang std::vector<uint16_t>* value_vector = 95fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang static_cast<std::vector<uint16_t>*>(value); 96fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang for (int i = 0; i < num_int16s; i++) { 97fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang uint16_t content = *reinterpret_cast<const uint16_t*>(buffer); 98fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang content = ntohs(content); 99fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang value_vector->push_back(content); 100fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang buffer += sizeof(uint16_t); 101fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang } 102fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang return true; 103fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang} 104fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang 105fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wangbool UInt32ListParser::GetOption(const uint8_t* buffer, 106fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang uint8_t length, 107fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang void* value) { 108fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang if (length == 0 || length % sizeof(uint32_t)) { 109fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang LOG(ERROR) << "Invalid option length field"; 110fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang return false; 111fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang } 112fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang int num_int32s = length / sizeof(uint32_t); 113fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang std::vector<uint32_t>* value_vector = 114fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang static_cast<std::vector<uint32_t>*>(value); 115fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang for (int i = 0; i < num_int32s; i++) { 116fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang uint32_t content = *reinterpret_cast<const uint32_t*>(buffer); 117fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang content = ntohl(content); 118fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang value_vector->push_back(content); 119fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang buffer += sizeof(uint32_t); 120fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang } 121fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang return true; 122fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang} 123fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang 124fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wangbool UInt32PairListParser::GetOption(const uint8_t* buffer, 125fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang uint8_t length, 126fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang void* value) { 127fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang if (length == 0 || length % (2 * sizeof(uint32_t))) { 128fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang LOG(ERROR) << "Invalid option length field"; 129fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang return false; 130fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang } 131fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang int num_int32pairs = length / (2 * sizeof(uint32_t)); 132fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang std::vector<std::pair<uint32_t, uint32_t>>* value_vector = 133fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang static_cast<std::vector<std::pair<uint32_t, uint32_t>>*>(value); 134fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang for (int i = 0; i < num_int32pairs; i++) { 135fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang uint32_t first = *reinterpret_cast<const uint32_t*>(buffer); 136fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang first = ntohl(first); 137fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang buffer += sizeof(uint32_t); 138fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang uint32_t second = *reinterpret_cast<const uint32_t*>(buffer); 139fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang second = ntohl(second); 140fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang value_vector->push_back(std::pair<uint32_t, uint32_t>(first, second)); 141fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang buffer += sizeof(uint32_t); 142fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang } 143fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang return true; 144fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang} 145fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang 146fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wangbool BoolParser::GetOption(const uint8_t* buffer, 147fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang uint8_t length, 148fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang void* value) { 149fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang if (length != sizeof(uint8_t)) { 150fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang LOG(ERROR) << "Invalid option length field"; 151fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang return false; 152fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang } 153fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang uint8_t content = *buffer; 154fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang bool* enable = static_cast<bool*>(value); 155fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang if (content == 1) { 156fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang *enable = true; 157fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang } else if (content == 0) { 158fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang *enable = false; 159fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang } else { 160fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang LOG(ERROR) << "Invalid option value field"; 161fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang return false; 162fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang } 163fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang return true; 164fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang} 165fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang 166fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wangbool StringParser::GetOption(const uint8_t* buffer, 167fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang uint8_t length, 168fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang void* value) { 169fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang if (length == 0) { 170fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang LOG(ERROR) << "Invalid option length field"; 171fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang return false; 172fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang } 173fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang std::string* option_string = static_cast<std::string*>(value); 174fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang option_string->assign(reinterpret_cast<const char*>(buffer), length); 175fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang return true; 176fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang} 177fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang 17857c5f54dae6f34e5569e6e343a7793f7db365debNingyuan Wangbool ByteArrayParser::GetOption(const uint8_t* buffer, 17957c5f54dae6f34e5569e6e343a7793f7db365debNingyuan Wang uint8_t length, 18057c5f54dae6f34e5569e6e343a7793f7db365debNingyuan Wang void* value) { 18157c5f54dae6f34e5569e6e343a7793f7db365debNingyuan Wang if (length == 0) { 18257c5f54dae6f34e5569e6e343a7793f7db365debNingyuan Wang LOG(ERROR) << "Invalid option length field"; 18357c5f54dae6f34e5569e6e343a7793f7db365debNingyuan Wang return false; 18457c5f54dae6f34e5569e6e343a7793f7db365debNingyuan Wang } 18557c5f54dae6f34e5569e6e343a7793f7db365debNingyuan Wang ByteString* byte_array = 18657c5f54dae6f34e5569e6e343a7793f7db365debNingyuan Wang static_cast<ByteString*>(value); 18757c5f54dae6f34e5569e6e343a7793f7db365debNingyuan Wang *byte_array = ByteString(buffer, length); 18857c5f54dae6f34e5569e6e343a7793f7db365debNingyuan Wang return true; 18957c5f54dae6f34e5569e6e343a7793f7db365debNingyuan Wang} 19057c5f54dae6f34e5569e6e343a7793f7db365debNingyuan Wang 191fb71bebf66ca47ba222f64325e065350a4a927e0Ningyuan Wang} // namespace dhcp_client 192