Home | History | Annotate | Download | only in dhcp_client
      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 
     29 using shill::ByteString;
     30 
     31 namespace dhcp_client {
     32 
     33 bool 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 
     45 bool 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 
     57 bool 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 
     69 bool 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 
     86 bool 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 
    105 bool 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 
    124 bool 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 
    146 bool 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 
    166 bool 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 
    178 bool 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