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