blob: 89017267133677d6a7299a4c6c681ed8e89873fc [file] [log] [blame]
Patrick Venture537ff142018-11-01 16:37:09 -07001#include "endian.hpp"
Ratan Gupta07c462a2016-12-14 00:40:30 +05302#include "slp.hpp"
Patrick Venture537ff142018-11-01 16:37:09 -07003#include "slp_meta.hpp"
Ratan Gupta07c462a2016-12-14 00:40:30 +05304
5#include <string.h>
6
Ratan Gupta07c462a2016-12-14 00:40:30 +05307#include <algorithm>
Patrick Venture537ff142018-11-01 16:37:09 -07008#include <string>
Ratan Gupta07c462a2016-12-14 00:40:30 +05309
10namespace slp
11{
12
13namespace parser
14{
15
16namespace internal
17{
18
19std::tuple<int, Message> parseHeader(const buffer& buff)
20{
21 /* 0 1 2 3
22 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
23 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
24 | Version | Function-ID | Length |
25 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
26 | Length, contd.|O|F|R| reserved |Next Ext Offset|
27 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
28 | Next Extension Offset, contd.| XID |
29 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
30 | Language Tag Length | Language Tag \
31 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
32
Patrick Williamsf191bd82023-04-04 20:50:38 -050033 Message req{};
Ratan Gupta07c462a2016-12-14 00:40:30 +053034 int rc = slp::SUCCESS;
35
Andrew Geissler0e948dc2024-05-23 09:51:48 -050036 if (buff.size() < slp::header::MIN_LEN)
Ratan Gupta07c462a2016-12-14 00:40:30 +053037 {
Andrew Geissler0e948dc2024-05-23 09:51:48 -050038 std::cerr << "Invalid msg size: " << buff.size() << std::endl;
Ratan Gupta07c462a2016-12-14 00:40:30 +053039 rc = static_cast<int>(slp::Error::PARSE_ERROR);
40 }
Andrew Geissler0e948dc2024-05-23 09:51:48 -050041 else
42 {
43 std::copy_n(buff.data(), slp::header::SIZE_VERSION,
44 &req.header.version);
45
46 std::copy_n(buff.data() + slp::header::OFFSET_FUNCTION,
47 slp::header::SIZE_VERSION, &req.header.functionID);
48
49 std::copy_n(buff.data() + slp::header::OFFSET_LENGTH,
50 slp::header::SIZE_LENGTH, req.header.length.data());
51
52 std::copy_n(buff.data() + slp::header::OFFSET_FLAGS,
53 slp::header::SIZE_FLAGS, (uint8_t*)&req.header.flags);
54
55 req.header.flags = endian::from_network(req.header.flags);
56 std::copy_n(buff.data() + slp::header::OFFSET_EXT,
57 slp::header::SIZE_EXT, req.header.extOffset.data());
58
59 std::copy_n(buff.data() + slp::header::OFFSET_XID,
60 slp::header::SIZE_XID, (uint8_t*)&req.header.xid);
61
62 req.header.xid = endian::from_network(req.header.xid);
63
64 uint16_t langtagLen;
65
66 std::copy_n(buff.data() + slp::header::OFFSET_LANG_LEN,
67 slp::header::SIZE_LANG, (uint8_t*)&langtagLen);
68
69 langtagLen = endian::from_network(langtagLen);
70
Andrew Geisslerc6683132024-05-23 10:21:26 -050071 // Enforce language tag size limits
72 if ((slp::header::OFFSET_LANG + langtagLen) > buff.size())
Andrew Geissler0e948dc2024-05-23 09:51:48 -050073 {
Andrew Geisslerc6683132024-05-23 10:21:26 -050074 std::cerr << "Invalid Language Tag Length: " << langtagLen
Andrew Geissler0e948dc2024-05-23 09:51:48 -050075 << std::endl;
76 rc = static_cast<int>(slp::Error::PARSE_ERROR);
77 }
Andrew Geisslerc6683132024-05-23 10:21:26 -050078 else
79 {
Andrew Geisslerf60e7102024-05-24 12:39:36 -050080 req.header.langtagLen = langtagLen;
Andrew Geisslerc6683132024-05-23 10:21:26 -050081 req.header.langtag.insert(
82 0, (const char*)buff.data() + slp::header::OFFSET_LANG,
83 langtagLen);
84
85 /* check for the validity of the function */
86 if (req.header.functionID <
87 static_cast<uint8_t>(slp::FunctionType::SRVRQST) ||
88 req.header.functionID >
89 static_cast<uint8_t>(slp::FunctionType::SAADV))
90 {
91 std::cerr << "Invalid function ID: " << req.header.functionID
92 << std::endl;
93 rc = static_cast<int>(slp::Error::PARSE_ERROR);
94 }
95 }
Andrew Geissler0e948dc2024-05-23 09:51:48 -050096 }
Ratan Gupta07c462a2016-12-14 00:40:30 +053097
98 return std::make_tuple(rc, std::move(req));
99}
100
Ratan Gupta07c462a2016-12-14 00:40:30 +0530101int parseSrvTypeRqst(const buffer& buff, Message& req)
102{
Ratan Gupta07c462a2016-12-14 00:40:30 +0530103 /* 0 1 2 3
104 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
105 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
106 | length of PRList | <PRList> String \
107 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
108 | length of Naming Authority | <Naming Authority String> \
109 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
110 | length of <scope-list> | <scope-list> String \
111 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
112
113 /* Enforce SLPv2 service type request size limits. */
114 if (buff.size() < slp::request::MIN_SRVTYPE_LEN)
115 {
116 return (int)slp::Error::PARSE_ERROR;
117 }
118
119 /* Parse the PRList. */
120 uint16_t prListLen;
Andrew Geisslerf60e7102024-05-24 12:39:36 -0500121 uint32_t pos = slp::header::MIN_LEN + req.header.langtagLen;
122 if ((pos + slp::request::SIZE_PRLIST) > buff.size())
123 {
124 std::cerr << "PRList length field is greater than input buffer: "
125 << (pos + slp::request::SIZE_PRLIST) << " / " << buff.size()
126 << std::endl;
127 return (int)slp::Error::PARSE_ERROR;
128 }
129 std::copy_n(buff.data() + pos, slp::request::SIZE_PRLIST,
130 (uint8_t*)&prListLen);
Ratan Gupta07c462a2016-12-14 00:40:30 +0530131
Andrew Geisslerf60e7102024-05-24 12:39:36 -0500132 pos += slp::request::SIZE_PRLIST;
Ratan Gupta07c462a2016-12-14 00:40:30 +0530133 prListLen = endian::from_network(prListLen);
134
Andrew Geisslerf60e7102024-05-24 12:39:36 -0500135 if ((pos + prListLen) > buff.size())
136 {
137 std::cerr << "Length of PRList is greater than input buffer: "
138 << (slp::request::OFFSET_PR + prListLen) << " / "
139 << buff.size() << std::endl;
140 return (int)slp::Error::PARSE_ERROR;
141 }
Ratan Gupta07c462a2016-12-14 00:40:30 +0530142
Andrew Geisslerf60e7102024-05-24 12:39:36 -0500143 req.body.srvtyperqst.prList.insert(0, (const char*)buff.data() + pos,
144 prListLen);
145
146 pos += prListLen;
Ratan Gupta07c462a2016-12-14 00:40:30 +0530147
148 /* Parse the Naming Authority. */
149 uint16_t namingAuthLen;
Andrew Geisslerf60e7102024-05-24 12:39:36 -0500150 if ((pos + slp::request::SIZE_NAMING) > buff.size())
151 {
152 std::cerr << "Naming auth length field is greater than input buffer: "
153 << (pos + slp::request::SIZE_NAMING) << " / " << buff.size()
154 << std::endl;
155 return (int)slp::Error::PARSE_ERROR;
156 }
Patrick Venture537ff142018-11-01 16:37:09 -0700157 std::copy_n(buff.data() + pos, slp::request::SIZE_NAMING,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530158 (uint8_t*)&namingAuthLen);
159
160 pos += slp::request::SIZE_NAMING;
161
162 namingAuthLen = endian::from_network(namingAuthLen);
Ratan Gupta07c462a2016-12-14 00:40:30 +0530163 if (namingAuthLen == 0 || namingAuthLen == 0xffff)
164 {
165 req.body.srvtyperqst.namingAuth = "";
Andrew Geisslerf60e7102024-05-24 12:39:36 -0500166 // If it's the special 0xffff, treat like 0 size
167 namingAuthLen = 0;
Ratan Gupta07c462a2016-12-14 00:40:30 +0530168 }
169 else
170 {
Andrew Geisslerf60e7102024-05-24 12:39:36 -0500171 if ((pos + namingAuthLen) > buff.size())
172 {
173 std::cerr << "Length of Naming Size is greater than input buffer: "
174 << (pos + namingAuthLen) << " / " << buff.size()
175 << std::endl;
176 return (int)slp::Error::PARSE_ERROR;
177 }
Patrick Venture537ff142018-11-01 16:37:09 -0700178 req.body.srvtyperqst.namingAuth.insert(
179 0, (const char*)buff.data() + pos, namingAuthLen);
Ratan Gupta07c462a2016-12-14 00:40:30 +0530180 }
181
182 pos += namingAuthLen;
183
184 /* Parse the <scope-list>. */
185 uint16_t scopeListLen;
Andrew Geisslerf60e7102024-05-24 12:39:36 -0500186 if ((pos + slp::request::SIZE_SCOPE) > buff.size())
187 {
188 std::cerr << "Length of Scope size is greater than input buffer: "
189 << (pos + slp::request::SIZE_SCOPE) << " / " << buff.size()
190 << std::endl;
191 return (int)slp::Error::PARSE_ERROR;
192 }
Patrick Venture537ff142018-11-01 16:37:09 -0700193 std::copy_n(buff.data() + pos, slp::request::SIZE_SCOPE,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530194 (uint8_t*)&scopeListLen);
195
196 pos += slp::request::SIZE_SCOPE;
197
198 scopeListLen = endian::from_network(scopeListLen);
Andrew Geisslerf60e7102024-05-24 12:39:36 -0500199 if ((pos + scopeListLen) > buff.size())
200 {
201 std::cerr << "Length of Scope List is greater than input buffer: "
202 << (pos + scopeListLen) << " / " << buff.size() << std::endl;
203 return (int)slp::Error::PARSE_ERROR;
204 }
Ratan Gupta07c462a2016-12-14 00:40:30 +0530205
206 req.body.srvtyperqst.scopeList.insert(0, (const char*)buff.data() + pos,
207 scopeListLen);
208
209 return slp::SUCCESS;
210}
211
212int parseSrvRqst(const buffer& buff, Message& req)
213{
214 /* 0 1 2 3
215 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
216 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
217 | length of <PRList> | <PRList> String \
218 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
219 | length of <service-type> | <service-type> String \
220 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
221 | length of <scope-list> | <scope-list> String \
222 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
223 | length of predicate string | Service Request <predicate> \
224 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
225 | length of <SLP SPI> string | <SLP SPI> String \
226 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
227
228 /* Enforce v2 service request size limits. */
229 if (buff.size() < slp::request::MIN_SRV_LEN)
230 {
231 return (int)slp::Error::PARSE_ERROR;
232 }
233
234 /* 1) Parse the PRList. */
235 uint16_t prListLen;
Andrew Geissler20bab742024-05-24 14:31:16 -0500236 uint32_t pos = slp::header::MIN_LEN + req.header.langtagLen;
237 if ((pos + slp::request::SIZE_PRLIST) > buff.size())
238 {
239 std::cerr << "PRList length field is greater then input buffer: "
240 << (pos + slp::request::SIZE_PRLIST) << " / " << buff.size()
241 << std::endl;
242 return (int)slp::Error::PARSE_ERROR;
243 }
244 std::copy_n(buff.data() + pos, slp::request::SIZE_PRLIST,
245 (uint8_t*)&prListLen);
Ratan Gupta07c462a2016-12-14 00:40:30 +0530246
Andrew Geissler20bab742024-05-24 14:31:16 -0500247 pos += slp::request::SIZE_PRLIST;
Ratan Gupta07c462a2016-12-14 00:40:30 +0530248
249 prListLen = endian::from_network(prListLen);
Andrew Geissler20bab742024-05-24 14:31:16 -0500250 if ((pos + prListLen) > buff.size())
251 {
252 std::cerr << "Length of PRList is greater then input buffer: "
253 << (slp::request::OFFSET_PR + prListLen) << " / "
254 << buff.size() << std::endl;
255 return (int)slp::Error::PARSE_ERROR;
256 }
Ratan Gupta07c462a2016-12-14 00:40:30 +0530257 req.body.srvrqst.prList.insert(0, (const char*)buff.data() + pos,
258 prListLen);
259
260 pos += prListLen;
261
Ratan Gupta07c462a2016-12-14 00:40:30 +0530262 /* 2) Parse the <service-type> string. */
263 uint16_t srvTypeLen;
Andrew Geissler20bab742024-05-24 14:31:16 -0500264 if ((pos + slp::request::SIZE_SERVICE_TYPE) > buff.size())
265 {
266 std::cerr << "SrvType length field is greater then input buffer: "
267 << (pos + slp::request::SIZE_SERVICE_TYPE) << " / "
268 << buff.size() << std::endl;
269 return (int)slp::Error::PARSE_ERROR;
270 }
Patrick Venture537ff142018-11-01 16:37:09 -0700271 std::copy_n(buff.data() + pos, slp::request::SIZE_SERVICE_TYPE,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530272 (uint8_t*)&srvTypeLen);
273
274 srvTypeLen = endian::from_network(srvTypeLen);
275
276 pos += slp::request::SIZE_SERVICE_TYPE;
277
Andrew Geissler20bab742024-05-24 14:31:16 -0500278 if ((pos + srvTypeLen) > buff.size())
279 {
280 std::cerr << "Length of SrvType is greater then input buffer: "
281 << (pos + srvTypeLen) << " / " << buff.size() << std::endl;
282 return (int)slp::Error::PARSE_ERROR;
283 }
Ratan Gupta07c462a2016-12-14 00:40:30 +0530284 req.body.srvrqst.srvType.insert(0, (const char*)buff.data() + pos,
285 srvTypeLen);
286
287 pos += srvTypeLen;
288
289 /* 3) Parse the <scope-list> string. */
290 uint16_t scopeListLen;
Andrew Geissler20bab742024-05-24 14:31:16 -0500291 if ((pos + slp::request::SIZE_SCOPE) > buff.size())
292 {
293 std::cerr << "Scope List length field is greater then input buffer: "
294 << (pos + slp::request::SIZE_SCOPE) << " / " << buff.size()
295 << std::endl;
296 return (int)slp::Error::PARSE_ERROR;
297 }
Patrick Venture537ff142018-11-01 16:37:09 -0700298 std::copy_n(buff.data() + pos, slp::request::SIZE_SCOPE,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530299 (uint8_t*)&scopeListLen);
300
301 scopeListLen = endian::from_network(scopeListLen);
302
303 pos += slp::request::SIZE_SCOPE;
304
Andrew Geissler20bab742024-05-24 14:31:16 -0500305 if ((pos + scopeListLen) > buff.size())
306 {
307 std::cerr << "Length of Scope List is greater then input buffer: "
308 << (pos + scopeListLen) << " / " << buff.size() << std::endl;
309 return (int)slp::Error::PARSE_ERROR;
310 }
Ratan Gupta07c462a2016-12-14 00:40:30 +0530311 req.body.srvrqst.scopeList.insert(0, (const char*)buff.data() + pos,
312 scopeListLen);
313
314 pos += scopeListLen;
315
316 /* 4) Parse the <predicate> string. */
317 uint16_t predicateLen;
Andrew Geissler20bab742024-05-24 14:31:16 -0500318 if ((pos + slp::request::SIZE_PREDICATE) > buff.size())
319 {
320 std::cerr << "Predicate length field is greater then input buffer: "
321 << (pos + slp::request::SIZE_PREDICATE) << " / "
322 << buff.size() << std::endl;
323 return (int)slp::Error::PARSE_ERROR;
324 }
Patrick Venture537ff142018-11-01 16:37:09 -0700325 std::copy_n(buff.data() + pos, slp::request::SIZE_PREDICATE,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530326 (uint8_t*)&predicateLen);
327
328 predicateLen = endian::from_network(predicateLen);
329 pos += slp::request::SIZE_PREDICATE;
330
Andrew Geissler20bab742024-05-24 14:31:16 -0500331 if ((pos + predicateLen) > buff.size())
332 {
333 std::cerr << "Length of Predicate is greater then input buffer: "
334 << (pos + predicateLen) << " / " << buff.size() << std::endl;
335 return (int)slp::Error::PARSE_ERROR;
336 }
Ratan Gupta07c462a2016-12-14 00:40:30 +0530337 req.body.srvrqst.predicate.insert(0, (const char*)buff.data() + pos,
338 predicateLen);
339
340 pos += predicateLen;
341
342 /* 5) Parse the <SLP SPI> string. */
343 uint16_t spistrLen;
Andrew Geissler20bab742024-05-24 14:31:16 -0500344 if ((pos + slp::request::SIZE_SLPI) > buff.size())
345 {
346 std::cerr << "SLP SPI length field is greater then input buffer: "
347 << (pos + slp::request::SIZE_SLPI) << " / " << buff.size()
348 << std::endl;
349 return (int)slp::Error::PARSE_ERROR;
350 }
Patrick Venture537ff142018-11-01 16:37:09 -0700351 std::copy_n(buff.data() + pos, slp::request::SIZE_SLPI,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530352 (uint8_t*)&spistrLen);
353
354 spistrLen = endian::from_network(spistrLen);
355 pos += slp::request::SIZE_SLPI;
356
Andrew Geissler20bab742024-05-24 14:31:16 -0500357 if ((pos + spistrLen) > buff.size())
358 {
359 std::cerr << "Length of SLP SPI is greater then input buffer: "
360 << (pos + spistrLen) << " / " << buff.size() << std::endl;
361 return (int)slp::Error::PARSE_ERROR;
362 }
Ratan Gupta07c462a2016-12-14 00:40:30 +0530363 req.body.srvrqst.spistr.insert(0, (const char*)buff.data() + pos,
364 spistrLen);
365
366 return slp::SUCCESS;
367}
Patrick Venture537ff142018-11-01 16:37:09 -0700368} // namespace internal
Ratan Gupta07c462a2016-12-14 00:40:30 +0530369
370std::tuple<int, Message> parseBuffer(const buffer& buff)
371{
372 Message req;
373 int rc = slp::SUCCESS;
374 /* parse the header first */
375 std::tie(rc, req) = internal::parseHeader(buff);
376 if (!rc)
377 {
378 /* switch on the function id to parse the body */
379 switch (req.header.functionID)
380 {
381 case (uint8_t)slp::FunctionType::SRVTYPERQST:
382 rc = internal::parseSrvTypeRqst(buff, req);
383 break;
384 case (uint8_t)slp::FunctionType::SRVRQST:
385 rc = internal::parseSrvRqst(buff, req);
386 break;
387 default:
388 rc = (int)slp::Error::MSG_NOT_SUPPORTED;
389 }
390 }
391 return std::make_tuple(rc, std::move(req));
392}
Patrick Venture537ff142018-11-01 16:37:09 -0700393} // namespace parser
394} // namespace slp