blob: 20f03580f1a94f3871e3a4b7d574ebfd467ee43e [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 <arpa/inet.h>
Ratan Guptaead7a3c2017-01-05 15:45:09 +05306#include <dirent.h>
Ratan Gupta07c462a2016-12-14 00:40:30 +05307#include <ifaddrs.h>
8#include <net/if.h>
9#include <string.h>
10
11#include <algorithm>
Andrew Geissler6f01edc2024-05-24 10:21:05 -050012#include <bitset>
Ratan Gupta07c462a2016-12-14 00:40:30 +053013
Ratan Gupta07c462a2016-12-14 00:40:30 +053014namespace slp
15{
16namespace handler
17{
18
19namespace internal
20{
21
Patrick Williamsf93142e2023-04-04 20:06:36 -050022static constexpr auto SERVICE_DIR = "/etc/slp/services/";
23
Ratan Gupta07c462a2016-12-14 00:40:30 +053024buffer prepareHeader(const Message& req)
25{
Patrick Venture537ff142018-11-01 16:37:09 -070026 uint8_t length =
27 slp::header::MIN_LEN + /* 14 bytes for header */
28 req.header.langtag.length() + /* Actual length of lang tag */
29 slp::response::SIZE_ERROR; /* 2 bytes for error code */
Ratan Gupta07c462a2016-12-14 00:40:30 +053030
31 buffer buff(length, 0);
32
33 buff[slp::header::OFFSET_VERSION] = req.header.version;
34
Patrick Venture537ff142018-11-01 16:37:09 -070035 // will increment the function id from 1 as reply
Ratan Gupta07c462a2016-12-14 00:40:30 +053036 buff[slp::header::OFFSET_FUNCTION] = req.header.functionID + 1;
37
38 std::copy_n(&length, slp::header::SIZE_LENGTH,
Patrick Venture537ff142018-11-01 16:37:09 -070039 buff.data() + slp::header::OFFSET_LENGTH);
Ratan Gupta07c462a2016-12-14 00:40:30 +053040
41 auto flags = endian::to_network(req.header.flags);
42
43 std::copy_n((uint8_t*)&flags, slp::header::SIZE_FLAGS,
Patrick Venture537ff142018-11-01 16:37:09 -070044 buff.data() + slp::header::OFFSET_FLAGS);
Ratan Gupta07c462a2016-12-14 00:40:30 +053045
46 std::copy_n(req.header.extOffset.data(), slp::header::SIZE_EXT,
Patrick Venture537ff142018-11-01 16:37:09 -070047 buff.data() + slp::header::OFFSET_EXT);
Ratan Gupta07c462a2016-12-14 00:40:30 +053048
49 auto xid = endian::to_network(req.header.xid);
50
51 std::copy_n((uint8_t*)&xid, slp::header::SIZE_XID,
Patrick Venture537ff142018-11-01 16:37:09 -070052 buff.data() + slp::header::OFFSET_XID);
Ratan Gupta07c462a2016-12-14 00:40:30 +053053
54 uint16_t langtagLen = req.header.langtag.length();
55 langtagLen = endian::to_network(langtagLen);
56 std::copy_n((uint8_t*)&langtagLen, slp::header::SIZE_LANG,
Patrick Venture537ff142018-11-01 16:37:09 -070057 buff.data() + slp::header::OFFSET_LANG_LEN);
Ratan Gupta07c462a2016-12-14 00:40:30 +053058
Patrick Venture537ff142018-11-01 16:37:09 -070059 std::copy_n((uint8_t*)req.header.langtag.c_str(),
60 req.header.langtag.length(),
61 buff.data() + slp::header::OFFSET_LANG);
Ratan Gupta07c462a2016-12-14 00:40:30 +053062 return buff;
Ratan Gupta07c462a2016-12-14 00:40:30 +053063}
64
Patrick Venture537ff142018-11-01 16:37:09 -070065std::tuple<int, buffer> processSrvTypeRequest(const Message& req)
Ratan Gupta07c462a2016-12-14 00:40:30 +053066{
Ratan Gupta07c462a2016-12-14 00:40:30 +053067 /*
68 0 1 2 3
69 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
70 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
71 | Service Location header (function = SrvTypeRply = 10) |
72 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
73 | Error Code | length of <srvType-list> |
74 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
75 | <srvtype--list> \
76 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
77 */
78
79 buffer buff;
80
Patrick Venture537ff142018-11-01 16:37:09 -070081 // read the slp service info from conf and create the service type string
Ratan Gupta07c462a2016-12-14 00:40:30 +053082 slp::handler::internal::ServiceList svcList =
Ratan Guptaead7a3c2017-01-05 15:45:09 +053083 slp::handler::internal::readSLPServiceInfo();
Ratan Gupta07c462a2016-12-14 00:40:30 +053084 if (svcList.size() <= 0)
85 {
86 buff.resize(0);
Ratan Gupta0d3e9e32017-02-10 22:27:12 +053087 std::cerr << "SLP unable to read the service info\n";
Ratan Gupta07c462a2016-12-14 00:40:30 +053088 return std::make_tuple((int)slp::Error::INTERNAL_ERROR, buff);
89 }
90
91 std::string service;
92 bool firstIteration = true;
93 for_each(svcList.cbegin(), svcList.cend(),
Patrick Venture537ff142018-11-01 16:37:09 -070094 [&service, &firstIteration](const auto& svc) {
Patrick Williamsaa902c62023-04-04 19:59:51 -050095 if (firstIteration == true)
96 {
97 service = svc.first;
98 firstIteration = false;
99 }
100 else
101 {
102 service += ",";
103 service += svc.first;
104 }
105 });
Ratan Gupta07c462a2016-12-14 00:40:30 +0530106
107 buff = prepareHeader(req);
108
109 /* Need to modify the length and the function type field of the header
110 * as it is dependent on the handler of the service */
111
112 std::cout << "service=" << service.c_str() << "\n";
113
Andrew Geisslereebd0812024-05-24 10:05:27 -0500114 // See if total response size exceeds our max
115 uint32_t totalLength =
116 buff.size() + /* 14 bytes header + length of langtag */
117 slp::response::SIZE_ERROR + /* 2 byte err code */
118 slp::response::SIZE_SERVICE + /* 2 byte srvtype len */
119 service.length();
120 if (totalLength > slp::MAX_LEN)
121 {
122 std::cerr << "Message response size exceeds maximum allowed: "
123 << totalLength << " / " << slp::MAX_LEN << std::endl;
124 buff.resize(0);
125 return std::make_tuple((int)slp::Error::PARSE_ERROR, buff);
126 }
127
Patrick Venture537ff142018-11-01 16:37:09 -0700128 uint8_t length = buff.size() + /* 14 bytes header + length of langtag */
129 slp::response::SIZE_ERROR + /* 2 byte err code */
130 slp::response::SIZE_SERVICE + /* 2 byte srvtype len */
131 service.length();
Ratan Gupta07c462a2016-12-14 00:40:30 +0530132
133 buff.resize(length);
134
135 std::copy_n(&length, slp::header::SIZE_LENGTH,
Patrick Venture537ff142018-11-01 16:37:09 -0700136 buff.data() + slp::header::OFFSET_LENGTH);
Ratan Gupta07c462a2016-12-14 00:40:30 +0530137
138 /* error code is already set to 0 moving to service type len */
139
140 uint16_t serviceTypeLen = service.length();
141 serviceTypeLen = endian::to_network(serviceTypeLen);
142
143 std::copy_n((uint8_t*)&serviceTypeLen, slp::response::SIZE_SERVICE,
Patrick Venture537ff142018-11-01 16:37:09 -0700144 buff.data() + slp::response::OFFSET_SERVICE_LEN);
Ratan Gupta07c462a2016-12-14 00:40:30 +0530145
146 /* service type data */
147 std::copy_n((uint8_t*)service.c_str(), service.length(),
Patrick Venture537ff142018-11-01 16:37:09 -0700148 (buff.data() + slp::response::OFFSET_SERVICE));
Ratan Gupta07c462a2016-12-14 00:40:30 +0530149
150 return std::make_tuple(slp::SUCCESS, buff);
151}
152
Patrick Venture537ff142018-11-01 16:37:09 -0700153std::tuple<int, buffer> processSrvRequest(const Message& req)
Ratan Gupta07c462a2016-12-14 00:40:30 +0530154{
Ratan Gupta07c462a2016-12-14 00:40:30 +0530155 /*
156 Service Reply
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 | Service Location header (function = SrvRply = 2) |
161 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
162 | Error Code | URL Entry count |
163 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
164 | <URL Entry 1> ... <URL Entry N> \
165 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
166
167 URL Entry
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 | Reserved | Lifetime | URL Length |
172 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
173 |URL len, contd.| URL (variable length) \
174 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
175 |# of URL auths | Auth. blocks (if any) \
176 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
177 */
178
179 buffer buff;
Patrick Venture537ff142018-11-01 16:37:09 -0700180 // Get all the services which are registered
Ratan Gupta07c462a2016-12-14 00:40:30 +0530181 slp::handler::internal::ServiceList svcList =
Ratan Guptaead7a3c2017-01-05 15:45:09 +0530182 slp::handler::internal::readSLPServiceInfo();
Ratan Gupta07c462a2016-12-14 00:40:30 +0530183 if (svcList.size() <= 0)
184 {
185 buff.resize(0);
Ratan Gupta0d3e9e32017-02-10 22:27:12 +0530186 std::cerr << "SLP unable to read the service info\n";
Ratan Gupta07c462a2016-12-14 00:40:30 +0530187 return std::make_tuple((int)slp::Error::INTERNAL_ERROR, buff);
188 }
189
Patrick Venture537ff142018-11-01 16:37:09 -0700190 // return error if serice type doesn't match
Ratan Gupta07c462a2016-12-14 00:40:30 +0530191 auto& svcName = req.body.srvrqst.srvType;
192 auto svcIt = svcList.find(svcName);
193 if (svcIt == svcList.end())
194 {
195 buff.resize(0);
Ratan Gupta0d3e9e32017-02-10 22:27:12 +0530196 std::cerr << "SLP unable to find the service=" << svcName << "\n";
Ratan Gupta07c462a2016-12-14 00:40:30 +0530197 return std::make_tuple((int)slp::Error::INTERNAL_ERROR, buff);
198 }
Patrick Venture537ff142018-11-01 16:37:09 -0700199 // Get all the interface address
Ratan Gupta07c462a2016-12-14 00:40:30 +0530200 auto ifaddrList = slp::handler::internal::getIntfAddrs();
201 if (ifaddrList.size() <= 0)
202 {
203 buff.resize(0);
Ratan Gupta0d3e9e32017-02-10 22:27:12 +0530204 std::cerr << "SLP unable to read the interface address\n";
Ratan Gupta07c462a2016-12-14 00:40:30 +0530205 return std::make_tuple((int)slp::Error::INTERNAL_ERROR, buff);
206 }
207
208 buff = prepareHeader(req);
Patrick Venture537ff142018-11-01 16:37:09 -0700209 // Calculate the length and resize the buffer
210 uint8_t length = buff.size() + /* 14 bytes header + length of langtag */
211 slp::response::SIZE_ERROR + /* 2 bytes error code */
212 slp::response::SIZE_URL_COUNT; /* 2 bytes srvtype len */
Ratan Gupta07c462a2016-12-14 00:40:30 +0530213
214 buff.resize(length);
215
Patrick Venture537ff142018-11-01 16:37:09 -0700216 // Populate the url count
Ratan Gupta07c462a2016-12-14 00:40:30 +0530217 uint16_t urlCount = ifaddrList.size();
218 urlCount = endian::to_network(urlCount);
219
220 std::copy_n((uint8_t*)&urlCount, slp::response::SIZE_URL_COUNT,
Patrick Venture537ff142018-11-01 16:37:09 -0700221 buff.data() + slp::response::OFFSET_URL_ENTRY);
Ratan Gupta07c462a2016-12-14 00:40:30 +0530222
Patrick Venture537ff142018-11-01 16:37:09 -0700223 // Find the service
Ratan Gupta07c462a2016-12-14 00:40:30 +0530224 const slp::ConfigData& svc = svcIt->second;
Patrick Venture537ff142018-11-01 16:37:09 -0700225 // Populate the URL Entries
Ratan Gupta07c462a2016-12-14 00:40:30 +0530226 auto pos = slp::response::OFFSET_URL_ENTRY + slp::response::SIZE_URL_COUNT;
227 for (const auto& addr : ifaddrList)
228 {
Patrick Williamsaa902c62023-04-04 19:59:51 -0500229 std::string url = svc.name + ':' + svc.type + "//" + addr + ',' +
230 svc.port;
Ratan Gupta07c462a2016-12-14 00:40:30 +0530231
Andrew Geisslereebd0812024-05-24 10:05:27 -0500232 // See if total response size exceeds our max
233 uint32_t totalLength = buff.size() + slp::response::SIZE_URL_ENTRY +
234 url.length();
235 if (totalLength > slp::MAX_LEN)
236 {
237 std::cerr << "Message response size exceeds maximum allowed: "
238 << totalLength << " / " << slp::MAX_LEN << std::endl;
239 buff.resize(0);
240 return std::make_tuple((int)slp::Error::PARSE_ERROR, buff);
241 }
242
Patrick Venture537ff142018-11-01 16:37:09 -0700243 buff.resize(buff.size() + slp::response::SIZE_URL_ENTRY + url.length());
Ratan Gupta07c462a2016-12-14 00:40:30 +0530244
245 uint8_t reserved = 0;
246 uint16_t auth = 0;
247 uint16_t lifetime = endian::to_network<uint16_t>(slp::LIFETIME);
248 uint16_t urlLength = url.length();
249
250 std::copy_n((uint8_t*)&reserved, slp::response::SIZE_RESERVED,
251 buff.data() + pos);
252
253 pos += slp::response::SIZE_RESERVED;
254
Ratan Gupta07c462a2016-12-14 00:40:30 +0530255 std::copy_n((uint8_t*)&lifetime, slp::response::SIZE_LIFETIME,
256 buff.data() + pos);
257
258 pos += slp::response::SIZE_LIFETIME;
259
260 urlLength = endian::to_network(urlLength);
261 std::copy_n((uint8_t*)&urlLength, slp::response::SIZE_URLLENGTH,
262 buff.data() + pos);
263 pos += slp::response::SIZE_URLLENGTH;
264
Patrick Venture537ff142018-11-01 16:37:09 -0700265 std::copy_n((uint8_t*)url.c_str(), url.length(), buff.data() + pos);
Ratan Gupta07c462a2016-12-14 00:40:30 +0530266 pos += url.length();
267
268 std::copy_n((uint8_t*)&auth, slp::response::SIZE_AUTH,
269 buff.data() + pos);
270 pos += slp::response::SIZE_AUTH;
271 }
272 uint8_t packetLength = buff.size();
273 std::copy_n((uint8_t*)&packetLength, slp::header::SIZE_VERSION,
Patrick Venture537ff142018-11-01 16:37:09 -0700274 buff.data() + slp::header::OFFSET_LENGTH);
Ratan Gupta07c462a2016-12-14 00:40:30 +0530275
276 return std::make_tuple((int)slp::SUCCESS, buff);
277}
278
279std::list<std::string> getIntfAddrs()
280{
281 std::list<std::string> addrList;
282
283 struct ifaddrs* ifaddr;
284 // attempt to fill struct with ifaddrs
285 if (getifaddrs(&ifaddr) == -1)
286 {
287 return addrList;
288 }
289
Patrick Venture537ff142018-11-01 16:37:09 -0700290 slp::deleted_unique_ptr<ifaddrs> ifaddrPtr(
291 ifaddr, [](ifaddrs* addr) { freeifaddrs(addr); });
Ratan Gupta07c462a2016-12-14 00:40:30 +0530292
293 ifaddr = nullptr;
294
295 for (ifaddrs* ifa = ifaddrPtr.get(); ifa != nullptr; ifa = ifa->ifa_next)
296 {
297 // walk interfaces
298 if (ifa->ifa_addr == nullptr)
299 {
300 continue;
301 }
302
303 // get only INET interfaces not ipv6
304 if (ifa->ifa_addr->sa_family == AF_INET)
305 {
306 // if loopback, or not running ignore
307 if ((ifa->ifa_flags & IFF_LOOPBACK) ||
308 !(ifa->ifa_flags & IFF_RUNNING))
309 {
310 continue;
311 }
312
Patrick Venture537ff142018-11-01 16:37:09 -0700313 char tmp[INET_ADDRSTRLEN] = {0};
Ratan Gupta07c462a2016-12-14 00:40:30 +0530314
315 inet_ntop(AF_INET,
Patrick Venture537ff142018-11-01 16:37:09 -0700316 &(((struct sockaddr_in*)(ifa->ifa_addr))->sin_addr), tmp,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530317 sizeof(tmp));
318 addrList.emplace_back(tmp);
319 }
320 }
321
322 return addrList;
323}
324
Patrick Venture537ff142018-11-01 16:37:09 -0700325slp::handler::internal::ServiceList readSLPServiceInfo()
Ratan Gupta07c462a2016-12-14 00:40:30 +0530326{
327 using namespace std::string_literals;
Ratan Gupta07c462a2016-12-14 00:40:30 +0530328 slp::handler::internal::ServiceList svcLst;
Ratan Gupta07c462a2016-12-14 00:40:30 +0530329 slp::ConfigData service;
Ratan Guptaead7a3c2017-01-05 15:45:09 +0530330 struct dirent* dent = nullptr;
Ratan Gupta07c462a2016-12-14 00:40:30 +0530331
Ratan Guptaead7a3c2017-01-05 15:45:09 +0530332 // Open the services dir and get the service info
333 // from service files.
334 // Service File format would be "ServiceName serviceType Port"
335 DIR* dir = opendir(SERVICE_DIR);
336 // wrap the pointer into smart pointer.
Patrick Venture537ff142018-11-01 16:37:09 -0700337 slp::deleted_unique_ptr<DIR> dirPtr(dir, [](DIR* dir) {
Ratan Guptaead7a3c2017-01-05 15:45:09 +0530338 if (!dir)
339 {
340 closedir(dir);
341 }
342 });
343 dir = nullptr;
344
345 if (dirPtr.get())
346 {
347 while ((dent = readdir(dirPtr.get())) != NULL)
348 {
Patrick Venture537ff142018-11-01 16:37:09 -0700349 if (dent->d_type == DT_REG) // regular file
Ratan Guptaead7a3c2017-01-05 15:45:09 +0530350 {
351 auto absFileName = std::string(SERVICE_DIR) + dent->d_name;
352 std::ifstream readFile(absFileName);
353 readFile >> service;
354 service.name = "service:"s + service.name;
355 svcLst.emplace(service.name, service);
356 }
357 }
Ratan Guptaead7a3c2017-01-05 15:45:09 +0530358 }
Ratan Gupta07c462a2016-12-14 00:40:30 +0530359 return svcLst;
360}
Patrick Venture537ff142018-11-01 16:37:09 -0700361} // namespace internal
Ratan Gupta07c462a2016-12-14 00:40:30 +0530362
Patrick Venture537ff142018-11-01 16:37:09 -0700363std::tuple<int, buffer> processRequest(const Message& msg)
Ratan Gupta07c462a2016-12-14 00:40:30 +0530364{
365 int rc = slp::SUCCESS;
Andrew Geissler40efe672024-07-24 16:02:10 -0300366 buffer resp;
Andrew Geissler6f01edc2024-05-24 10:21:05 -0500367 std::cout << "SLP Processing Request="
368 << std::bitset<8>(msg.header.functionID) << "\n";
Brad Bishopb5e632a2018-02-23 15:22:12 -0500369
Ratan Gupta07c462a2016-12-14 00:40:30 +0530370 switch (msg.header.functionID)
371 {
Ratan Gupta07c462a2016-12-14 00:40:30 +0530372 case (uint8_t)slp::FunctionType::SRVTYPERQST:
Patrick Williamsaa902c62023-04-04 19:59:51 -0500373 std::tie(rc,
374 resp) = slp::handler::internal::processSrvTypeRequest(msg);
Ratan Gupta07c462a2016-12-14 00:40:30 +0530375 break;
376 case (uint8_t)slp::FunctionType::SRVRQST:
377 std::tie(rc, resp) = slp::handler::internal::processSrvRequest(msg);
378 break;
379 default:
380 rc = (uint8_t)slp::Error::MSG_NOT_SUPPORTED;
381 }
382 return std::make_tuple(rc, resp);
383}
384
Patrick Venture537ff142018-11-01 16:37:09 -0700385buffer processError(const Message& req, uint8_t err)
Ratan Gupta07c462a2016-12-14 00:40:30 +0530386{
Andrew Geissler6f01edc2024-05-24 10:21:05 -0500387 if (req.header.functionID != 0)
388 {
389 std::cout << "Processing Error for function: "
390 << std::bitset<8>(req.header.functionID) << std::endl;
391 }
392
393 /* 0 1 2 3
394 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
395 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
396 | Service Location header (function = SrvRply = 2) |
397 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
398 | Error Code | URL Entry count |
399 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
400 | <URL Entry 1> ... <URL Entry N> \
401 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+*/
402
403 // There has been some sort of issue processing the request from
404 // the client. Can not assume the input request buffer is valid
405 // so just create an empty buffer with the non-variable size
406 // fields set and the error code
407 uint8_t length = slp::header::MIN_LEN + /* 14 bytes for header */
408 slp::response::SIZE_ERROR; /* 2 bytes for error code */
409
410 buffer buff(length, 0);
Ratan Gupta07c462a2016-12-14 00:40:30 +0530411
Patrick Williamsedf88cb2023-04-04 20:16:37 -0500412 static_assert(sizeof(err) == 1, "Errors should be 1 byte.");
413
Andrew Geissler6f01edc2024-05-24 10:21:05 -0500414 buff[slp::header::OFFSET_VERSION] = req.header.version;
415
416 // will increment the function id from 1 as reply
417 buff[slp::header::OFFSET_FUNCTION] = req.header.functionID + 1;
418
419 std::copy_n(&length, slp::header::SIZE_LENGTH,
420 buff.data() + slp::header::OFFSET_LENGTH);
421
422 auto flags = endian::to_network(req.header.flags);
423
424 std::copy_n((uint8_t*)&flags, slp::header::SIZE_FLAGS,
425 buff.data() + slp::header::OFFSET_FLAGS);
426
427 std::copy_n(req.header.extOffset.data(), slp::header::SIZE_EXT,
428 buff.data() + slp::header::OFFSET_EXT);
429
430 auto xid = endian::to_network(req.header.xid);
431
432 std::copy_n((uint8_t*)&xid, slp::header::SIZE_XID,
433 buff.data() + slp::header::OFFSET_XID);
434
435 // This is an invalid header from user so just fill in 0 for langtag
436 uint16_t langtagLen = 0;
437 std::copy_n((uint8_t*)&langtagLen, slp::header::SIZE_LANG,
438 buff.data() + slp::header::OFFSET_LANG_LEN);
439
Patrick Williamsedf88cb2023-04-04 20:16:37 -0500440 // Since this is network order, the err should go in the 2nd byte of the
Andrew Geissler6f01edc2024-05-24 10:21:05 -0500441 // error field.
442 buff[slp::header::MIN_LEN + 1] = err;
Patrick Williamsedf88cb2023-04-04 20:16:37 -0500443
Ratan Gupta07c462a2016-12-14 00:40:30 +0530444 return buff;
Ratan Gupta07c462a2016-12-14 00:40:30 +0530445}
Patrick Venture537ff142018-11-01 16:37:09 -0700446} // namespace handler
447} // namespace slp