blob: 9b4119b3c3536a586f45662a10340e373e048da0 [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 Venture537ff142018-11-01 16:37:09 -070033 Message req{0};
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{
79
Ratan Gupta07c462a2016-12-14 00:40:30 +053080 /* 0 1 2 3
81 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
82 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
83 | length of PRList | <PRList> String \
84 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
85 | length of Naming Authority | <Naming Authority String> \
86 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
87 | length of <scope-list> | <scope-list> String \
88 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
89
90 /* Enforce SLPv2 service type request size limits. */
91 if (buff.size() < slp::request::MIN_SRVTYPE_LEN)
92 {
93 return (int)slp::Error::PARSE_ERROR;
94 }
95
96 /* Parse the PRList. */
97 uint16_t prListLen;
98 std::copy_n(buff.data() + slp::request::OFFSET_PR_LEN,
Patrick Venture537ff142018-11-01 16:37:09 -070099 slp::request::SIZE_PRLIST, (uint8_t*)&prListLen);
Ratan Gupta07c462a2016-12-14 00:40:30 +0530100
101 prListLen = endian::from_network(prListLen);
102
Patrick Venture537ff142018-11-01 16:37:09 -0700103 req.body.srvtyperqst.prList.insert(
104 0, (const char*)buff.data() + slp::request::OFFSET_PR, prListLen);
Ratan Gupta07c462a2016-12-14 00:40:30 +0530105
106 uint8_t pos = slp::request::OFFSET_PR + prListLen;
107
108 /* Parse the Naming Authority. */
109 uint16_t namingAuthLen;
Patrick Venture537ff142018-11-01 16:37:09 -0700110 std::copy_n(buff.data() + pos, slp::request::SIZE_NAMING,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530111 (uint8_t*)&namingAuthLen);
112
113 pos += slp::request::SIZE_NAMING;
114
115 namingAuthLen = endian::from_network(namingAuthLen);
116
117 if (namingAuthLen == 0 || namingAuthLen == 0xffff)
118 {
119 req.body.srvtyperqst.namingAuth = "";
120 }
121 else
122 {
Patrick Venture537ff142018-11-01 16:37:09 -0700123 req.body.srvtyperqst.namingAuth.insert(
124 0, (const char*)buff.data() + pos, namingAuthLen);
Ratan Gupta07c462a2016-12-14 00:40:30 +0530125 }
126
127 pos += namingAuthLen;
128
129 /* Parse the <scope-list>. */
130 uint16_t scopeListLen;
Patrick Venture537ff142018-11-01 16:37:09 -0700131 std::copy_n(buff.data() + pos, slp::request::SIZE_SCOPE,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530132 (uint8_t*)&scopeListLen);
133
134 pos += slp::request::SIZE_SCOPE;
135
136 scopeListLen = endian::from_network(scopeListLen);
137
138 req.body.srvtyperqst.scopeList.insert(0, (const char*)buff.data() + pos,
139 scopeListLen);
140
141 return slp::SUCCESS;
142}
143
144int parseSrvRqst(const buffer& buff, Message& req)
145{
146 /* 0 1 2 3
147 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
148 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
149 | length of <PRList> | <PRList> String \
150 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
151 | length of <service-type> | <service-type> String \
152 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
153 | length of <scope-list> | <scope-list> String \
154 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
155 | length of predicate string | Service Request <predicate> \
156 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
157 | length of <SLP SPI> string | <SLP SPI> String \
158 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
159
160 /* Enforce v2 service request size limits. */
161 if (buff.size() < slp::request::MIN_SRV_LEN)
162 {
163 return (int)slp::Error::PARSE_ERROR;
164 }
165
166 /* 1) Parse the PRList. */
167 uint16_t prListLen;
168 std::copy_n(buff.data() + slp::request::OFFSET_PR_LEN,
Patrick Venture537ff142018-11-01 16:37:09 -0700169 slp::request::SIZE_PRLIST, (uint8_t*)&prListLen);
Ratan Gupta07c462a2016-12-14 00:40:30 +0530170
171 auto pos = slp::request::OFFSET_PR_LEN + slp::request::SIZE_PRLIST;
172
173 prListLen = endian::from_network(prListLen);
174
175 req.body.srvrqst.prList.insert(0, (const char*)buff.data() + pos,
176 prListLen);
177
178 pos += prListLen;
179
Ratan Gupta07c462a2016-12-14 00:40:30 +0530180 /* 2) Parse the <service-type> string. */
181 uint16_t srvTypeLen;
Patrick Venture537ff142018-11-01 16:37:09 -0700182 std::copy_n(buff.data() + pos, slp::request::SIZE_SERVICE_TYPE,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530183 (uint8_t*)&srvTypeLen);
184
185 srvTypeLen = endian::from_network(srvTypeLen);
186
187 pos += slp::request::SIZE_SERVICE_TYPE;
188
189 req.body.srvrqst.srvType.insert(0, (const char*)buff.data() + pos,
190 srvTypeLen);
191
192 pos += srvTypeLen;
193
194 /* 3) Parse the <scope-list> string. */
195 uint16_t scopeListLen;
Patrick Venture537ff142018-11-01 16:37:09 -0700196 std::copy_n(buff.data() + pos, slp::request::SIZE_SCOPE,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530197 (uint8_t*)&scopeListLen);
198
199 scopeListLen = endian::from_network(scopeListLen);
200
201 pos += slp::request::SIZE_SCOPE;
202
203 req.body.srvrqst.scopeList.insert(0, (const char*)buff.data() + pos,
204 scopeListLen);
205
206 pos += scopeListLen;
207
208 /* 4) Parse the <predicate> string. */
209 uint16_t predicateLen;
Patrick Venture537ff142018-11-01 16:37:09 -0700210 std::copy_n(buff.data() + pos, slp::request::SIZE_PREDICATE,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530211 (uint8_t*)&predicateLen);
212
213 predicateLen = endian::from_network(predicateLen);
214 pos += slp::request::SIZE_PREDICATE;
215
216 req.body.srvrqst.predicate.insert(0, (const char*)buff.data() + pos,
217 predicateLen);
218
219 pos += predicateLen;
220
221 /* 5) Parse the <SLP SPI> string. */
222 uint16_t spistrLen;
Patrick Venture537ff142018-11-01 16:37:09 -0700223 std::copy_n(buff.data() + pos, slp::request::SIZE_SLPI,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530224 (uint8_t*)&spistrLen);
225
226 spistrLen = endian::from_network(spistrLen);
227 pos += slp::request::SIZE_SLPI;
228
229 req.body.srvrqst.spistr.insert(0, (const char*)buff.data() + pos,
230 spistrLen);
231
232 return slp::SUCCESS;
233}
Patrick Venture537ff142018-11-01 16:37:09 -0700234} // namespace internal
Ratan Gupta07c462a2016-12-14 00:40:30 +0530235
236std::tuple<int, Message> parseBuffer(const buffer& buff)
237{
238 Message req;
239 int rc = slp::SUCCESS;
240 /* parse the header first */
241 std::tie(rc, req) = internal::parseHeader(buff);
242 if (!rc)
243 {
244 /* switch on the function id to parse the body */
245 switch (req.header.functionID)
246 {
247 case (uint8_t)slp::FunctionType::SRVTYPERQST:
248 rc = internal::parseSrvTypeRqst(buff, req);
249 break;
250 case (uint8_t)slp::FunctionType::SRVRQST:
251 rc = internal::parseSrvRqst(buff, req);
252 break;
253 default:
254 rc = (int)slp::Error::MSG_NOT_SUPPORTED;
255 }
256 }
257 return std::make_tuple(rc, std::move(req));
258}
Patrick Venture537ff142018-11-01 16:37:09 -0700259} // namespace parser
260} // namespace slp