blob: 293cba7e44df28252584a5c2df2a99b869659dd6 [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
71 req.header.langtag.insert(
72 0, (const char*)buff.data() + slp::header::OFFSET_LANG, langtagLen);
73
74 /* check for the validity of the function */
75 if (req.header.functionID <
76 static_cast<uint8_t>(slp::FunctionType::SRVRQST) ||
77 req.header.functionID >
78 static_cast<uint8_t>(slp::FunctionType::SAADV))
79 {
80 std::cerr << "Invalid function ID: " << req.header.functionID
81 << std::endl;
82 rc = static_cast<int>(slp::Error::PARSE_ERROR);
83 }
84 }
Ratan Gupta07c462a2016-12-14 00:40:30 +053085
86 return std::make_tuple(rc, std::move(req));
87}
88
Ratan Gupta07c462a2016-12-14 00:40:30 +053089int parseSrvTypeRqst(const buffer& buff, Message& req)
90{
Ratan Gupta07c462a2016-12-14 00:40:30 +053091 /* 0 1 2 3
92 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
93 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
94 | length of PRList | <PRList> String \
95 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
96 | length of Naming Authority | <Naming Authority String> \
97 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
98 | length of <scope-list> | <scope-list> String \
99 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
100
101 /* Enforce SLPv2 service type request size limits. */
102 if (buff.size() < slp::request::MIN_SRVTYPE_LEN)
103 {
104 return (int)slp::Error::PARSE_ERROR;
105 }
106
107 /* Parse the PRList. */
108 uint16_t prListLen;
109 std::copy_n(buff.data() + slp::request::OFFSET_PR_LEN,
Patrick Venture537ff142018-11-01 16:37:09 -0700110 slp::request::SIZE_PRLIST, (uint8_t*)&prListLen);
Ratan Gupta07c462a2016-12-14 00:40:30 +0530111
112 prListLen = endian::from_network(prListLen);
113
Patrick Venture537ff142018-11-01 16:37:09 -0700114 req.body.srvtyperqst.prList.insert(
115 0, (const char*)buff.data() + slp::request::OFFSET_PR, prListLen);
Ratan Gupta07c462a2016-12-14 00:40:30 +0530116
117 uint8_t pos = slp::request::OFFSET_PR + prListLen;
118
119 /* Parse the Naming Authority. */
120 uint16_t namingAuthLen;
Patrick Venture537ff142018-11-01 16:37:09 -0700121 std::copy_n(buff.data() + pos, slp::request::SIZE_NAMING,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530122 (uint8_t*)&namingAuthLen);
123
124 pos += slp::request::SIZE_NAMING;
125
126 namingAuthLen = endian::from_network(namingAuthLen);
127
128 if (namingAuthLen == 0 || namingAuthLen == 0xffff)
129 {
130 req.body.srvtyperqst.namingAuth = "";
131 }
132 else
133 {
Patrick Venture537ff142018-11-01 16:37:09 -0700134 req.body.srvtyperqst.namingAuth.insert(
135 0, (const char*)buff.data() + pos, namingAuthLen);
Ratan Gupta07c462a2016-12-14 00:40:30 +0530136 }
137
138 pos += namingAuthLen;
139
140 /* Parse the <scope-list>. */
141 uint16_t scopeListLen;
Patrick Venture537ff142018-11-01 16:37:09 -0700142 std::copy_n(buff.data() + pos, slp::request::SIZE_SCOPE,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530143 (uint8_t*)&scopeListLen);
144
145 pos += slp::request::SIZE_SCOPE;
146
147 scopeListLen = endian::from_network(scopeListLen);
148
149 req.body.srvtyperqst.scopeList.insert(0, (const char*)buff.data() + pos,
150 scopeListLen);
151
152 return slp::SUCCESS;
153}
154
155int parseSrvRqst(const buffer& buff, Message& req)
156{
157 /* 0 1 2 3
158 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
159 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
160 | length of <PRList> | <PRList> String \
161 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
162 | length of <service-type> | <service-type> String \
163 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
164 | length of <scope-list> | <scope-list> String \
165 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
166 | length of predicate string | Service Request <predicate> \
167 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
168 | length of <SLP SPI> string | <SLP SPI> String \
169 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
170
171 /* Enforce v2 service request size limits. */
172 if (buff.size() < slp::request::MIN_SRV_LEN)
173 {
174 return (int)slp::Error::PARSE_ERROR;
175 }
176
177 /* 1) Parse the PRList. */
178 uint16_t prListLen;
179 std::copy_n(buff.data() + slp::request::OFFSET_PR_LEN,
Patrick Venture537ff142018-11-01 16:37:09 -0700180 slp::request::SIZE_PRLIST, (uint8_t*)&prListLen);
Ratan Gupta07c462a2016-12-14 00:40:30 +0530181
182 auto pos = slp::request::OFFSET_PR_LEN + slp::request::SIZE_PRLIST;
183
184 prListLen = endian::from_network(prListLen);
185
186 req.body.srvrqst.prList.insert(0, (const char*)buff.data() + pos,
187 prListLen);
188
189 pos += prListLen;
190
Ratan Gupta07c462a2016-12-14 00:40:30 +0530191 /* 2) Parse the <service-type> string. */
192 uint16_t srvTypeLen;
Patrick Venture537ff142018-11-01 16:37:09 -0700193 std::copy_n(buff.data() + pos, slp::request::SIZE_SERVICE_TYPE,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530194 (uint8_t*)&srvTypeLen);
195
196 srvTypeLen = endian::from_network(srvTypeLen);
197
198 pos += slp::request::SIZE_SERVICE_TYPE;
199
200 req.body.srvrqst.srvType.insert(0, (const char*)buff.data() + pos,
201 srvTypeLen);
202
203 pos += srvTypeLen;
204
205 /* 3) Parse the <scope-list> string. */
206 uint16_t scopeListLen;
Patrick Venture537ff142018-11-01 16:37:09 -0700207 std::copy_n(buff.data() + pos, slp::request::SIZE_SCOPE,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530208 (uint8_t*)&scopeListLen);
209
210 scopeListLen = endian::from_network(scopeListLen);
211
212 pos += slp::request::SIZE_SCOPE;
213
214 req.body.srvrqst.scopeList.insert(0, (const char*)buff.data() + pos,
215 scopeListLen);
216
217 pos += scopeListLen;
218
219 /* 4) Parse the <predicate> string. */
220 uint16_t predicateLen;
Patrick Venture537ff142018-11-01 16:37:09 -0700221 std::copy_n(buff.data() + pos, slp::request::SIZE_PREDICATE,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530222 (uint8_t*)&predicateLen);
223
224 predicateLen = endian::from_network(predicateLen);
225 pos += slp::request::SIZE_PREDICATE;
226
227 req.body.srvrqst.predicate.insert(0, (const char*)buff.data() + pos,
228 predicateLen);
229
230 pos += predicateLen;
231
232 /* 5) Parse the <SLP SPI> string. */
233 uint16_t spistrLen;
Patrick Venture537ff142018-11-01 16:37:09 -0700234 std::copy_n(buff.data() + pos, slp::request::SIZE_SLPI,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530235 (uint8_t*)&spistrLen);
236
237 spistrLen = endian::from_network(spistrLen);
238 pos += slp::request::SIZE_SLPI;
239
240 req.body.srvrqst.spistr.insert(0, (const char*)buff.data() + pos,
241 spistrLen);
242
243 return slp::SUCCESS;
244}
Patrick Venture537ff142018-11-01 16:37:09 -0700245} // namespace internal
Ratan Gupta07c462a2016-12-14 00:40:30 +0530246
247std::tuple<int, Message> parseBuffer(const buffer& buff)
248{
249 Message req;
250 int rc = slp::SUCCESS;
251 /* parse the header first */
252 std::tie(rc, req) = internal::parseHeader(buff);
253 if (!rc)
254 {
255 /* switch on the function id to parse the body */
256 switch (req.header.functionID)
257 {
258 case (uint8_t)slp::FunctionType::SRVTYPERQST:
259 rc = internal::parseSrvTypeRqst(buff, req);
260 break;
261 case (uint8_t)slp::FunctionType::SRVRQST:
262 rc = internal::parseSrvRqst(buff, req);
263 break;
264 default:
265 rc = (int)slp::Error::MSG_NOT_SUPPORTED;
266 }
267 }
268 return std::make_tuple(rc, std::move(req));
269}
Patrick Venture537ff142018-11-01 16:37:09 -0700270} // namespace parser
271} // namespace slp