blob: 4c008ad33632989d1747845f466d7518bde26604 [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
Patrick Venture537ff142018-11-01 16:37:09 -070036 std::copy_n(buff.data(), slp::header::SIZE_VERSION, &req.header.version);
Ratan Gupta07c462a2016-12-14 00:40:30 +053037
38 std::copy_n(buff.data() + slp::header::OFFSET_FUNCTION,
Patrick Venture537ff142018-11-01 16:37:09 -070039 slp::header::SIZE_VERSION, &req.header.functionID);
Ratan Gupta07c462a2016-12-14 00:40:30 +053040
41 std::copy_n(buff.data() + slp::header::OFFSET_LENGTH,
Patrick Venture537ff142018-11-01 16:37:09 -070042 slp::header::SIZE_LENGTH, req.header.length.data());
Ratan Gupta07c462a2016-12-14 00:40:30 +053043
44 std::copy_n(buff.data() + slp::header::OFFSET_FLAGS,
Patrick Venture537ff142018-11-01 16:37:09 -070045 slp::header::SIZE_FLAGS, (uint8_t*)&req.header.flags);
Ratan Gupta07c462a2016-12-14 00:40:30 +053046
47 req.header.flags = endian::from_network(req.header.flags);
Patrick Venture537ff142018-11-01 16:37:09 -070048 std::copy_n(buff.data() + slp::header::OFFSET_EXT, slp::header::SIZE_EXT,
Ratan Gupta07c462a2016-12-14 00:40:30 +053049 req.header.extOffset.data());
50
Patrick Venture537ff142018-11-01 16:37:09 -070051 std::copy_n(buff.data() + slp::header::OFFSET_XID, slp::header::SIZE_XID,
Ratan Gupta07c462a2016-12-14 00:40:30 +053052 (uint8_t*)&req.header.xid);
53
54 req.header.xid = endian::from_network(req.header.xid);
55
56 uint16_t langtagLen;
57
58 std::copy_n(buff.data() + slp::header::OFFSET_LANG_LEN,
Patrick Venture537ff142018-11-01 16:37:09 -070059 slp::header::SIZE_LANG, (uint8_t*)&langtagLen);
Ratan Gupta07c462a2016-12-14 00:40:30 +053060
61 langtagLen = endian::from_network(langtagLen);
62
Patrick Venture537ff142018-11-01 16:37:09 -070063 req.header.langtag.insert(
64 0, (const char*)buff.data() + slp::header::OFFSET_LANG, langtagLen);
Ratan Gupta07c462a2016-12-14 00:40:30 +053065
66 /* check for the validity of the function */
Patrick Venture537ff142018-11-01 16:37:09 -070067 if (req.header.functionID <
68 static_cast<uint8_t>(slp::FunctionType::SRVRQST) ||
69 req.header.functionID > static_cast<uint8_t>(slp::FunctionType::SAADV))
Ratan Gupta07c462a2016-12-14 00:40:30 +053070 {
71 rc = static_cast<int>(slp::Error::PARSE_ERROR);
72 }
73
74 return std::make_tuple(rc, std::move(req));
75}
76
Ratan Gupta07c462a2016-12-14 00:40:30 +053077int parseSrvTypeRqst(const buffer& buff, Message& req)
78{
Ratan Gupta07c462a2016-12-14 00:40:30 +053079 /* 0 1 2 3
80 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
81 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
82 | length of PRList | <PRList> String \
83 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
84 | length of Naming Authority | <Naming Authority String> \
85 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
86 | length of <scope-list> | <scope-list> String \
87 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
88
89 /* Enforce SLPv2 service type request size limits. */
90 if (buff.size() < slp::request::MIN_SRVTYPE_LEN)
91 {
92 return (int)slp::Error::PARSE_ERROR;
93 }
94
95 /* Parse the PRList. */
96 uint16_t prListLen;
97 std::copy_n(buff.data() + slp::request::OFFSET_PR_LEN,
Patrick Venture537ff142018-11-01 16:37:09 -070098 slp::request::SIZE_PRLIST, (uint8_t*)&prListLen);
Ratan Gupta07c462a2016-12-14 00:40:30 +053099
100 prListLen = endian::from_network(prListLen);
101
Patrick Venture537ff142018-11-01 16:37:09 -0700102 req.body.srvtyperqst.prList.insert(
103 0, (const char*)buff.data() + slp::request::OFFSET_PR, prListLen);
Ratan Gupta07c462a2016-12-14 00:40:30 +0530104
105 uint8_t pos = slp::request::OFFSET_PR + prListLen;
106
107 /* Parse the Naming Authority. */
108 uint16_t namingAuthLen;
Patrick Venture537ff142018-11-01 16:37:09 -0700109 std::copy_n(buff.data() + pos, slp::request::SIZE_NAMING,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530110 (uint8_t*)&namingAuthLen);
111
112 pos += slp::request::SIZE_NAMING;
113
114 namingAuthLen = endian::from_network(namingAuthLen);
115
116 if (namingAuthLen == 0 || namingAuthLen == 0xffff)
117 {
118 req.body.srvtyperqst.namingAuth = "";
119 }
120 else
121 {
Patrick Venture537ff142018-11-01 16:37:09 -0700122 req.body.srvtyperqst.namingAuth.insert(
123 0, (const char*)buff.data() + pos, namingAuthLen);
Ratan Gupta07c462a2016-12-14 00:40:30 +0530124 }
125
126 pos += namingAuthLen;
127
128 /* Parse the <scope-list>. */
129 uint16_t scopeListLen;
Patrick Venture537ff142018-11-01 16:37:09 -0700130 std::copy_n(buff.data() + pos, slp::request::SIZE_SCOPE,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530131 (uint8_t*)&scopeListLen);
132
133 pos += slp::request::SIZE_SCOPE;
134
135 scopeListLen = endian::from_network(scopeListLen);
136
137 req.body.srvtyperqst.scopeList.insert(0, (const char*)buff.data() + pos,
138 scopeListLen);
139
140 return slp::SUCCESS;
141}
142
143int parseSrvRqst(const buffer& buff, Message& req)
144{
145 /* 0 1 2 3
146 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
147 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
148 | length of <PRList> | <PRList> String \
149 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
150 | length of <service-type> | <service-type> String \
151 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
152 | length of <scope-list> | <scope-list> String \
153 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
154 | length of predicate string | Service Request <predicate> \
155 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
156 | length of <SLP SPI> string | <SLP SPI> String \
157 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
158
159 /* Enforce v2 service request size limits. */
160 if (buff.size() < slp::request::MIN_SRV_LEN)
161 {
162 return (int)slp::Error::PARSE_ERROR;
163 }
164
165 /* 1) Parse the PRList. */
166 uint16_t prListLen;
167 std::copy_n(buff.data() + slp::request::OFFSET_PR_LEN,
Patrick Venture537ff142018-11-01 16:37:09 -0700168 slp::request::SIZE_PRLIST, (uint8_t*)&prListLen);
Ratan Gupta07c462a2016-12-14 00:40:30 +0530169
170 auto pos = slp::request::OFFSET_PR_LEN + slp::request::SIZE_PRLIST;
171
172 prListLen = endian::from_network(prListLen);
173
174 req.body.srvrqst.prList.insert(0, (const char*)buff.data() + pos,
175 prListLen);
176
177 pos += prListLen;
178
Ratan Gupta07c462a2016-12-14 00:40:30 +0530179 /* 2) Parse the <service-type> string. */
180 uint16_t srvTypeLen;
Patrick Venture537ff142018-11-01 16:37:09 -0700181 std::copy_n(buff.data() + pos, slp::request::SIZE_SERVICE_TYPE,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530182 (uint8_t*)&srvTypeLen);
183
184 srvTypeLen = endian::from_network(srvTypeLen);
185
186 pos += slp::request::SIZE_SERVICE_TYPE;
187
188 req.body.srvrqst.srvType.insert(0, (const char*)buff.data() + pos,
189 srvTypeLen);
190
191 pos += srvTypeLen;
192
193 /* 3) Parse the <scope-list> string. */
194 uint16_t scopeListLen;
Patrick Venture537ff142018-11-01 16:37:09 -0700195 std::copy_n(buff.data() + pos, slp::request::SIZE_SCOPE,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530196 (uint8_t*)&scopeListLen);
197
198 scopeListLen = endian::from_network(scopeListLen);
199
200 pos += slp::request::SIZE_SCOPE;
201
202 req.body.srvrqst.scopeList.insert(0, (const char*)buff.data() + pos,
203 scopeListLen);
204
205 pos += scopeListLen;
206
207 /* 4) Parse the <predicate> string. */
208 uint16_t predicateLen;
Patrick Venture537ff142018-11-01 16:37:09 -0700209 std::copy_n(buff.data() + pos, slp::request::SIZE_PREDICATE,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530210 (uint8_t*)&predicateLen);
211
212 predicateLen = endian::from_network(predicateLen);
213 pos += slp::request::SIZE_PREDICATE;
214
215 req.body.srvrqst.predicate.insert(0, (const char*)buff.data() + pos,
216 predicateLen);
217
218 pos += predicateLen;
219
220 /* 5) Parse the <SLP SPI> string. */
221 uint16_t spistrLen;
Patrick Venture537ff142018-11-01 16:37:09 -0700222 std::copy_n(buff.data() + pos, slp::request::SIZE_SLPI,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530223 (uint8_t*)&spistrLen);
224
225 spistrLen = endian::from_network(spistrLen);
226 pos += slp::request::SIZE_SLPI;
227
228 req.body.srvrqst.spistr.insert(0, (const char*)buff.data() + pos,
229 spistrLen);
230
231 return slp::SUCCESS;
232}
Patrick Venture537ff142018-11-01 16:37:09 -0700233} // namespace internal
Ratan Gupta07c462a2016-12-14 00:40:30 +0530234
235std::tuple<int, Message> parseBuffer(const buffer& buff)
236{
237 Message req;
238 int rc = slp::SUCCESS;
239 /* parse the header first */
240 std::tie(rc, req) = internal::parseHeader(buff);
241 if (!rc)
242 {
243 /* switch on the function id to parse the body */
244 switch (req.header.functionID)
245 {
246 case (uint8_t)slp::FunctionType::SRVTYPERQST:
247 rc = internal::parseSrvTypeRqst(buff, req);
248 break;
249 case (uint8_t)slp::FunctionType::SRVRQST:
250 rc = internal::parseSrvRqst(buff, req);
251 break;
252 default:
253 rc = (int)slp::Error::MSG_NOT_SUPPORTED;
254 }
255 }
256 return std::make_tuple(rc, std::move(req));
257}
Patrick Venture537ff142018-11-01 16:37:09 -0700258} // namespace parser
259} // namespace slp