blob: f99b527e10f8ffbc8fa7ddab2f1c8c864879457e [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;
236 std::copy_n(buff.data() + slp::request::OFFSET_PR_LEN,
Patrick Venture537ff142018-11-01 16:37:09 -0700237 slp::request::SIZE_PRLIST, (uint8_t*)&prListLen);
Ratan Gupta07c462a2016-12-14 00:40:30 +0530238
239 auto pos = slp::request::OFFSET_PR_LEN + slp::request::SIZE_PRLIST;
240
241 prListLen = endian::from_network(prListLen);
242
243 req.body.srvrqst.prList.insert(0, (const char*)buff.data() + pos,
244 prListLen);
245
246 pos += prListLen;
247
Ratan Gupta07c462a2016-12-14 00:40:30 +0530248 /* 2) Parse the <service-type> string. */
249 uint16_t srvTypeLen;
Patrick Venture537ff142018-11-01 16:37:09 -0700250 std::copy_n(buff.data() + pos, slp::request::SIZE_SERVICE_TYPE,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530251 (uint8_t*)&srvTypeLen);
252
253 srvTypeLen = endian::from_network(srvTypeLen);
254
255 pos += slp::request::SIZE_SERVICE_TYPE;
256
257 req.body.srvrqst.srvType.insert(0, (const char*)buff.data() + pos,
258 srvTypeLen);
259
260 pos += srvTypeLen;
261
262 /* 3) Parse the <scope-list> string. */
263 uint16_t scopeListLen;
Patrick Venture537ff142018-11-01 16:37:09 -0700264 std::copy_n(buff.data() + pos, slp::request::SIZE_SCOPE,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530265 (uint8_t*)&scopeListLen);
266
267 scopeListLen = endian::from_network(scopeListLen);
268
269 pos += slp::request::SIZE_SCOPE;
270
271 req.body.srvrqst.scopeList.insert(0, (const char*)buff.data() + pos,
272 scopeListLen);
273
274 pos += scopeListLen;
275
276 /* 4) Parse the <predicate> string. */
277 uint16_t predicateLen;
Patrick Venture537ff142018-11-01 16:37:09 -0700278 std::copy_n(buff.data() + pos, slp::request::SIZE_PREDICATE,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530279 (uint8_t*)&predicateLen);
280
281 predicateLen = endian::from_network(predicateLen);
282 pos += slp::request::SIZE_PREDICATE;
283
284 req.body.srvrqst.predicate.insert(0, (const char*)buff.data() + pos,
285 predicateLen);
286
287 pos += predicateLen;
288
289 /* 5) Parse the <SLP SPI> string. */
290 uint16_t spistrLen;
Patrick Venture537ff142018-11-01 16:37:09 -0700291 std::copy_n(buff.data() + pos, slp::request::SIZE_SLPI,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530292 (uint8_t*)&spistrLen);
293
294 spistrLen = endian::from_network(spistrLen);
295 pos += slp::request::SIZE_SLPI;
296
297 req.body.srvrqst.spistr.insert(0, (const char*)buff.data() + pos,
298 spistrLen);
299
300 return slp::SUCCESS;
301}
Patrick Venture537ff142018-11-01 16:37:09 -0700302} // namespace internal
Ratan Gupta07c462a2016-12-14 00:40:30 +0530303
304std::tuple<int, Message> parseBuffer(const buffer& buff)
305{
306 Message req;
307 int rc = slp::SUCCESS;
308 /* parse the header first */
309 std::tie(rc, req) = internal::parseHeader(buff);
310 if (!rc)
311 {
312 /* switch on the function id to parse the body */
313 switch (req.header.functionID)
314 {
315 case (uint8_t)slp::FunctionType::SRVTYPERQST:
316 rc = internal::parseSrvTypeRqst(buff, req);
317 break;
318 case (uint8_t)slp::FunctionType::SRVRQST:
319 rc = internal::parseSrvRqst(buff, req);
320 break;
321 default:
322 rc = (int)slp::Error::MSG_NOT_SUPPORTED;
323 }
324 }
325 return std::make_tuple(rc, std::move(req));
326}
Patrick Venture537ff142018-11-01 16:37:09 -0700327} // namespace parser
328} // namespace slp