1537ff140SPatrick Venture #include "config.h"
2537ff140SPatrick Venture 
3537ff140SPatrick Venture #include "endian.hpp"
407c462acSRatan Gupta #include "slp.hpp"
5537ff140SPatrick Venture #include "slp_meta.hpp"
607c462acSRatan Gupta 
707c462acSRatan Gupta #include <arpa/inet.h>
8ead7a3caSRatan Gupta #include <dirent.h>
907c462acSRatan Gupta #include <ifaddrs.h>
1007c462acSRatan Gupta #include <net/if.h>
1107c462acSRatan Gupta #include <string.h>
1207c462acSRatan Gupta 
1307c462acSRatan Gupta #include <algorithm>
1407c462acSRatan Gupta 
1507c462acSRatan Gupta namespace slp
1607c462acSRatan Gupta {
1707c462acSRatan Gupta namespace handler
1807c462acSRatan Gupta {
1907c462acSRatan Gupta 
2007c462acSRatan Gupta namespace internal
2107c462acSRatan Gupta {
2207c462acSRatan Gupta 
2307c462acSRatan Gupta buffer prepareHeader(const Message& req)
2407c462acSRatan Gupta {
25537ff140SPatrick Venture     uint8_t length =
26537ff140SPatrick Venture         slp::header::MIN_LEN +        /* 14 bytes for header     */
2707c462acSRatan Gupta         req.header.langtag.length() + /* Actual length of lang tag */
2807c462acSRatan Gupta         slp::response::SIZE_ERROR;    /*  2 bytes for error code */
2907c462acSRatan Gupta 
3007c462acSRatan Gupta     buffer buff(length, 0);
3107c462acSRatan Gupta 
3207c462acSRatan Gupta     buff[slp::header::OFFSET_VERSION] = req.header.version;
3307c462acSRatan Gupta 
3407c462acSRatan Gupta     // will increment the function id from 1 as reply
3507c462acSRatan Gupta     buff[slp::header::OFFSET_FUNCTION] = req.header.functionID + 1;
3607c462acSRatan Gupta 
3707c462acSRatan Gupta     std::copy_n(&length, slp::header::SIZE_LENGTH,
38537ff140SPatrick Venture                 buff.data() + slp::header::OFFSET_LENGTH);
3907c462acSRatan Gupta 
4007c462acSRatan Gupta     auto flags = endian::to_network(req.header.flags);
4107c462acSRatan Gupta 
4207c462acSRatan Gupta     std::copy_n((uint8_t*)&flags, slp::header::SIZE_FLAGS,
43537ff140SPatrick Venture                 buff.data() + slp::header::OFFSET_FLAGS);
4407c462acSRatan Gupta 
4507c462acSRatan Gupta     std::copy_n(req.header.extOffset.data(), slp::header::SIZE_EXT,
46537ff140SPatrick Venture                 buff.data() + slp::header::OFFSET_EXT);
4707c462acSRatan Gupta 
4807c462acSRatan Gupta     auto xid = endian::to_network(req.header.xid);
4907c462acSRatan Gupta 
5007c462acSRatan Gupta     std::copy_n((uint8_t*)&xid, slp::header::SIZE_XID,
51537ff140SPatrick Venture                 buff.data() + slp::header::OFFSET_XID);
5207c462acSRatan Gupta 
5307c462acSRatan Gupta     uint16_t langtagLen = req.header.langtag.length();
5407c462acSRatan Gupta     langtagLen = endian::to_network(langtagLen);
5507c462acSRatan Gupta     std::copy_n((uint8_t*)&langtagLen, slp::header::SIZE_LANG,
56537ff140SPatrick Venture                 buff.data() + slp::header::OFFSET_LANG_LEN);
5707c462acSRatan Gupta 
58537ff140SPatrick Venture     std::copy_n((uint8_t*)req.header.langtag.c_str(),
59537ff140SPatrick Venture                 req.header.langtag.length(),
60537ff140SPatrick Venture                 buff.data() + slp::header::OFFSET_LANG);
6107c462acSRatan Gupta     return buff;
6207c462acSRatan Gupta }
6307c462acSRatan Gupta 
64537ff140SPatrick Venture std::tuple<int, buffer> processSrvTypeRequest(const Message& req)
6507c462acSRatan Gupta {
6607c462acSRatan Gupta     /*
6707c462acSRatan Gupta        0                   1                   2                   3
6807c462acSRatan Gupta        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
6907c462acSRatan Gupta       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
7007c462acSRatan Gupta       |      Service Location header (function = SrvTypeRply = 10)    |
7107c462acSRatan Gupta       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
7207c462acSRatan Gupta       |           Error Code          |    length of <srvType-list>   |
7307c462acSRatan Gupta       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
7407c462acSRatan Gupta       |                       <srvtype--list>                         \
7507c462acSRatan Gupta       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
7607c462acSRatan Gupta     */
7707c462acSRatan Gupta 
7807c462acSRatan Gupta     buffer buff;
7907c462acSRatan Gupta 
8007c462acSRatan Gupta     // read the slp service info from conf and create the service type string
8107c462acSRatan Gupta     slp::handler::internal::ServiceList svcList =
82ead7a3caSRatan Gupta         slp::handler::internal::readSLPServiceInfo();
8307c462acSRatan Gupta     if (svcList.size() <= 0)
8407c462acSRatan Gupta     {
8507c462acSRatan Gupta         buff.resize(0);
860d3e9e33SRatan Gupta         std::cerr << "SLP unable to read the service info\n";
8707c462acSRatan Gupta         return std::make_tuple((int)slp::Error::INTERNAL_ERROR, buff);
8807c462acSRatan Gupta     }
8907c462acSRatan Gupta 
9007c462acSRatan Gupta     std::string service;
9107c462acSRatan Gupta     bool firstIteration = true;
9207c462acSRatan Gupta     for_each(svcList.cbegin(), svcList.cend(),
93537ff140SPatrick Venture              [&service, &firstIteration](const auto& svc) {
9407c462acSRatan Gupta         if (firstIteration == true)
9507c462acSRatan Gupta         {
9607c462acSRatan Gupta             service = svc.first;
9707c462acSRatan Gupta             firstIteration = false;
9807c462acSRatan Gupta         }
9907c462acSRatan Gupta         else
10007c462acSRatan Gupta         {
10107c462acSRatan Gupta             service += ",";
10207c462acSRatan Gupta             service += svc.first;
10307c462acSRatan Gupta         }
10407c462acSRatan Gupta     });
10507c462acSRatan Gupta 
10607c462acSRatan Gupta     buff = prepareHeader(req);
10707c462acSRatan Gupta 
10807c462acSRatan Gupta     /* Need to modify the length and the function type field of the header
10907c462acSRatan Gupta      * as it is dependent on the handler of the service */
11007c462acSRatan Gupta 
11107c462acSRatan Gupta     std::cout << "service=" << service.c_str() << "\n";
11207c462acSRatan Gupta 
11307c462acSRatan Gupta     uint8_t length = buff.size() + /* 14 bytes header + length of langtag */
11407c462acSRatan Gupta                      slp::response::SIZE_ERROR +   /* 2 byte err code */
11507c462acSRatan Gupta                      slp::response::SIZE_SERVICE + /* 2 byte srvtype len */
11607c462acSRatan Gupta                      service.length();
11707c462acSRatan Gupta 
11807c462acSRatan Gupta     buff.resize(length);
11907c462acSRatan Gupta 
12007c462acSRatan Gupta     std::copy_n(&length, slp::header::SIZE_LENGTH,
121537ff140SPatrick Venture                 buff.data() + slp::header::OFFSET_LENGTH);
12207c462acSRatan Gupta 
12307c462acSRatan Gupta     /* error code is already set to 0 moving to service type len */
12407c462acSRatan Gupta 
12507c462acSRatan Gupta     uint16_t serviceTypeLen = service.length();
12607c462acSRatan Gupta     serviceTypeLen = endian::to_network(serviceTypeLen);
12707c462acSRatan Gupta 
12807c462acSRatan Gupta     std::copy_n((uint8_t*)&serviceTypeLen, slp::response::SIZE_SERVICE,
129537ff140SPatrick Venture                 buff.data() + slp::response::OFFSET_SERVICE_LEN);
13007c462acSRatan Gupta 
13107c462acSRatan Gupta     /* service type data */
13207c462acSRatan Gupta     std::copy_n((uint8_t*)service.c_str(), service.length(),
133537ff140SPatrick Venture                 (buff.data() + slp::response::OFFSET_SERVICE));
13407c462acSRatan Gupta 
13507c462acSRatan Gupta     return std::make_tuple(slp::SUCCESS, buff);
13607c462acSRatan Gupta }
13707c462acSRatan Gupta 
138537ff140SPatrick Venture std::tuple<int, buffer> processSrvRequest(const Message& req)
13907c462acSRatan Gupta {
14007c462acSRatan Gupta     /*
14107c462acSRatan Gupta           Service Reply
14207c462acSRatan Gupta           0                   1                   2                   3
14307c462acSRatan Gupta           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
14407c462acSRatan Gupta          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
14507c462acSRatan Gupta          |        Service Location header (function = SrvRply = 2)       |
14607c462acSRatan Gupta          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
14707c462acSRatan Gupta          |        Error Code             |        URL Entry count        |
14807c462acSRatan Gupta          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
14907c462acSRatan Gupta          |       <URL Entry 1>          ...       <URL Entry N>          \
15007c462acSRatan Gupta          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15107c462acSRatan Gupta 
15207c462acSRatan Gupta          URL Entry
15307c462acSRatan Gupta           0                   1                   2                   3
15407c462acSRatan Gupta           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
15507c462acSRatan Gupta          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15607c462acSRatan Gupta          |   Reserved    |          Lifetime             |   URL Length  |
15707c462acSRatan Gupta          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15807c462acSRatan Gupta          |URL len, contd.|            URL (variable length)              \
15907c462acSRatan Gupta          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16007c462acSRatan Gupta          |# of URL auths |            Auth. blocks (if any)              \
16107c462acSRatan Gupta          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16207c462acSRatan Gupta     */
16307c462acSRatan Gupta 
16407c462acSRatan Gupta     buffer buff;
16507c462acSRatan Gupta     // Get all the services which are registered
16607c462acSRatan Gupta     slp::handler::internal::ServiceList svcList =
167ead7a3caSRatan Gupta         slp::handler::internal::readSLPServiceInfo();
16807c462acSRatan Gupta     if (svcList.size() <= 0)
16907c462acSRatan Gupta     {
17007c462acSRatan Gupta         buff.resize(0);
1710d3e9e33SRatan Gupta         std::cerr << "SLP unable to read the service info\n";
17207c462acSRatan Gupta         return std::make_tuple((int)slp::Error::INTERNAL_ERROR, buff);
17307c462acSRatan Gupta     }
17407c462acSRatan Gupta 
17507c462acSRatan Gupta     // return error if serice type doesn't match
17607c462acSRatan Gupta     auto& svcName = req.body.srvrqst.srvType;
17707c462acSRatan Gupta     auto svcIt = svcList.find(svcName);
17807c462acSRatan Gupta     if (svcIt == svcList.end())
17907c462acSRatan Gupta     {
18007c462acSRatan Gupta         buff.resize(0);
1810d3e9e33SRatan Gupta         std::cerr << "SLP unable to find the service=" << svcName << "\n";
18207c462acSRatan Gupta         return std::make_tuple((int)slp::Error::INTERNAL_ERROR, buff);
18307c462acSRatan Gupta     }
18407c462acSRatan Gupta     // Get all the interface address
18507c462acSRatan Gupta     auto ifaddrList = slp::handler::internal::getIntfAddrs();
18607c462acSRatan Gupta     if (ifaddrList.size() <= 0)
18707c462acSRatan Gupta     {
18807c462acSRatan Gupta         buff.resize(0);
1890d3e9e33SRatan Gupta         std::cerr << "SLP unable to read the interface address\n";
19007c462acSRatan Gupta         return std::make_tuple((int)slp::Error::INTERNAL_ERROR, buff);
19107c462acSRatan Gupta     }
19207c462acSRatan Gupta 
19307c462acSRatan Gupta     buff = prepareHeader(req);
19407c462acSRatan Gupta     // Calculate the length and resize the buffer
19507c462acSRatan Gupta     uint8_t length = buff.size() + /* 14 bytes header + length of langtag */
19607c462acSRatan Gupta                      slp::response::SIZE_ERROR +    /* 2 bytes error code */
19707c462acSRatan Gupta                      slp::response::SIZE_URL_COUNT; /* 2 bytes srvtype len */
19807c462acSRatan Gupta 
19907c462acSRatan Gupta     buff.resize(length);
20007c462acSRatan Gupta 
20107c462acSRatan Gupta     // Populate the url count
20207c462acSRatan Gupta     uint16_t urlCount = ifaddrList.size();
20307c462acSRatan Gupta     urlCount = endian::to_network(urlCount);
20407c462acSRatan Gupta 
20507c462acSRatan Gupta     std::copy_n((uint8_t*)&urlCount, slp::response::SIZE_URL_COUNT,
206537ff140SPatrick Venture                 buff.data() + slp::response::OFFSET_URL_ENTRY);
20707c462acSRatan Gupta 
20807c462acSRatan Gupta     // Find the service
20907c462acSRatan Gupta     const slp::ConfigData& svc = svcIt->second;
2101f12e380SGunnar Mills     // Populate the URL Entries
21107c462acSRatan Gupta     auto pos = slp::response::OFFSET_URL_ENTRY + slp::response::SIZE_URL_COUNT;
21207c462acSRatan Gupta     for (const auto& addr : ifaddrList)
21307c462acSRatan Gupta     {
214*aa902c6eSPatrick Williams         std::string url = svc.name + ':' + svc.type + "//" + addr + ',' +
215*aa902c6eSPatrick Williams                           svc.port;
21607c462acSRatan Gupta 
217537ff140SPatrick Venture         buff.resize(buff.size() + slp::response::SIZE_URL_ENTRY + url.length());
21807c462acSRatan Gupta 
21907c462acSRatan Gupta         uint8_t reserved = 0;
22007c462acSRatan Gupta         uint16_t auth = 0;
22107c462acSRatan Gupta         uint16_t lifetime = endian::to_network<uint16_t>(slp::LIFETIME);
22207c462acSRatan Gupta         uint16_t urlLength = url.length();
22307c462acSRatan Gupta 
22407c462acSRatan Gupta         std::copy_n((uint8_t*)&reserved, slp::response::SIZE_RESERVED,
22507c462acSRatan Gupta                     buff.data() + pos);
22607c462acSRatan Gupta 
22707c462acSRatan Gupta         pos += slp::response::SIZE_RESERVED;
22807c462acSRatan Gupta 
22907c462acSRatan Gupta         std::copy_n((uint8_t*)&lifetime, slp::response::SIZE_LIFETIME,
23007c462acSRatan Gupta                     buff.data() + pos);
23107c462acSRatan Gupta 
23207c462acSRatan Gupta         pos += slp::response::SIZE_LIFETIME;
23307c462acSRatan Gupta 
23407c462acSRatan Gupta         urlLength = endian::to_network(urlLength);
23507c462acSRatan Gupta         std::copy_n((uint8_t*)&urlLength, slp::response::SIZE_URLLENGTH,
23607c462acSRatan Gupta                     buff.data() + pos);
23707c462acSRatan Gupta         pos += slp::response::SIZE_URLLENGTH;
23807c462acSRatan Gupta 
239537ff140SPatrick Venture         std::copy_n((uint8_t*)url.c_str(), url.length(), buff.data() + pos);
24007c462acSRatan Gupta         pos += url.length();
24107c462acSRatan Gupta 
24207c462acSRatan Gupta         std::copy_n((uint8_t*)&auth, slp::response::SIZE_AUTH,
24307c462acSRatan Gupta                     buff.data() + pos);
24407c462acSRatan Gupta         pos += slp::response::SIZE_AUTH;
24507c462acSRatan Gupta     }
24607c462acSRatan Gupta     uint8_t packetLength = buff.size();
24707c462acSRatan Gupta     std::copy_n((uint8_t*)&packetLength, slp::header::SIZE_VERSION,
248537ff140SPatrick Venture                 buff.data() + slp::header::OFFSET_LENGTH);
24907c462acSRatan Gupta 
25007c462acSRatan Gupta     return std::make_tuple((int)slp::SUCCESS, buff);
25107c462acSRatan Gupta }
25207c462acSRatan Gupta 
25307c462acSRatan Gupta std::list<std::string> getIntfAddrs()
25407c462acSRatan Gupta {
25507c462acSRatan Gupta     std::list<std::string> addrList;
25607c462acSRatan Gupta 
25707c462acSRatan Gupta     struct ifaddrs* ifaddr;
25807c462acSRatan Gupta     // attempt to fill struct with ifaddrs
25907c462acSRatan Gupta     if (getifaddrs(&ifaddr) == -1)
26007c462acSRatan Gupta     {
26107c462acSRatan Gupta         return addrList;
26207c462acSRatan Gupta     }
26307c462acSRatan Gupta 
264537ff140SPatrick Venture     slp::deleted_unique_ptr<ifaddrs> ifaddrPtr(
265537ff140SPatrick Venture         ifaddr, [](ifaddrs* addr) { freeifaddrs(addr); });
26607c462acSRatan Gupta 
26707c462acSRatan Gupta     ifaddr = nullptr;
26807c462acSRatan Gupta 
26907c462acSRatan Gupta     for (ifaddrs* ifa = ifaddrPtr.get(); ifa != nullptr; ifa = ifa->ifa_next)
27007c462acSRatan Gupta     {
27107c462acSRatan Gupta         // walk interfaces
27207c462acSRatan Gupta         if (ifa->ifa_addr == nullptr)
27307c462acSRatan Gupta         {
27407c462acSRatan Gupta             continue;
27507c462acSRatan Gupta         }
27607c462acSRatan Gupta 
27707c462acSRatan Gupta         // get only INET interfaces not ipv6
27807c462acSRatan Gupta         if (ifa->ifa_addr->sa_family == AF_INET)
27907c462acSRatan Gupta         {
28007c462acSRatan Gupta             // if loopback, or not running ignore
28107c462acSRatan Gupta             if ((ifa->ifa_flags & IFF_LOOPBACK) ||
28207c462acSRatan Gupta                 !(ifa->ifa_flags & IFF_RUNNING))
28307c462acSRatan Gupta             {
28407c462acSRatan Gupta                 continue;
28507c462acSRatan Gupta             }
28607c462acSRatan Gupta 
28707c462acSRatan Gupta             char tmp[INET_ADDRSTRLEN] = {0};
28807c462acSRatan Gupta 
28907c462acSRatan Gupta             inet_ntop(AF_INET,
290537ff140SPatrick Venture                       &(((struct sockaddr_in*)(ifa->ifa_addr))->sin_addr), tmp,
29107c462acSRatan Gupta                       sizeof(tmp));
29207c462acSRatan Gupta             addrList.emplace_back(tmp);
29307c462acSRatan Gupta         }
29407c462acSRatan Gupta     }
29507c462acSRatan Gupta 
29607c462acSRatan Gupta     return addrList;
29707c462acSRatan Gupta }
29807c462acSRatan Gupta 
299ead7a3caSRatan Gupta slp::handler::internal::ServiceList readSLPServiceInfo()
30007c462acSRatan Gupta {
30107c462acSRatan Gupta     using namespace std::string_literals;
30207c462acSRatan Gupta     slp::handler::internal::ServiceList svcLst;
30307c462acSRatan Gupta     slp::ConfigData service;
304ead7a3caSRatan Gupta     struct dirent* dent = nullptr;
305ead7a3caSRatan Gupta 
306ead7a3caSRatan Gupta     // Open the services dir and get the service info
307ead7a3caSRatan Gupta     // from service files.
308ead7a3caSRatan Gupta     // Service File format would be "ServiceName serviceType Port"
309ead7a3caSRatan Gupta     DIR* dir = opendir(SERVICE_DIR);
310ead7a3caSRatan Gupta     // wrap the pointer into smart pointer.
311537ff140SPatrick Venture     slp::deleted_unique_ptr<DIR> dirPtr(dir, [](DIR* dir) {
312ead7a3caSRatan Gupta         if (!dir)
313ead7a3caSRatan Gupta         {
314ead7a3caSRatan Gupta             closedir(dir);
315ead7a3caSRatan Gupta         }
316ead7a3caSRatan Gupta     });
317ead7a3caSRatan Gupta     dir = nullptr;
318ead7a3caSRatan Gupta 
319ead7a3caSRatan Gupta     if (dirPtr.get())
320ead7a3caSRatan Gupta     {
321ead7a3caSRatan Gupta         while ((dent = readdir(dirPtr.get())) != NULL)
322ead7a3caSRatan Gupta         {
323ead7a3caSRatan Gupta             if (dent->d_type == DT_REG) // regular file
324ead7a3caSRatan Gupta             {
325ead7a3caSRatan Gupta                 auto absFileName = std::string(SERVICE_DIR) + dent->d_name;
326ead7a3caSRatan Gupta                 std::ifstream readFile(absFileName);
327ead7a3caSRatan Gupta                 readFile >> service;
328ead7a3caSRatan Gupta                 service.name = "service:"s + service.name;
32907c462acSRatan Gupta                 svcLst.emplace(service.name, service);
33007c462acSRatan Gupta             }
331ead7a3caSRatan Gupta         }
332ead7a3caSRatan Gupta     }
33307c462acSRatan Gupta     return svcLst;
33407c462acSRatan Gupta }
33507c462acSRatan Gupta } // namespace internal
33607c462acSRatan Gupta 
337537ff140SPatrick Venture std::tuple<int, buffer> processRequest(const Message& msg)
33807c462acSRatan Gupta {
33907c462acSRatan Gupta     int rc = slp::SUCCESS;
34007c462acSRatan Gupta     buffer resp(0);
341537ff140SPatrick Venture     std::cout << "SLP Processing Request=" << msg.header.functionID << "\n";
3420d3e9e33SRatan Gupta 
343b5e632a1SBrad Bishop     switch (msg.header.functionID)
344b5e632a1SBrad Bishop     {
34507c462acSRatan Gupta         case (uint8_t)slp::FunctionType::SRVTYPERQST:
346*aa902c6eSPatrick Williams             std::tie(rc,
347*aa902c6eSPatrick Williams                      resp) = slp::handler::internal::processSrvTypeRequest(msg);
34807c462acSRatan Gupta             break;
34907c462acSRatan Gupta         case (uint8_t)slp::FunctionType::SRVRQST:
35007c462acSRatan Gupta             std::tie(rc, resp) = slp::handler::internal::processSrvRequest(msg);
35107c462acSRatan Gupta             break;
35207c462acSRatan Gupta         default:
35307c462acSRatan Gupta             rc = (uint8_t)slp::Error::MSG_NOT_SUPPORTED;
35407c462acSRatan Gupta     }
35507c462acSRatan Gupta     return std::make_tuple(rc, resp);
35607c462acSRatan Gupta }
35707c462acSRatan Gupta 
358537ff140SPatrick Venture buffer processError(const Message& req, uint8_t err)
35907c462acSRatan Gupta {
36007c462acSRatan Gupta     buffer buff;
36107c462acSRatan Gupta     buff = slp::handler::internal::prepareHeader(req);
36207c462acSRatan Gupta 
36307c462acSRatan Gupta     std::copy_n(&err, slp::response::SIZE_ERROR,
364537ff140SPatrick Venture                 buff.data() + slp::response::OFFSET_ERROR);
36507c462acSRatan Gupta     return buff;
36607c462acSRatan Gupta }
36707c462acSRatan Gupta } // namespace handler
36807c462acSRatan Gupta } // namespace slp
369