1d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang//
2d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang// Copyright (C) 2015 The Android Open Source Project
3d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang//
4d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang// Licensed under the Apache License, Version 2.0 (the "License");
5d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang// you may not use this file except in compliance with the License.
6d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang// You may obtain a copy of the License at
7d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang//
8d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang//      http://www.apache.org/licenses/LICENSE-2.0
9d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang//
10d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang// Unless required by applicable law or agreed to in writing, software
11d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang// distributed under the License is distributed on an "AS IS" BASIS,
12d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang// See the License for the specific language governing permissions and
14d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang// limitations under the License.
15d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang//
16d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang
17d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang#include "dhcp_client/dhcp_options_writer.h"
18d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang
19d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang#include <netinet/in.h>
20d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang
21d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang#include <string>
22d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang#include <utility>
23d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang#include <vector>
24d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang
25d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang#include <base/logging.h>
26d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang#include <base/macros.h>
27d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang
28d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang#include "dhcp_client/dhcp_options.h"
29d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang
3015c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wangusing shill::ByteString;
31d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wangnamespace {
32d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wangbase::LazyInstance<dhcp_client::DHCPOptionsWriter> g_dhcp_options_writer
33d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang    = LAZY_INSTANCE_INITIALIZER;
34d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang}  // namespace
35d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang
36d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wangnamespace dhcp_client {
37d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang
38d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan WangDHCPOptionsWriter* DHCPOptionsWriter::GetInstance() {
39d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang  return g_dhcp_options_writer.Pointer();
40d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang}
41d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang
4215c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wangint DHCPOptionsWriter::WriteUInt8Option(ByteString* buffer,
43d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang                                        uint8_t option_code,
44d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang                                        uint8_t value) {
4515c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  uint8_t length = sizeof(uint8_t);
4615c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  buffer->Append(ByteString(reinterpret_cast<const char*>(&option_code),
4715c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                            sizeof(uint8_t)));
4815c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  buffer->Append(ByteString(reinterpret_cast<const char*>(&length),
4915c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                            sizeof(uint8_t)));
5015c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  buffer->Append(ByteString(reinterpret_cast<const char*>(&value),
5115c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                            sizeof(uint8_t)));
5215c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  return length + 2;
53d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang}
54d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang
5515c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wangint DHCPOptionsWriter::WriteUInt16Option(ByteString* buffer,
56d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang                                         uint8_t option_code,
57d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang                                         uint16_t value) {
5815c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  uint8_t length = sizeof(uint16_t);
5915c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  uint16_t value_net = htons(value);
6015c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  buffer->Append(ByteString(reinterpret_cast<const char*>(&option_code),
6115c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                            sizeof(uint8_t)));
6215c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  buffer->Append(ByteString(reinterpret_cast<const char*>(&length),
6315c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                            sizeof(uint8_t)));
6415c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  buffer->Append(ByteString(reinterpret_cast<const char*>(&value_net),
6515c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                            sizeof(uint16_t)));
6615c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  return length + 2;
67d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang}
68d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang
6915c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wangint DHCPOptionsWriter::WriteUInt32Option(ByteString* buffer,
70d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang                                         uint8_t option_code,
71d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang                                         uint32_t value) {
7215c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  uint8_t length = sizeof(uint32_t);
7315c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  uint32_t value_net = htonl(value);
7415c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  buffer->Append(ByteString(reinterpret_cast<const char*>(&option_code),
7515c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                            sizeof(uint8_t)));
7615c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  buffer->Append(ByteString(reinterpret_cast<const char*>(&length),
7715c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                            sizeof(uint8_t)));
7815c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  buffer->Append(ByteString(reinterpret_cast<const char*>(&value_net),
7915c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                            sizeof(uint32_t)));
8015c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  return length + 2;
81d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang}
82d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang
8315c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wangint DHCPOptionsWriter::WriteUInt8ListOption(ByteString* buffer,
84d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang    uint8_t option_code,
85d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang    const std::vector<uint8_t>& value) {
8615c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  if (value.size() == 0) {
8715c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang    LOG(ERROR) << "Faild to write option: " << static_cast<int>(option_code)
8815c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang               << ", because value size cannot be 0";
8915c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang    return -1;
90d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang  }
9115c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  uint8_t length = value.size() * sizeof(uint8_t);
9215c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  buffer->Append(ByteString(reinterpret_cast<const char*>(&option_code),
9315c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                            sizeof(uint8_t)));
9415c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  buffer->Append(ByteString(reinterpret_cast<const char*>(&length),
9515c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                            sizeof(uint8_t)));
9615c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  buffer->Append(ByteString(reinterpret_cast<const char*>(&value.front()),
9715c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                            length * sizeof(uint8_t)));
9815c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  return length + 2;
99d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang}
100d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang
10115c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wangint DHCPOptionsWriter::WriteUInt16ListOption(ByteString* buffer,
102d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang    uint8_t option_code,
103d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang    const std::vector<uint16_t>& value) {
104d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang  if (value.size() == 0) {
105d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang    LOG(ERROR) << "Faild to write option: " << static_cast<int>(option_code)
106d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang               << ", because value size cannot be 0";
107d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang    return -1;
108d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang  }
10915c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  uint8_t length = value.size() * sizeof(uint16_t);
11015c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  buffer->Append(ByteString(reinterpret_cast<const char*>(&option_code),
11115c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                            sizeof(uint8_t)));
11215c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  buffer->Append(ByteString(reinterpret_cast<const char*>(&length),
11315c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                            sizeof(uint8_t)));
114d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang  for (uint16_t element : value) {
11515c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang    uint16_t element_net = htons(element);
11615c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang    buffer->Append(ByteString(reinterpret_cast<const char *>(&element_net),
11715c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                              sizeof(uint16_t)));
118d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang  }
11915c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  return length + 2;
120d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang}
121d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang
12215c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wangint DHCPOptionsWriter::WriteUInt32ListOption(ByteString* buffer,
123d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang    uint8_t option_code,
124d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang    const std::vector<uint32_t>& value) {
125d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang  if (value.size() == 0) {
126d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang    LOG(ERROR) << "Faild to write option: " << static_cast<int>(option_code)
127d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang               << ", because value size cannot be 0";
128d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang    return -1;
129d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang  }
13015c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  uint8_t length = value.size() * sizeof(uint32_t);
13115c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  buffer->Append(ByteString(reinterpret_cast<const char*>(&option_code),
13215c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                            sizeof(uint8_t)));
13315c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  buffer->Append(ByteString(reinterpret_cast<const char*>(&length),
13415c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                            sizeof(uint8_t)));
135d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang  for (uint32_t element : value) {
13615c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang    uint32_t element_net = htonl(element);
13715c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang    buffer->Append(ByteString(reinterpret_cast<const char*>(&element_net),
13815c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                              sizeof(uint32_t)));
139d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang  }
14015c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  return length + 2;
141d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang}
142d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang
14315c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wangint DHCPOptionsWriter::WriteUInt32PairListOption(ByteString* buffer,
144d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang    uint8_t option_code,
145d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang    const std::vector<std::pair<uint32_t, uint32_t>>& value) {
146d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang  if (value.size() == 0) {
147d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang    LOG(ERROR) << "Faild to write option: " << static_cast<int>(option_code)
148d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang               << ", because value size cannot be 0";
149d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang    return -1;
150d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang  }
15115c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  uint8_t length = value.size() * sizeof(uint32_t) * 2;
15215c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  buffer->Append(ByteString(reinterpret_cast<const char*>(&option_code),
15315c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                            sizeof(uint8_t)));
15415c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  buffer->Append(ByteString(reinterpret_cast<const char*>(&length),
15515c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                            sizeof(uint8_t)));
156d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang  for (auto element : value) {
15715c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang    uint32_t first_net = htonl(element.first);
15815c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang    uint32_t second_net = htonl(element.second);
15915c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang    buffer->Append(ByteString(reinterpret_cast<const char*>(&first_net),
16015c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                              sizeof(uint32_t)));
16115c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang    buffer->Append(ByteString(reinterpret_cast<const char*>(&second_net),
16215c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                              sizeof(uint32_t)));
163d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang  }
16415c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  return length + 2;
165d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang}
166d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang
16715c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wangint DHCPOptionsWriter::WriteBoolOption(ByteString* buffer,
168d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang                                       uint8_t option_code,
169d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang                                       const bool value) {
17015c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  uint8_t length = sizeof(uint8_t);
17115c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  uint8_t value_uint8 = value ? 1 : 0;
17215c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  buffer->Append(ByteString(reinterpret_cast<const char*>(&option_code),
17315c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                            sizeof(uint8_t)));
17415c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  buffer->Append(ByteString(reinterpret_cast<const char*>(&length),
17515c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                            sizeof(uint8_t)));
17615c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  buffer->Append(ByteString(reinterpret_cast<const char*>(&value_uint8),
17715c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                            sizeof(uint8_t)));
17815c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  return length + 2;
179d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang}
180d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang
18115c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wangint DHCPOptionsWriter::WriteStringOption(ByteString* buffer,
182d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang    uint8_t option_code,
183d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang    const std::string& value) {
184d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang  if (value.size() == 0) {
185d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang    LOG(ERROR) << "Faild to write option: " << static_cast<int>(option_code)
186d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang               << ", because value size cannot be 0";
187d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang    return -1;
188d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang  }
18915c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  uint8_t length = value.size();
19015c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  buffer->Append(ByteString(reinterpret_cast<const char*>(&option_code),
19115c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                            sizeof(uint8_t)));
19215c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  buffer->Append(ByteString(reinterpret_cast<const char*>(&length),
19315c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                            sizeof(uint8_t)));
19415c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  buffer->Append(ByteString(reinterpret_cast<const char*>(&value.front()),
19515c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                            length * sizeof(uint8_t)));
19615c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  return length + 2;
19715c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang}
19815c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang
19915c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wangint DHCPOptionsWriter::WriteByteArrayOption(ByteString* buffer,
20015c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                                            uint8_t option_code,
20115c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                                            const ByteString& value) {
20215c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  uint8_t length = value.GetLength();
20315c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  buffer->Append(ByteString(reinterpret_cast<const char*>(&option_code),
20415c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                            sizeof(uint8_t)));
20515c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  buffer->Append(ByteString(reinterpret_cast<const char*>(&length),
20615c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                            sizeof(uint8_t)));
20715c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang
20815c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  buffer->Append(value);
20915c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  return length + 2;
210d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang}
211d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang
21215c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wangint DHCPOptionsWriter::WriteEndTag(ByteString* buffer) {
21315c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  uint8_t tag = kDHCPOptionEnd;
21415c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  buffer->Append(ByteString(reinterpret_cast<const char*>(&tag),
21515c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang                            sizeof(uint8_t)));
21615c10d2a1c42c31c68c1d88f85627ff9bdefd29dNingyuan Wang  return 1;
217d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang}
218d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang
219d4b86841f58d9c4b299e651ce1772cd0b505c614Ningyuan Wang}  // namespace dhcp_client
220