Changeset 79568 in vbox for trunk/src/VBox/NetworkServices/Dhcpd/Db.cpp
- Timestamp:
- Jul 6, 2019 11:42:51 PM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 131858
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/NetworkServices/Dhcpd/Db.cpp
r79563 r79568 159 159 * Serializes the binding to XML for the lease database. 160 160 * 161 * @throw std::bad_alloc 161 * @throw std::bad_alloc 162 * @note DHCPServerImpl.cpp contains a reader, keep it in sync. 162 163 */ 163 164 void Binding::toXML(xml::ElementNode *pElmParent) const … … 204 205 * Deserializes the binding from the XML lease database. 205 206 * 206 * @param pElmLease The "Lease" element .207 * @param pElmLease The "Lease" element to serialize into. 207 208 * @return Pointer to the resulting binding, NULL on failure. 208 209 * @throw std::bad_alloc 210 * @note DHCPServerImpl.cpp contains a similar reader, keep it in sync. 209 211 */ 210 212 Binding *Binding::fromXML(const xml::ElementNode *pElmLease) 211 213 { 212 /* Lease/@network seems to always have bogus value, ignore it. */ 213 214 /* 215 * Lease/@mac 216 */ 217 RTCString strMac; 218 bool fHasMac = pElmLease->getAttributeValue("mac", &strMac); 219 if (!fHasMac) 220 return NULL; 214 /* Note! Lease/@network seems to always have bogus value, ignore it. */ 215 /* Note! We parse the mandatory attributes and elements first, then 216 the optional ones. This means things appear a little jumbled. */ 217 218 /* 219 * Lease/@mac - mandatory. 220 */ 221 const char *pszMacAddress = pElmLease->findAttributeValue("mac"); 222 if (!pszMacAddress) 223 DHCP_LOG_RET_NULL(("Binding::fromXML: <Lease> element without 'mac' attribute! Skipping lease.\n")); 221 224 222 225 RTMAC mac; 223 int rc = RTNetStrToMacAddr( strMac.c_str(), &mac);226 int rc = RTNetStrToMacAddr(pszMacAddress, &mac); 224 227 if (RT_FAILURE(rc)) 225 return NULL; 226 227 OptClientId id; 228 RTCString strId; 229 bool fHasId = pElmLease->getAttributeValue("id", &strId); 230 if (fHasId) 231 { 232 /* 233 * Decode from "de:ad:be:ef". 234 */ 235 /** @todo RTStrConvertHexBytes() doesn't grok colons */ 236 size_t cbBytes = strId.length() / 2; 237 uint8_t *pbBytes = new uint8_t[cbBytes]; 238 rc = RTStrConvertHexBytes(strId.c_str(), pbBytes, cbBytes, 0); 239 if (RT_SUCCESS(rc)) 240 { 241 try 242 { 243 std::vector<uint8_t> rawopt(pbBytes, pbBytes + cbBytes); 244 id = OptClientId(rawopt); 245 } 246 catch (std::bad_alloc &) 247 { 248 delete[] pbBytes; 249 throw; 250 } 251 } 252 delete[] pbBytes; 253 } 254 255 /* 256 * Lease/@state - not present in old leases file. We will try to 257 * infer from lease time below. 258 */ 259 RTCString strState; 260 bool fHasState = pElmLease->getAttributeValue("state", &strState); 261 262 /* 263 * Lease/Address 264 */ 265 const xml::ElementNode *ndAddress = pElmLease->findChildElement("Address"); 266 if (ndAddress == NULL) 267 return NULL; 268 269 /* 270 * Lease/Address/@value 271 */ 272 RTCString strAddress; 273 bool fHasValue = ndAddress->getAttributeValue("value", &strAddress); 274 if (!fHasValue) 275 return NULL; 228 DHCP_LOG_RET_NULL(("Binding::fromXML: Malformed mac address attribute value '%s': %Rrc - Skipping lease.\n", 229 pszMacAddress, rc)); 230 231 /* 232 * Lease/Address/@value - mandatory. 233 */ 234 const char *pszAddress = pElmLease->findChildElementAttributeValue("Address", "value"); 235 if (!pszAddress) 236 DHCP_LOG_RET_NULL(("Binding::fromXML: Could not find <Address> with a 'value' attribute! Skipping lease.\n")); 276 237 277 238 RTNETADDRIPV4 addr; 278 rc = RTNetStrToIPv4Addr( strAddress.c_str(), &addr);239 rc = RTNetStrToIPv4Addr(pszAddress, &addr); 279 240 if (RT_FAILURE(rc)) 280 return NULL; 281 282 /* 283 * Lease/Time 284 */ 285 const xml::ElementNode *ndTime = pElmLease->findChildElement("Time"); 286 if (ndTime == NULL) 287 return NULL; 288 289 /* 290 * Lease/Time/@issued 291 */ 292 int64_t issued; 293 bool fHasIssued = ndTime->getAttributeValue("issued", &issued); 294 if (!fHasIssued) 295 return NULL; 296 297 /* 298 * Lease/Time/@expiration 299 */ 300 uint32_t duration; 301 bool fHasExpiration = ndTime->getAttributeValue("expiration", &duration); 302 if (!fHasExpiration) 303 return NULL; 241 DHCP_LOG_RET_NULL(("Binding::fromXML: Malformed IPv4 address value '%s': %Rrc - Skipping lease.\n", pszAddress, rc)); 242 243 /* 244 * Lease/Time - mandatory. 245 */ 246 const xml::ElementNode *pElmTime = pElmLease->findChildElement("Time"); 247 if (pElmTime == NULL) 248 DHCP_LOG_RET_NULL(("Binding::fromXML: No <Time> element under <Lease mac=%RTmac>! Skipping lease.\n", &mac)); 249 250 /* 251 * Lease/Time/@issued - mandatory. 252 */ 253 int64_t secIssued; 254 if (!pElmTime->getAttributeValue("issued", &secIssued)) 255 DHCP_LOG_RET_NULL(("Binding::fromXML: <Time> element for %RTmac has no valid 'issued' attribute! Skipping lease.\n", &mac)); 256 257 /* 258 * Lease/Time/@expiration - mandatory. 259 */ 260 uint32_t cSecToLive; 261 if (!pElmTime->getAttributeValue("expiration", &cSecToLive)) 262 DHCP_LOG_RET_NULL(("Binding::fromXML: <Time> element for %RTmac has no valid 'expiration' attribute! Skipping lease.\n", &mac)); 304 263 305 264 std::unique_ptr<Binding> b(new Binding(addr)); 306 b->m_id = ClientId(mac, id); 307 308 if (fHasState) 309 { 310 b->m_issued = Timestamp::absSeconds(issued); 311 b->m_secLease = duration; 312 b->setState(strState.c_str()); 265 266 /* 267 * Lease/@state - mandatory but not present in old leases file, so pretent 268 * we're loading an expired one if absent. 269 */ 270 const char *pszState = pElmLease->findAttributeValue("state"); 271 if (pszState) 272 { 273 b->m_issued = Timestamp::absSeconds(secIssued); 274 b->setState(pszState); 313 275 } 314 276 else 315 277 { /** @todo XXX: old code wrote timestamps instead of absolute time. */ 316 278 /* pretend that lease has just ended */ 317 Timestamp fakeIssued = Timestamp::now(); 318 fakeIssued.subSeconds(duration); 319 b->m_issued = fakeIssued; 320 b->m_secLease = duration; 321 b->m_state = Binding::EXPIRED; 322 } 279 LogRel(("Binding::fromXML: No 'state' attribute for <Lease mac=%RTmac> (ts=%RI64 ttl=%RU32)! Assuming EXPIRED.\n", 280 &mac, secIssued, cSecToLive)); 281 b->m_issued = Timestamp::now().subSeconds(cSecToLive); 282 b->m_state = Binding::EXPIRED; 283 } 284 b->m_secLease = cSecToLive; 285 286 287 /* 288 * Lease/@id - optional, ignore if bad. 289 * Value format: "deadbeef..." or "de:ad:be:ef...". 290 */ 291 const char *pszClientId = pElmLease->findAttributeValue("id"); 292 if (pszClientId) 293 { 294 uint8_t abBytes[255]; 295 size_t cbActual; 296 rc = RTStrConvertHexBytesEx(pszClientId, abBytes, sizeof(abBytes), RTSTRCONVERTHEXBYTES_F_SEP_COLON, NULL, &cbActual); 297 if (RT_SUCCESS(rc)) 298 { 299 b->m_id = ClientId(mac, OptClientId(std::vector<uint8_t>(&abBytes[0], &abBytes[cbActual]))); /* throws bad_alloc */ 300 if (rc != VINF_BUFFER_UNDERFLOW && rc != VINF_SUCCESS) 301 LogRel(("Binding::fromXML: imperfect 'id' attribute: rc=%Rrc, cbActual=%u, '%s'\n", rc, cbActual, pszClientId)); 302 } 303 else 304 { 305 LogRel(("Binding::fromXML: ignoring malformed 'id' attribute: rc=%Rrc, cbActual=%u, '%s'\n", 306 rc, cbActual, pszClientId)); 307 b->m_id = ClientId(mac, OptClientId()); 308 } 309 } 310 else 311 b->m_id = ClientId(mac, OptClientId()); 323 312 324 313 return b.release(); … … 433 422 434 423 if (addr.u != 0) 435 Log DHCP(("> allocateAddress %RTnaipv4 to client %R[id]\n", addr.u, &id));424 LogRel(("> allocateAddress %RTnaipv4 to client %R[id]\n", addr.u, &id)); 436 425 else 437 Log DHCP(("> allocateAddress to client %R[id]\n", &id));426 LogRel(("> allocateAddress to client %R[id]\n", &id)); 438 427 439 428 /* … … 456 445 if (b->m_id == id) 457 446 { 458 Log DHCP(("> ... found existing binding %R[binding]\n", b));447 LogRel(("> ... found existing binding %R[binding]\n", b)); 459 448 return b; 460 449 } … … 464 453 Assert(addrBinding == NULL); 465 454 addrBinding = b; 466 Log DHCP(("> .... noted existing binding %R[binding]\n", addrBinding));455 LogRel(("> .... noted existing binding %R[binding]\n", addrBinding)); 467 456 } 468 457 … … 473 462 { 474 463 freeBinding = b; 475 Log DHCP(("> .... noted free binding %R[binding]\n", freeBinding));464 LogRel(("> .... noted free binding %R[binding]\n", freeBinding)); 476 465 continue; 477 466 } … … 485 474 { 486 475 reuseBinding = b; 487 Log DHCP(("> .... noted released binding %R[binding]\n", reuseBinding));476 LogRel(("> .... noted released binding %R[binding]\n", reuseBinding)); 488 477 } 489 478 } … … 495 484 { 496 485 reuseBinding = b; 497 Log DHCP(("> .... noted expired binding %R[binding]\n", reuseBinding));486 LogRel(("> .... noted expired binding %R[binding]\n", reuseBinding)); 498 487 } 499 488 } … … 510 499 addrBinding = i_createBinding(addr, id); 511 500 Assert(addrBinding != NULL); 512 Log DHCP(("> .... creating new binding for this address %R[binding]\n", addrBinding));501 LogRel(("> .... creating new binding for this address %R[binding]\n", addrBinding)); 513 502 return addrBinding; 514 503 } … … 516 505 if (addrBinding->m_state <= Binding::EXPIRED) /* not in use */ 517 506 { 518 Log DHCP(("> .... reusing %s binding for this address\n", addrBinding->stateName()));507 LogRel(("> .... reusing %s binding for this address\n", addrBinding->stateName())); 519 508 addrBinding->giveTo(id); 520 509 return addrBinding; 521 510 } 522 Log DHCP(("> .... cannot reuse %s binding for this address\n", addrBinding->stateName()));511 LogRel(("> .... cannot reuse %s binding for this address\n", addrBinding->stateName())); 523 512 } 524 513 … … 530 519 { 531 520 idBinding = freeBinding; 532 Log DHCP(("> .... reusing free binding\n"));521 LogRel(("> .... reusing free binding\n")); 533 522 } 534 523 else … … 536 525 idBinding = i_createBinding(); 537 526 if (idBinding != NULL) 538 Log DHCP(("> .... creating new binding\n"));527 LogRel(("> .... creating new binding\n")); 539 528 else 540 529 { 541 530 idBinding = reuseBinding; 542 531 if (idBinding != NULL) 543 Log DHCP(("> .... reusing %s binding %R[binding]\n", reuseBinding->stateName(), reuseBinding));532 LogRel(("> .... reusing %s binding %R[binding]\n", reuseBinding->stateName(), reuseBinding)); 544 533 else 545 { 546 LogDHCP(("> .... failed to allocate binding\n")); 547 return NULL; 548 } 534 DHCP_LOG_RET_NULL(("> .... failed to allocate binding\n")); 549 535 } 550 536 } 551 537 552 538 idBinding->giveTo(id); 553 Log DHCP(("> .... allocated %R[binding]\n", idBinding));539 LogRel(("> .... allocated %R[binding]\n", idBinding)); 554 540 555 541 return idBinding; … … 576 562 if (req.messageType() == RTNET_DHCP_MT_DISCOVER) 577 563 { 578 Log DHCP(("DISCOVER: ignoring invalid requested address\n"));564 LogRel(("DISCOVER: ignoring invalid requested address\n")); 579 565 reqAddr = OptRequestedAddress(); 580 566 } 581 567 else 582 { 583 LogDHCP(("rejecting invalid requested address\n")); 584 return NULL; 585 } 568 DHCP_LOG_RET_NULL(("rejecting invalid requested address\n")); 586 569 } 587 570 … … 621 604 if (!addressBelongs(pNewBinding->m_addr)) 622 605 { 623 Log DHCP(("Binding for out of range address %RTnaipv4 ignored\n", pNewBinding->m_addr.u));606 LogRel(("Binding for out of range address %RTnaipv4 ignored\n", pNewBinding->m_addr.u)); 624 607 return VERR_OUT_OF_RANGE; 625 608 } … … 631 614 if (pNewBinding->m_addr.u == b->m_addr.u) 632 615 { 633 Log DHCP(("> ADD: %R[binding]\n", pNewBinding));634 Log DHCP(("> .... duplicate ip: %R[binding]\n", b));616 LogRel(("> ADD: %R[binding]\n", pNewBinding)); 617 LogRel(("> .... duplicate ip: %R[binding]\n", b)); 635 618 return VERR_DUPLICATE; 636 619 } … … 638 621 if (pNewBinding->m_id == b->m_id) 639 622 { 640 Log DHCP(("> ADD: %R[binding]\n", pNewBinding));641 Log DHCP(("> .... duplicate id: %R[binding]\n", b));623 LogRel(("> ADD: %R[binding]\n", pNewBinding)); 624 LogRel(("> .... duplicate id: %R[binding]\n", b)); 642 625 return VERR_DUPLICATE; 643 626 } … … 734 717 int Db::writeLeases(const RTCString &strFilename) const RT_NOEXCEPT 735 718 { 736 Log DHCP(("writing leases to %s\n", strFilename.c_str()));719 LogRel(("writing leases to %s\n", strFilename.c_str())); 737 720 738 721 /** @todo This could easily be written directly to the file w/o going thru … … 777 760 catch (const xml::EIPRTFailure &e) 778 761 { 779 Log DHCP(("%s\n", e.what()));762 LogRel(("%s\n", e.what())); 780 763 return e.rc(); 781 764 } 782 765 catch (const RTCError &e) 783 766 { 784 Log DHCP(("%s\n", e.what()));767 LogRel(("%s\n", e.what())); 785 768 return VERR_GENERAL_FAILURE; 786 769 } 787 770 catch (...) 788 771 { 789 Log DHCP(("Unknown exception while writing '%s'\n", strFilename.c_str()));772 LogRel(("Unknown exception while writing '%s'\n", strFilename.c_str())); 790 773 return VERR_UNEXPECTED_EXCEPTION; 791 774 } … … 806 789 int Db::loadLeases(const RTCString &strFilename) RT_NOEXCEPT 807 790 { 808 Log DHCP(("loading leases from %s\n", strFilename.c_str()));791 LogRel(("loading leases from %s\n", strFilename.c_str())); 809 792 810 793 /* … … 819 802 catch (const xml::EIPRTFailure &e) 820 803 { 821 Log DHCP(("%s\n", e.what()));804 LogRel(("%s\n", e.what())); 822 805 return e.rc(); 823 806 } 824 807 catch (const RTCError &e) 825 808 { 826 Log DHCP(("%s\n", e.what()));809 LogRel(("%s\n", e.what())); 827 810 return VERR_GENERAL_FAILURE; 828 811 } 829 812 catch (...) 830 813 { 831 Log DHCP(("Unknown exception while reading and parsing '%s'\n", strFilename.c_str()));814 LogRel(("Unknown exception while reading and parsing '%s'\n", strFilename.c_str())); 832 815 return VERR_UNEXPECTED_EXCEPTION; 833 816 } … … 839 822 if (!pElmRoot) 840 823 { 841 Log DHCP(("No root element in '%s'\n", strFilename.c_str()));824 LogRel(("No root element in '%s'\n", strFilename.c_str())); 842 825 return VERR_NOT_FOUND; 843 826 } 844 827 if (!pElmRoot->nameEquals("Leases")) 845 828 { 846 Log DHCP(("No root element is not 'Leases' in '%s', but '%s'\n", strFilename.c_str(), pElmRoot->getName()));829 LogRel(("No root element is not 'Leases' in '%s', but '%s'\n", strFilename.c_str(), pElmRoot->getName())); 847 830 return VERR_NOT_FOUND; 848 831 } … … 864 847 } 865 848 else 866 Log DHCP(("Ignoring unexpected element '%s' under 'Leases'...\n", pElmLease->getName()));849 LogRel(("Ignoring unexpected element '%s' under 'Leases'...\n", pElmLease->getName())); 867 850 } 868 851 … … 892 875 bool fExpired = pBinding->expire(); 893 876 if (!fExpired) 894 Log DHCP(("> LOAD: lease %R[binding]\n", pBinding));877 LogRel(("> LOAD: lease %R[binding]\n", pBinding)); 895 878 else 896 Log DHCP(("> LOAD: EXPIRED lease %R[binding]\n", pBinding));879 LogRel(("> LOAD: EXPIRED lease %R[binding]\n", pBinding)); 897 880 898 881 int rc = i_addBinding(pBinding); … … 901 884 return rc; 902 885 } 903 Log DHCP(("> LOAD: failed to load lease!\n"));886 LogRel(("> LOAD: failed to load lease!\n")); 904 887 return VERR_PARSE_ERROR; 905 888 }
Note:
See TracChangeset
for help on using the changeset viewer.