1 #include "endian.hpp" 2 #include "slp.hpp" 3 #include "slp_meta.hpp" 4 5 #include <string.h> 6 7 #include <algorithm> 8 #include <string> 9 10 namespace slp 11 { 12 13 namespace parser 14 { 15 16 namespace internal 17 { 18 19 std::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 33 Message req{}; 34 int rc = slp::SUCCESS; 35 36 if (buff.size() < slp::header::MIN_LEN) 37 { 38 std::cerr << "Invalid msg size: " << buff.size() << std::endl; 39 rc = static_cast<int>(slp::Error::PARSE_ERROR); 40 } 41 else 42 { 43 std::copy_n(buff.data(), slp::header::SIZE_VERSION, 44 &req.header.version); 45 46 std::copy_n(buff.data() + slp::header::OFFSET_FUNCTION, 47 slp::header::SIZE_VERSION, &req.header.functionID); 48 49 std::copy_n(buff.data() + slp::header::OFFSET_LENGTH, 50 slp::header::SIZE_LENGTH, req.header.length.data()); 51 52 std::copy_n(buff.data() + slp::header::OFFSET_FLAGS, 53 slp::header::SIZE_FLAGS, (uint8_t*)&req.header.flags); 54 55 req.header.flags = endian::from_network(req.header.flags); 56 std::copy_n(buff.data() + slp::header::OFFSET_EXT, 57 slp::header::SIZE_EXT, req.header.extOffset.data()); 58 59 std::copy_n(buff.data() + slp::header::OFFSET_XID, 60 slp::header::SIZE_XID, (uint8_t*)&req.header.xid); 61 62 req.header.xid = endian::from_network(req.header.xid); 63 64 uint16_t langtagLen; 65 66 std::copy_n(buff.data() + slp::header::OFFSET_LANG_LEN, 67 slp::header::SIZE_LANG, (uint8_t*)&langtagLen); 68 69 langtagLen = endian::from_network(langtagLen); 70 71 req.header.langtag.insert( 72 0, (const char*)buff.data() + slp::header::OFFSET_LANG, langtagLen); 73 74 /* check for the validity of the function */ 75 if (req.header.functionID < 76 static_cast<uint8_t>(slp::FunctionType::SRVRQST) || 77 req.header.functionID > 78 static_cast<uint8_t>(slp::FunctionType::SAADV)) 79 { 80 std::cerr << "Invalid function ID: " << req.header.functionID 81 << std::endl; 82 rc = static_cast<int>(slp::Error::PARSE_ERROR); 83 } 84 } 85 86 return std::make_tuple(rc, std::move(req)); 87 } 88 89 int parseSrvTypeRqst(const buffer& buff, Message& req) 90 { 91 /* 0 1 2 3 92 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 93 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 94 | length of PRList | <PRList> String \ 95 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 96 | length of Naming Authority | <Naming Authority String> \ 97 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 98 | length of <scope-list> | <scope-list> String \ 99 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ 100 101 /* Enforce SLPv2 service type request size limits. */ 102 if (buff.size() < slp::request::MIN_SRVTYPE_LEN) 103 { 104 return (int)slp::Error::PARSE_ERROR; 105 } 106 107 /* Parse the PRList. */ 108 uint16_t prListLen; 109 std::copy_n(buff.data() + slp::request::OFFSET_PR_LEN, 110 slp::request::SIZE_PRLIST, (uint8_t*)&prListLen); 111 112 prListLen = endian::from_network(prListLen); 113 114 req.body.srvtyperqst.prList.insert( 115 0, (const char*)buff.data() + slp::request::OFFSET_PR, prListLen); 116 117 uint8_t pos = slp::request::OFFSET_PR + prListLen; 118 119 /* Parse the Naming Authority. */ 120 uint16_t namingAuthLen; 121 std::copy_n(buff.data() + pos, slp::request::SIZE_NAMING, 122 (uint8_t*)&namingAuthLen); 123 124 pos += slp::request::SIZE_NAMING; 125 126 namingAuthLen = endian::from_network(namingAuthLen); 127 128 if (namingAuthLen == 0 || namingAuthLen == 0xffff) 129 { 130 req.body.srvtyperqst.namingAuth = ""; 131 } 132 else 133 { 134 req.body.srvtyperqst.namingAuth.insert( 135 0, (const char*)buff.data() + pos, namingAuthLen); 136 } 137 138 pos += namingAuthLen; 139 140 /* Parse the <scope-list>. */ 141 uint16_t scopeListLen; 142 std::copy_n(buff.data() + pos, slp::request::SIZE_SCOPE, 143 (uint8_t*)&scopeListLen); 144 145 pos += slp::request::SIZE_SCOPE; 146 147 scopeListLen = endian::from_network(scopeListLen); 148 149 req.body.srvtyperqst.scopeList.insert(0, (const char*)buff.data() + pos, 150 scopeListLen); 151 152 return slp::SUCCESS; 153 } 154 155 int parseSrvRqst(const buffer& buff, Message& req) 156 { 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 | length of <PRList> | <PRList> String \ 161 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 162 | length of <service-type> | <service-type> String \ 163 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 164 | length of <scope-list> | <scope-list> String \ 165 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 166 | length of predicate string | Service Request <predicate> \ 167 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 168 | length of <SLP SPI> string | <SLP SPI> String \ 169 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ 170 171 /* Enforce v2 service request size limits. */ 172 if (buff.size() < slp::request::MIN_SRV_LEN) 173 { 174 return (int)slp::Error::PARSE_ERROR; 175 } 176 177 /* 1) Parse the PRList. */ 178 uint16_t prListLen; 179 std::copy_n(buff.data() + slp::request::OFFSET_PR_LEN, 180 slp::request::SIZE_PRLIST, (uint8_t*)&prListLen); 181 182 auto pos = slp::request::OFFSET_PR_LEN + slp::request::SIZE_PRLIST; 183 184 prListLen = endian::from_network(prListLen); 185 186 req.body.srvrqst.prList.insert(0, (const char*)buff.data() + pos, 187 prListLen); 188 189 pos += prListLen; 190 191 /* 2) Parse the <service-type> string. */ 192 uint16_t srvTypeLen; 193 std::copy_n(buff.data() + pos, slp::request::SIZE_SERVICE_TYPE, 194 (uint8_t*)&srvTypeLen); 195 196 srvTypeLen = endian::from_network(srvTypeLen); 197 198 pos += slp::request::SIZE_SERVICE_TYPE; 199 200 req.body.srvrqst.srvType.insert(0, (const char*)buff.data() + pos, 201 srvTypeLen); 202 203 pos += srvTypeLen; 204 205 /* 3) Parse the <scope-list> string. */ 206 uint16_t scopeListLen; 207 std::copy_n(buff.data() + pos, slp::request::SIZE_SCOPE, 208 (uint8_t*)&scopeListLen); 209 210 scopeListLen = endian::from_network(scopeListLen); 211 212 pos += slp::request::SIZE_SCOPE; 213 214 req.body.srvrqst.scopeList.insert(0, (const char*)buff.data() + pos, 215 scopeListLen); 216 217 pos += scopeListLen; 218 219 /* 4) Parse the <predicate> string. */ 220 uint16_t predicateLen; 221 std::copy_n(buff.data() + pos, slp::request::SIZE_PREDICATE, 222 (uint8_t*)&predicateLen); 223 224 predicateLen = endian::from_network(predicateLen); 225 pos += slp::request::SIZE_PREDICATE; 226 227 req.body.srvrqst.predicate.insert(0, (const char*)buff.data() + pos, 228 predicateLen); 229 230 pos += predicateLen; 231 232 /* 5) Parse the <SLP SPI> string. */ 233 uint16_t spistrLen; 234 std::copy_n(buff.data() + pos, slp::request::SIZE_SLPI, 235 (uint8_t*)&spistrLen); 236 237 spistrLen = endian::from_network(spistrLen); 238 pos += slp::request::SIZE_SLPI; 239 240 req.body.srvrqst.spistr.insert(0, (const char*)buff.data() + pos, 241 spistrLen); 242 243 return slp::SUCCESS; 244 } 245 } // namespace internal 246 247 std::tuple<int, Message> parseBuffer(const buffer& buff) 248 { 249 Message req; 250 int rc = slp::SUCCESS; 251 /* parse the header first */ 252 std::tie(rc, req) = internal::parseHeader(buff); 253 if (!rc) 254 { 255 /* switch on the function id to parse the body */ 256 switch (req.header.functionID) 257 { 258 case (uint8_t)slp::FunctionType::SRVTYPERQST: 259 rc = internal::parseSrvTypeRqst(buff, req); 260 break; 261 case (uint8_t)slp::FunctionType::SRVRQST: 262 rc = internal::parseSrvRqst(buff, req); 263 break; 264 default: 265 rc = (int)slp::Error::MSG_NOT_SUPPORTED; 266 } 267 } 268 return std::make_tuple(rc, std::move(req)); 269 } 270 } // namespace parser 271 } // namespace slp 272