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
GetOption(const uint8_t * buffer,uint8_t length,void * value)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
GetOption(const uint8_t * buffer,uint8_t length,void * value)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
GetOption(const uint8_t * buffer,uint8_t length,void * value)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
GetOption(const uint8_t * buffer,uint8_t length,void * value)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
GetOption(const uint8_t * buffer,uint8_t length,void * value)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
GetOption(const uint8_t * buffer,uint8_t length,void * value)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
GetOption(const uint8_t * buffer,uint8_t length,void * value)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
GetOption(const uint8_t * buffer,uint8_t length,void * value)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
GetOption(const uint8_t * buffer,uint8_t length,void * value)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
GetOption(const uint8_t * buffer,uint8_t length,void * value)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