blob: 0535f4b8ad38d898a8597d99aedee33aed93ad01 [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 Williams1a6b1c22024-08-16 15:22:34 -040095 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 Williams1a6b1c22024-08-16 15:22:34 -0400229 std::string url =
230 svc.name + ':' + svc.type + "//" + addr + ',' + 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
Patrick Williams1a6b1c22024-08-16 15:22:34 -0400233 uint32_t totalLength =
234 buff.size() + slp::response::SIZE_URL_ENTRY + url.length();
Andrew Geisslereebd0812024-05-24 10:05:27 -0500235 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 Williams1a6b1c22024-08-16 15:22:34 -0400290 slp::deleted_unique_ptr<ifaddrs> ifaddrPtr(ifaddr, [](ifaddrs* addr) {
291 freeifaddrs(addr);
292 });
Ratan Gupta07c462a2016-12-14 00:40:30 +0530293
294 ifaddr = nullptr;
295
296 for (ifaddrs* ifa = ifaddrPtr.get(); ifa != nullptr; ifa = ifa->ifa_next)
297 {
298 // walk interfaces
299 if (ifa->ifa_addr == nullptr)
300 {
301 continue;
302 }
303
304 // get only INET interfaces not ipv6
305 if (ifa->ifa_addr->sa_family == AF_INET)
306 {
307 // if loopback, or not running ignore
308 if ((ifa->ifa_flags & IFF_LOOPBACK) ||
309 !(ifa->ifa_flags & IFF_RUNNING))
310 {
311 continue;
312 }
313
Patrick Venture537ff142018-11-01 16:37:09 -0700314 char tmp[INET_ADDRSTRLEN] = {0};
Ratan Gupta07c462a2016-12-14 00:40:30 +0530315
316 inet_ntop(AF_INET,
Patrick Venture537ff142018-11-01 16:37:09 -0700317 &(((struct sockaddr_in*)(ifa->ifa_addr))->sin_addr), tmp,
Ratan Gupta07c462a2016-12-14 00:40:30 +0530318 sizeof(tmp));
319 addrList.emplace_back(tmp);
320 }
321 }
322
323 return addrList;
324}
325
Patrick Venture537ff142018-11-01 16:37:09 -0700326slp::handler::internal::ServiceList readSLPServiceInfo()
Ratan Gupta07c462a2016-12-14 00:40:30 +0530327{
328 using namespace std::string_literals;
Ratan Gupta07c462a2016-12-14 00:40:30 +0530329 slp::handler::internal::ServiceList svcLst;
Ratan Gupta07c462a2016-12-14 00:40:30 +0530330 slp::ConfigData service;
Ratan Guptaead7a3c2017-01-05 15:45:09 +0530331 struct dirent* dent = nullptr;
Ratan Gupta07c462a2016-12-14 00:40:30 +0530332
Ratan Guptaead7a3c2017-01-05 15:45:09 +0530333 // Open the services dir and get the service info
334 // from service files.
335 // Service File format would be "ServiceName serviceType Port"
336 DIR* dir = opendir(SERVICE_DIR);
337 // wrap the pointer into smart pointer.
Patrick Venture537ff142018-11-01 16:37:09 -0700338 slp::deleted_unique_ptr<DIR> dirPtr(dir, [](DIR* dir) {
Ratan Guptaead7a3c2017-01-05 15:45:09 +0530339 if (!dir)
340 {
341 closedir(dir);
342 }
343 });
344 dir = nullptr;
345
346 if (dirPtr.get())
347 {
348 while ((dent = readdir(dirPtr.get())) != NULL)
349 {
Patrick Venture537ff142018-11-01 16:37:09 -0700350 if (dent->d_type == DT_REG) // regular file
Ratan Guptaead7a3c2017-01-05 15:45:09 +0530351 {
352 auto absFileName = std::string(SERVICE_DIR) + dent->d_name;
353 std::ifstream readFile(absFileName);
354 readFile >> service;
355 service.name = "service:"s + service.name;
356 svcLst.emplace(service.name, service);
357 }
358 }
Ratan Guptaead7a3c2017-01-05 15:45:09 +0530359 }
Ratan Gupta07c462a2016-12-14 00:40:30 +0530360 return svcLst;
361}
Patrick Venture537ff142018-11-01 16:37:09 -0700362} // namespace internal
Ratan Gupta07c462a2016-12-14 00:40:30 +0530363
Patrick Venture537ff142018-11-01 16:37:09 -0700364std::tuple<int, buffer> processRequest(const Message& msg)
Ratan Gupta07c462a2016-12-14 00:40:30 +0530365{
366 int rc = slp::SUCCESS;
Andrew Geissler40efe672024-07-24 16:02:10 -0300367 buffer resp;
Andrew Geissler6f01edc2024-05-24 10:21:05 -0500368 std::cout << "SLP Processing Request="
369 << std::bitset<8>(msg.header.functionID) << "\n";
Brad Bishopb5e632a2018-02-23 15:22:12 -0500370
Ratan Gupta07c462a2016-12-14 00:40:30 +0530371 switch (msg.header.functionID)
372 {
Ratan Gupta07c462a2016-12-14 00:40:30 +0530373 case (uint8_t)slp::FunctionType::SRVTYPERQST:
Patrick Williams1a6b1c22024-08-16 15:22:34 -0400374 std::tie(rc, resp) =
375 slp::handler::internal::processSrvTypeRequest(msg);
Ratan Gupta07c462a2016-12-14 00:40:30 +0530376 break;
377 case (uint8_t)slp::FunctionType::SRVRQST:
378 std::tie(rc, resp) = slp::handler::internal::processSrvRequest(msg);
379 break;
380 default:
381 rc = (uint8_t)slp::Error::MSG_NOT_SUPPORTED;
382 }
383 return std::make_tuple(rc, resp);
384}
385
Patrick Venture537ff142018-11-01 16:37:09 -0700386buffer processError(const Message& req, uint8_t err)
Ratan Gupta07c462a2016-12-14 00:40:30 +0530387{
Andrew Geissler6f01edc2024-05-24 10:21:05 -0500388 if (req.header.functionID != 0)
389 {
390 std::cout << "Processing Error for function: "
391 << std::bitset<8>(req.header.functionID) << std::endl;
392 }
393
394 /* 0 1 2 3
395 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
396 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
397 | Service Location header (function = SrvRply = 2) |
398 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
399 | Error Code | URL Entry count |
400 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
401 | <URL Entry 1> ... <URL Entry N> \
402 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+*/
403
404 // There has been some sort of issue processing the request from
405 // the client. Can not assume the input request buffer is valid
406 // so just create an empty buffer with the non-variable size
407 // fields set and the error code
408 uint8_t length = slp::header::MIN_LEN + /* 14 bytes for header */
409 slp::response::SIZE_ERROR; /* 2 bytes for error code */
410
411 buffer buff(length, 0);
Ratan Gupta07c462a2016-12-14 00:40:30 +0530412
Patrick Williamsedf88cb2023-04-04 20:16:37 -0500413 static_assert(sizeof(err) == 1, "Errors should be 1 byte.");
414
Andrew Geissler6f01edc2024-05-24 10:21:05 -0500415 buff[slp::header::OFFSET_VERSION] = req.header.version;
416
417 // will increment the function id from 1 as reply
418 buff[slp::header::OFFSET_FUNCTION] = req.header.functionID + 1;
419
420 std::copy_n(&length, slp::header::SIZE_LENGTH,
421 buff.data() + slp::header::OFFSET_LENGTH);
422
423 auto flags = endian::to_network(req.header.flags);
424
425 std::copy_n((uint8_t*)&flags, slp::header::SIZE_FLAGS,
426 buff.data() + slp::header::OFFSET_FLAGS);
427
428 std::copy_n(req.header.extOffset.data(), slp::header::SIZE_EXT,
429 buff.data() + slp::header::OFFSET_EXT);
430
431 auto xid = endian::to_network(req.header.xid);
432
433 std::copy_n((uint8_t*)&xid, slp::header::SIZE_XID,
434 buff.data() + slp::header::OFFSET_XID);
435
436 // This is an invalid header from user so just fill in 0 for langtag
437 uint16_t langtagLen = 0;
438 std::copy_n((uint8_t*)&langtagLen, slp::header::SIZE_LANG,
439 buff.data() + slp::header::OFFSET_LANG_LEN);
440
Patrick Williamsedf88cb2023-04-04 20:16:37 -0500441 // Since this is network order, the err should go in the 2nd byte of the
Andrew Geissler6f01edc2024-05-24 10:21:05 -0500442 // error field.
443 buff[slp::header::MIN_LEN + 1] = err;
Patrick Williamsedf88cb2023-04-04 20:16:37 -0500444
Ratan Gupta07c462a2016-12-14 00:40:30 +0530445 return buff;
Ratan Gupta07c462a2016-12-14 00:40:30 +0530446}
Patrick Venture537ff142018-11-01 16:37:09 -0700447} // namespace handler
448} // namespace slp