blob: b79cff21a5d24303ca1007e56577ab45b7034f51 [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 {
80 req.header.langtag.insert(
81 0, (const char*)buff.data() + slp::header::OFFSET_LANG,
82 langtagLen);
83
84 /* check for the validity of the function */
85 if (req.header.functionID <
86 static_cast<uint8_t>(slp::FunctionType::SRVRQST) ||
87 req.header.functionID >
88 static_cast<uint8_t>(slp::FunctionType::SAADV))
89 {
90 std::cerr << "Invalid function ID: " << req.header.functionID
91 << std::endl;
92 rc = static_cast<int>(slp::Error::PARSE_ERROR);
93 }
94 }
Andrew Geissler0e948dc2024-05-23 09:51:48 -050095 }
Ratan Gupta07c462a2016-12-14 00:40:30 +053096
97 return std::make_tuple(rc, std::move(req));
98}
99
Ratan Gupta07c462a2016-12-14 00:40:30 +0530100int parseSrvTypeRqst(const buffer& buff, Message& req)
101{
Ratan Gupta07c462a2016-12-14 00:40:30 +0530102 /* 0 1 2 3
103 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
104 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
105 | length of PRList | <PRList> String \
106 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
107 | length of Naming Authority | <Naming Authority String> \
108 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
109 | length of <scope-list> | <scope-list> String \
110 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
111
112 /* Enforce SLPv2 service type request size limits. */
113 if (buff.size() < slp::request::MIN_SRVTYPE_LEN)
114 {
115 return (int)slp::Error::PARSE_ERROR;
116 }
117
118 /* Parse the PRList. */
119 uint16_t prListLen;
120 std::copy_n(buff.data() + slp::request::OFFSET_PR_LEN,
Patrick Venture537ff142018-11-01 16:37:09 -0700121 slp::request::SIZE_PRLIST, (uint8_t*)&prListLen);
Ratan Gupta07c462a2016-12-14 00:40:30 +0530122
123 prListLen = endian::from_network(prListLen);
124
Patrick Venture537ff142018-11-01 16:37:09 -0700125 req.body.srvtyperqst.prList.insert(
126 0, (const char*)buff.data() + slp::request::OFFSET_PR, prListLen);
Ratan Gupta07c462a2016-12-14 00:40:30 +0530127
128 uint8_t pos = slp::request::OFFSET_PR + prListLen;
129
130 /* Parse the Naming Authority. */
131 uint16_t namingAuthLen;
Patrick Venture537ff142018-11-01 16:37:09 -0700132 std::copy_n(buff.data() + pos, slp::request::SIZE_NAMING,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530133 (uint8_t*)&namingAuthLen);
134
135 pos += slp::request::SIZE_NAMING;
136
137 namingAuthLen = endian::from_network(namingAuthLen);
138
139 if (namingAuthLen == 0 || namingAuthLen == 0xffff)
140 {
141 req.body.srvtyperqst.namingAuth = "";
142 }
143 else
144 {
Patrick Venture537ff142018-11-01 16:37:09 -0700145 req.body.srvtyperqst.namingAuth.insert(
146 0, (const char*)buff.data() + pos, namingAuthLen);
Ratan Gupta07c462a2016-12-14 00:40:30 +0530147 }
148
149 pos += namingAuthLen;
150
151 /* Parse the <scope-list>. */
152 uint16_t scopeListLen;
Patrick Venture537ff142018-11-01 16:37:09 -0700153 std::copy_n(buff.data() + pos, slp::request::SIZE_SCOPE,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530154 (uint8_t*)&scopeListLen);
155
156 pos += slp::request::SIZE_SCOPE;
157
158 scopeListLen = endian::from_network(scopeListLen);
159
160 req.body.srvtyperqst.scopeList.insert(0, (const char*)buff.data() + pos,
161 scopeListLen);
162
163 return slp::SUCCESS;
164}
165
166int parseSrvRqst(const buffer& buff, Message& req)
167{
168 /* 0 1 2 3
169 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
170 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
171 | length of <PRList> | <PRList> String \
172 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
173 | length of <service-type> | <service-type> String \
174 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
175 | length of <scope-list> | <scope-list> String \
176 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
177 | length of predicate string | Service Request <predicate> \
178 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
179 | length of <SLP SPI> string | <SLP SPI> String \
180 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
181
182 /* Enforce v2 service request size limits. */
183 if (buff.size() < slp::request::MIN_SRV_LEN)
184 {
185 return (int)slp::Error::PARSE_ERROR;
186 }
187
188 /* 1) Parse the PRList. */
189 uint16_t prListLen;
190 std::copy_n(buff.data() + slp::request::OFFSET_PR_LEN,
Patrick Venture537ff142018-11-01 16:37:09 -0700191 slp::request::SIZE_PRLIST, (uint8_t*)&prListLen);
Ratan Gupta07c462a2016-12-14 00:40:30 +0530192
193 auto pos = slp::request::OFFSET_PR_LEN + slp::request::SIZE_PRLIST;
194
195 prListLen = endian::from_network(prListLen);
196
197 req.body.srvrqst.prList.insert(0, (const char*)buff.data() + pos,
198 prListLen);
199
200 pos += prListLen;
201
Ratan Gupta07c462a2016-12-14 00:40:30 +0530202 /* 2) Parse the <service-type> string. */
203 uint16_t srvTypeLen;
Patrick Venture537ff142018-11-01 16:37:09 -0700204 std::copy_n(buff.data() + pos, slp::request::SIZE_SERVICE_TYPE,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530205 (uint8_t*)&srvTypeLen);
206
207 srvTypeLen = endian::from_network(srvTypeLen);
208
209 pos += slp::request::SIZE_SERVICE_TYPE;
210
211 req.body.srvrqst.srvType.insert(0, (const char*)buff.data() + pos,
212 srvTypeLen);
213
214 pos += srvTypeLen;
215
216 /* 3) Parse the <scope-list> string. */
217 uint16_t scopeListLen;
Patrick Venture537ff142018-11-01 16:37:09 -0700218 std::copy_n(buff.data() + pos, slp::request::SIZE_SCOPE,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530219 (uint8_t*)&scopeListLen);
220
221 scopeListLen = endian::from_network(scopeListLen);
222
223 pos += slp::request::SIZE_SCOPE;
224
225 req.body.srvrqst.scopeList.insert(0, (const char*)buff.data() + pos,
226 scopeListLen);
227
228 pos += scopeListLen;
229
230 /* 4) Parse the <predicate> string. */
231 uint16_t predicateLen;
Patrick Venture537ff142018-11-01 16:37:09 -0700232 std::copy_n(buff.data() + pos, slp::request::SIZE_PREDICATE,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530233 (uint8_t*)&predicateLen);
234
235 predicateLen = endian::from_network(predicateLen);
236 pos += slp::request::SIZE_PREDICATE;
237
238 req.body.srvrqst.predicate.insert(0, (const char*)buff.data() + pos,
239 predicateLen);
240
241 pos += predicateLen;
242
243 /* 5) Parse the <SLP SPI> string. */
244 uint16_t spistrLen;
Patrick Venture537ff142018-11-01 16:37:09 -0700245 std::copy_n(buff.data() + pos, slp::request::SIZE_SLPI,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530246 (uint8_t*)&spistrLen);
247
248 spistrLen = endian::from_network(spistrLen);
249 pos += slp::request::SIZE_SLPI;
250
251 req.body.srvrqst.spistr.insert(0, (const char*)buff.data() + pos,
252 spistrLen);
253
254 return slp::SUCCESS;
255}
Patrick Venture537ff142018-11-01 16:37:09 -0700256} // namespace internal
Ratan Gupta07c462a2016-12-14 00:40:30 +0530257
258std::tuple<int, Message> parseBuffer(const buffer& buff)
259{
260 Message req;
261 int rc = slp::SUCCESS;
262 /* parse the header first */
263 std::tie(rc, req) = internal::parseHeader(buff);
264 if (!rc)
265 {
266 /* switch on the function id to parse the body */
267 switch (req.header.functionID)
268 {
269 case (uint8_t)slp::FunctionType::SRVTYPERQST:
270 rc = internal::parseSrvTypeRqst(buff, req);
271 break;
272 case (uint8_t)slp::FunctionType::SRVRQST:
273 rc = internal::parseSrvRqst(buff, req);
274 break;
275 default:
276 rc = (int)slp::Error::MSG_NOT_SUPPORTED;
277 }
278 }
279 return std::make_tuple(rc, std::move(req));
280}
Patrick Venture537ff142018-11-01 16:37:09 -0700281} // namespace parser
282} // namespace slp