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_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