1537ff140SPatrick Venture #include "endian.hpp"
207c462acSRatan Gupta #include "slp.hpp"
3537ff140SPatrick Venture #include "slp_meta.hpp"
407c462acSRatan Gupta 
507c462acSRatan Gupta #include <arpa/inet.h>
6ead7a3caSRatan Gupta #include <dirent.h>
707c462acSRatan Gupta #include <ifaddrs.h>
807c462acSRatan Gupta #include <net/if.h>
907c462acSRatan Gupta #include <string.h>
1007c462acSRatan Gupta 
1107c462acSRatan Gupta #include <algorithm>
1207c462acSRatan Gupta 
1307c462acSRatan Gupta namespace slp
1407c462acSRatan Gupta {
1507c462acSRatan Gupta namespace handler
1607c462acSRatan Gupta {
1707c462acSRatan Gupta 
1807c462acSRatan Gupta namespace internal
1907c462acSRatan Gupta {
2007c462acSRatan Gupta 
21f93142e8SPatrick Williams static constexpr auto SERVICE_DIR = "/etc/slp/services/";
22f93142e8SPatrick Williams 
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 
113*eebd0815SAndrew Geissler     // See if total response size exceeds our max
114*eebd0815SAndrew Geissler     uint32_t totalLength =
115*eebd0815SAndrew Geissler         buff.size() +                 /* 14 bytes header + length of langtag */
116*eebd0815SAndrew Geissler         slp::response::SIZE_ERROR +   /* 2 byte err code */
117*eebd0815SAndrew Geissler         slp::response::SIZE_SERVICE + /* 2 byte srvtype len */
118*eebd0815SAndrew Geissler         service.length();
119*eebd0815SAndrew Geissler     if (totalLength > slp::MAX_LEN)
120*eebd0815SAndrew Geissler     {
121*eebd0815SAndrew Geissler         std::cerr << "Message response size exceeds maximum allowed: "
122*eebd0815SAndrew Geissler                   << totalLength << " / " << slp::MAX_LEN << std::endl;
123*eebd0815SAndrew Geissler         buff.resize(0);
124*eebd0815SAndrew Geissler         return std::make_tuple((int)slp::Error::PARSE_ERROR, buff);
125*eebd0815SAndrew Geissler     }
126*eebd0815SAndrew Geissler 
12707c462acSRatan Gupta     uint8_t length = buff.size() + /* 14 bytes header + length of langtag */
12807c462acSRatan Gupta                      slp::response::SIZE_ERROR +   /* 2 byte err code */
12907c462acSRatan Gupta                      slp::response::SIZE_SERVICE + /* 2 byte srvtype len */
13007c462acSRatan Gupta                      service.length();
13107c462acSRatan Gupta 
13207c462acSRatan Gupta     buff.resize(length);
13307c462acSRatan Gupta 
13407c462acSRatan Gupta     std::copy_n(&length, slp::header::SIZE_LENGTH,
135537ff140SPatrick Venture                 buff.data() + slp::header::OFFSET_LENGTH);
13607c462acSRatan Gupta 
13707c462acSRatan Gupta     /* error code is already set to 0 moving to service type len */
13807c462acSRatan Gupta 
13907c462acSRatan Gupta     uint16_t serviceTypeLen = service.length();
14007c462acSRatan Gupta     serviceTypeLen = endian::to_network(serviceTypeLen);
14107c462acSRatan Gupta 
14207c462acSRatan Gupta     std::copy_n((uint8_t*)&serviceTypeLen, slp::response::SIZE_SERVICE,
143537ff140SPatrick Venture                 buff.data() + slp::response::OFFSET_SERVICE_LEN);
14407c462acSRatan Gupta 
14507c462acSRatan Gupta     /* service type data */
14607c462acSRatan Gupta     std::copy_n((uint8_t*)service.c_str(), service.length(),
147537ff140SPatrick Venture                 (buff.data() + slp::response::OFFSET_SERVICE));
14807c462acSRatan Gupta 
14907c462acSRatan Gupta     return std::make_tuple(slp::SUCCESS, buff);
15007c462acSRatan Gupta }
15107c462acSRatan Gupta 
152537ff140SPatrick Venture std::tuple<int, buffer> processSrvRequest(const Message& req)
15307c462acSRatan Gupta {
15407c462acSRatan Gupta     /*
15507c462acSRatan Gupta           Service Reply
15607c462acSRatan Gupta           0                   1                   2                   3
15707c462acSRatan 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
15807c462acSRatan Gupta          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15907c462acSRatan Gupta          |        Service Location header (function = SrvRply = 2)       |
16007c462acSRatan Gupta          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16107c462acSRatan Gupta          |        Error Code             |        URL Entry count        |
16207c462acSRatan Gupta          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16307c462acSRatan Gupta          |       <URL Entry 1>          ...       <URL Entry N>          \
16407c462acSRatan Gupta          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16507c462acSRatan Gupta 
16607c462acSRatan Gupta          URL Entry
16707c462acSRatan Gupta           0                   1                   2                   3
16807c462acSRatan 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
16907c462acSRatan Gupta          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17007c462acSRatan Gupta          |   Reserved    |          Lifetime             |   URL Length  |
17107c462acSRatan Gupta          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17207c462acSRatan Gupta          |URL len, contd.|            URL (variable length)              \
17307c462acSRatan Gupta          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17407c462acSRatan Gupta          |# of URL auths |            Auth. blocks (if any)              \
17507c462acSRatan Gupta          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17607c462acSRatan Gupta     */
17707c462acSRatan Gupta 
17807c462acSRatan Gupta     buffer buff;
17907c462acSRatan Gupta     // Get all the services which are registered
18007c462acSRatan Gupta     slp::handler::internal::ServiceList svcList =
181ead7a3caSRatan Gupta         slp::handler::internal::readSLPServiceInfo();
18207c462acSRatan Gupta     if (svcList.size() <= 0)
18307c462acSRatan Gupta     {
18407c462acSRatan Gupta         buff.resize(0);
1850d3e9e33SRatan Gupta         std::cerr << "SLP unable to read the service info\n";
18607c462acSRatan Gupta         return std::make_tuple((int)slp::Error::INTERNAL_ERROR, buff);
18707c462acSRatan Gupta     }
18807c462acSRatan Gupta 
18907c462acSRatan Gupta     // return error if serice type doesn't match
19007c462acSRatan Gupta     auto& svcName = req.body.srvrqst.srvType;
19107c462acSRatan Gupta     auto svcIt = svcList.find(svcName);
19207c462acSRatan Gupta     if (svcIt == svcList.end())
19307c462acSRatan Gupta     {
19407c462acSRatan Gupta         buff.resize(0);
1950d3e9e33SRatan Gupta         std::cerr << "SLP unable to find the service=" << svcName << "\n";
19607c462acSRatan Gupta         return std::make_tuple((int)slp::Error::INTERNAL_ERROR, buff);
19707c462acSRatan Gupta     }
19807c462acSRatan Gupta     // Get all the interface address
19907c462acSRatan Gupta     auto ifaddrList = slp::handler::internal::getIntfAddrs();
20007c462acSRatan Gupta     if (ifaddrList.size() <= 0)
20107c462acSRatan Gupta     {
20207c462acSRatan Gupta         buff.resize(0);
2030d3e9e33SRatan Gupta         std::cerr << "SLP unable to read the interface address\n";
20407c462acSRatan Gupta         return std::make_tuple((int)slp::Error::INTERNAL_ERROR, buff);
20507c462acSRatan Gupta     }
20607c462acSRatan Gupta 
20707c462acSRatan Gupta     buff = prepareHeader(req);
20807c462acSRatan Gupta     // Calculate the length and resize the buffer
20907c462acSRatan Gupta     uint8_t length = buff.size() + /* 14 bytes header + length of langtag */
21007c462acSRatan Gupta                      slp::response::SIZE_ERROR +    /* 2 bytes error code */
21107c462acSRatan Gupta                      slp::response::SIZE_URL_COUNT; /* 2 bytes srvtype len */
21207c462acSRatan Gupta 
21307c462acSRatan Gupta     buff.resize(length);
21407c462acSRatan Gupta 
21507c462acSRatan Gupta     // Populate the url count
21607c462acSRatan Gupta     uint16_t urlCount = ifaddrList.size();
21707c462acSRatan Gupta     urlCount = endian::to_network(urlCount);
21807c462acSRatan Gupta 
21907c462acSRatan Gupta     std::copy_n((uint8_t*)&urlCount, slp::response::SIZE_URL_COUNT,
220537ff140SPatrick Venture                 buff.data() + slp::response::OFFSET_URL_ENTRY);
22107c462acSRatan Gupta 
22207c462acSRatan Gupta     // Find the service
22307c462acSRatan Gupta     const slp::ConfigData& svc = svcIt->second;
2241f12e380SGunnar Mills     // Populate the URL Entries
22507c462acSRatan Gupta     auto pos = slp::response::OFFSET_URL_ENTRY + slp::response::SIZE_URL_COUNT;
22607c462acSRatan Gupta     for (const auto& addr : ifaddrList)
22707c462acSRatan Gupta     {
228aa902c6eSPatrick Williams         std::string url = svc.name + ':' + svc.type + "//" + addr + ',' +
229aa902c6eSPatrick Williams                           svc.port;
23007c462acSRatan Gupta 
231*eebd0815SAndrew Geissler         // See if total response size exceeds our max
232*eebd0815SAndrew Geissler         uint32_t totalLength = buff.size() + slp::response::SIZE_URL_ENTRY +
233*eebd0815SAndrew Geissler                                url.length();
234*eebd0815SAndrew Geissler         if (totalLength > slp::MAX_LEN)
235*eebd0815SAndrew Geissler         {
236*eebd0815SAndrew Geissler             std::cerr << "Message response size exceeds maximum allowed: "
237*eebd0815SAndrew Geissler                       << totalLength << " / " << slp::MAX_LEN << std::endl;
238*eebd0815SAndrew Geissler             buff.resize(0);
239*eebd0815SAndrew Geissler             return std::make_tuple((int)slp::Error::PARSE_ERROR, buff);
240*eebd0815SAndrew Geissler         }
241*eebd0815SAndrew Geissler 
242537ff140SPatrick Venture         buff.resize(buff.size() + slp::response::SIZE_URL_ENTRY + url.length());
24307c462acSRatan Gupta 
24407c462acSRatan Gupta         uint8_t reserved = 0;
24507c462acSRatan Gupta         uint16_t auth = 0;
24607c462acSRatan Gupta         uint16_t lifetime = endian::to_network<uint16_t>(slp::LIFETIME);
24707c462acSRatan Gupta         uint16_t urlLength = url.length();
24807c462acSRatan Gupta 
24907c462acSRatan Gupta         std::copy_n((uint8_t*)&reserved, slp::response::SIZE_RESERVED,
25007c462acSRatan Gupta                     buff.data() + pos);
25107c462acSRatan Gupta 
25207c462acSRatan Gupta         pos += slp::response::SIZE_RESERVED;
25307c462acSRatan Gupta 
25407c462acSRatan Gupta         std::copy_n((uint8_t*)&lifetime, slp::response::SIZE_LIFETIME,
25507c462acSRatan Gupta                     buff.data() + pos);
25607c462acSRatan Gupta 
25707c462acSRatan Gupta         pos += slp::response::SIZE_LIFETIME;
25807c462acSRatan Gupta 
25907c462acSRatan Gupta         urlLength = endian::to_network(urlLength);
26007c462acSRatan Gupta         std::copy_n((uint8_t*)&urlLength, slp::response::SIZE_URLLENGTH,
26107c462acSRatan Gupta                     buff.data() + pos);
26207c462acSRatan Gupta         pos += slp::response::SIZE_URLLENGTH;
26307c462acSRatan Gupta 
264537ff140SPatrick Venture         std::copy_n((uint8_t*)url.c_str(), url.length(), buff.data() + pos);
26507c462acSRatan Gupta         pos += url.length();
26607c462acSRatan Gupta 
26707c462acSRatan Gupta         std::copy_n((uint8_t*)&auth, slp::response::SIZE_AUTH,
26807c462acSRatan Gupta                     buff.data() + pos);
26907c462acSRatan Gupta         pos += slp::response::SIZE_AUTH;
27007c462acSRatan Gupta     }
27107c462acSRatan Gupta     uint8_t packetLength = buff.size();
27207c462acSRatan Gupta     std::copy_n((uint8_t*)&packetLength, slp::header::SIZE_VERSION,
273537ff140SPatrick Venture                 buff.data() + slp::header::OFFSET_LENGTH);
27407c462acSRatan Gupta 
27507c462acSRatan Gupta     return std::make_tuple((int)slp::SUCCESS, buff);
27607c462acSRatan Gupta }
27707c462acSRatan Gupta 
27807c462acSRatan Gupta std::list<std::string> getIntfAddrs()
27907c462acSRatan Gupta {
28007c462acSRatan Gupta     std::list<std::string> addrList;
28107c462acSRatan Gupta 
28207c462acSRatan Gupta     struct ifaddrs* ifaddr;
28307c462acSRatan Gupta     // attempt to fill struct with ifaddrs
28407c462acSRatan Gupta     if (getifaddrs(&ifaddr) == -1)
28507c462acSRatan Gupta     {
28607c462acSRatan Gupta         return addrList;
28707c462acSRatan Gupta     }
28807c462acSRatan Gupta 
289537ff140SPatrick Venture     slp::deleted_unique_ptr<ifaddrs> ifaddrPtr(
290537ff140SPatrick Venture         ifaddr, [](ifaddrs* addr) { freeifaddrs(addr); });
29107c462acSRatan Gupta 
29207c462acSRatan Gupta     ifaddr = nullptr;
29307c462acSRatan Gupta 
29407c462acSRatan Gupta     for (ifaddrs* ifa = ifaddrPtr.get(); ifa != nullptr; ifa = ifa->ifa_next)
29507c462acSRatan Gupta     {
29607c462acSRatan Gupta         // walk interfaces
29707c462acSRatan Gupta         if (ifa->ifa_addr == nullptr)
29807c462acSRatan Gupta         {
29907c462acSRatan Gupta             continue;
30007c462acSRatan Gupta         }
30107c462acSRatan Gupta 
30207c462acSRatan Gupta         // get only INET interfaces not ipv6
30307c462acSRatan Gupta         if (ifa->ifa_addr->sa_family == AF_INET)
30407c462acSRatan Gupta         {
30507c462acSRatan Gupta             // if loopback, or not running ignore
30607c462acSRatan Gupta             if ((ifa->ifa_flags & IFF_LOOPBACK) ||
30707c462acSRatan Gupta                 !(ifa->ifa_flags & IFF_RUNNING))
30807c462acSRatan Gupta             {
30907c462acSRatan Gupta                 continue;
31007c462acSRatan Gupta             }
31107c462acSRatan Gupta 
31207c462acSRatan Gupta             char tmp[INET_ADDRSTRLEN] = {0};
31307c462acSRatan Gupta 
31407c462acSRatan Gupta             inet_ntop(AF_INET,
315537ff140SPatrick Venture                       &(((struct sockaddr_in*)(ifa->ifa_addr))->sin_addr), tmp,
31607c462acSRatan Gupta                       sizeof(tmp));
31707c462acSRatan Gupta             addrList.emplace_back(tmp);
31807c462acSRatan Gupta         }
31907c462acSRatan Gupta     }
32007c462acSRatan Gupta 
32107c462acSRatan Gupta     return addrList;
32207c462acSRatan Gupta }
32307c462acSRatan Gupta 
324ead7a3caSRatan Gupta slp::handler::internal::ServiceList readSLPServiceInfo()
32507c462acSRatan Gupta {
32607c462acSRatan Gupta     using namespace std::string_literals;
32707c462acSRatan Gupta     slp::handler::internal::ServiceList svcLst;
32807c462acSRatan Gupta     slp::ConfigData service;
329ead7a3caSRatan Gupta     struct dirent* dent = nullptr;
330ead7a3caSRatan Gupta 
331ead7a3caSRatan Gupta     // Open the services dir and get the service info
332ead7a3caSRatan Gupta     // from service files.
333ead7a3caSRatan Gupta     // Service File format would be "ServiceName serviceType Port"
334ead7a3caSRatan Gupta     DIR* dir = opendir(SERVICE_DIR);
335ead7a3caSRatan Gupta     // wrap the pointer into smart pointer.
336537ff140SPatrick Venture     slp::deleted_unique_ptr<DIR> dirPtr(dir, [](DIR* dir) {
337ead7a3caSRatan Gupta         if (!dir)
338ead7a3caSRatan Gupta         {
339ead7a3caSRatan Gupta             closedir(dir);
340ead7a3caSRatan Gupta         }
341ead7a3caSRatan Gupta     });
342ead7a3caSRatan Gupta     dir = nullptr;
343ead7a3caSRatan Gupta 
344ead7a3caSRatan Gupta     if (dirPtr.get())
345ead7a3caSRatan Gupta     {
346ead7a3caSRatan Gupta         while ((dent = readdir(dirPtr.get())) != NULL)
347ead7a3caSRatan Gupta         {
348ead7a3caSRatan Gupta             if (dent->d_type == DT_REG) // regular file
349ead7a3caSRatan Gupta             {
350ead7a3caSRatan Gupta                 auto absFileName = std::string(SERVICE_DIR) + dent->d_name;
351ead7a3caSRatan Gupta                 std::ifstream readFile(absFileName);
352ead7a3caSRatan Gupta                 readFile >> service;
353ead7a3caSRatan Gupta                 service.name = "service:"s + service.name;
35407c462acSRatan Gupta                 svcLst.emplace(service.name, service);
35507c462acSRatan Gupta             }
356ead7a3caSRatan Gupta         }
357ead7a3caSRatan Gupta     }
35807c462acSRatan Gupta     return svcLst;
35907c462acSRatan Gupta }
36007c462acSRatan Gupta } // namespace internal
36107c462acSRatan Gupta 
362537ff140SPatrick Venture std::tuple<int, buffer> processRequest(const Message& msg)
36307c462acSRatan Gupta {
36407c462acSRatan Gupta     int rc = slp::SUCCESS;
36507c462acSRatan Gupta     buffer resp(0);
366537ff140SPatrick Venture     std::cout << "SLP Processing Request=" << msg.header.functionID << "\n";
3670d3e9e33SRatan Gupta 
368b5e632a1SBrad Bishop     switch (msg.header.functionID)
369b5e632a1SBrad Bishop     {
37007c462acSRatan Gupta         case (uint8_t)slp::FunctionType::SRVTYPERQST:
371aa902c6eSPatrick Williams             std::tie(rc,
372aa902c6eSPatrick Williams                      resp) = slp::handler::internal::processSrvTypeRequest(msg);
37307c462acSRatan Gupta             break;
37407c462acSRatan Gupta         case (uint8_t)slp::FunctionType::SRVRQST:
37507c462acSRatan Gupta             std::tie(rc, resp) = slp::handler::internal::processSrvRequest(msg);
37607c462acSRatan Gupta             break;
37707c462acSRatan Gupta         default:
37807c462acSRatan Gupta             rc = (uint8_t)slp::Error::MSG_NOT_SUPPORTED;
37907c462acSRatan Gupta     }
38007c462acSRatan Gupta     return std::make_tuple(rc, resp);
38107c462acSRatan Gupta }
38207c462acSRatan Gupta 
383537ff140SPatrick Venture buffer processError(const Message& req, uint8_t err)
38407c462acSRatan Gupta {
38507c462acSRatan Gupta     buffer buff;
38607c462acSRatan Gupta     buff = slp::handler::internal::prepareHeader(req);
38707c462acSRatan Gupta 
388edf88cb2SPatrick Williams     static_assert(sizeof(err) == 1, "Errors should be 1 byte.");
389edf88cb2SPatrick Williams 
390edf88cb2SPatrick Williams     // Since this is network order, the err should go in the 2nd byte of the
391edf88cb2SPatrick Williams     // error field.  This is immediately after the langtag.
392edf88cb2SPatrick Williams     buff[slp::header::MIN_LEN + req.header.langtag.length() + 1] = err;
393edf88cb2SPatrick Williams 
39407c462acSRatan Gupta     return buff;
39507c462acSRatan Gupta }
39607c462acSRatan Gupta } // namespace handler
39707c462acSRatan Gupta } // namespace slp
398