VirtualBox

source: vbox/trunk/src/VBox/NetworkServices/Dhcpd/IPv4Pool.cpp@ 79529

Last change on this file since 79529 was 79529, checked in by vboxsync, 5 years ago

Dhcpd: Went over the Db and IPv4Pool code adding comments and and such. bugref:9288

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 5.0 KB
Line 
1/* $Id: IPv4Pool.cpp 79529 2019-07-04 18:17:50Z vboxsync $ */
2/** @file
3 * DHCP server - A pool of IPv4 addresses.
4 */
5
6/*
7 * Copyright (C) 2017-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#include "DhcpdInternal.h"
23#include <iprt/errcore.h>
24
25#include "IPv4Pool.h"
26
27
28int IPv4Pool::init(const IPv4Range &aRange)
29{
30 AssertReturn(aRange.isValid(), VERR_INVALID_PARAMETER);
31
32 m_range = aRange;
33 m_pool.insert(m_range);
34 return VINF_SUCCESS;
35}
36
37
38int IPv4Pool::init(RTNETADDRIPV4 aFirstAddr, RTNETADDRIPV4 aLastAddr)
39{
40 return init(IPv4Range(aFirstAddr, aLastAddr));
41}
42
43
44/**
45 * Internal worker for inserting a range into the pool of available addresses.
46 *
47 * @returns IPRT status code (asserted).
48 * @param a_Range The range to insert.
49 */
50int IPv4Pool::insert(const IPv4Range &a_Range)
51{
52 /*
53 * Check preconditions. Asserting because nobody checks the return code.
54 */
55 AssertReturn(m_range.isValid(), VERR_INVALID_STATE);
56 AssertReturn(a_Range.isValid(), VERR_INVALID_PARAMETER);
57 AssertReturn(m_range.contains(a_Range), VERR_INVALID_PARAMETER);
58
59 /*
60 * Check that the incoming range doesn't overlap with existing ranges in the pool.
61 */
62 it_t itHint = m_pool.upper_bound(IPv4Range(a_Range.LastAddr)); /* successor, insertion hint */
63#if 0 /** @todo r=bird: This code is wrong. It has no end() check for starters. Since the method is
64 * only for internal consumption, I've replaced it with a strict build assertion. */
65 if (itHint != m_pool.begin())
66 {
67 it_t prev(itHint);
68 --prev;
69 if (a_Range.FirstAddr <= prev->LastAddr)
70 {
71 LogDHCP(("%08x-%08x conflicts with %08x-%08x\n",
72 a_Range.FirstAddr, a_Range.LastAddr,
73 prev->FirstAddr, prev->LastAddr));
74 return VERR_INVALID_PARAMETER;
75 }
76 }
77#endif
78#ifdef VBOX_STRICT
79 for (it_t it2 = m_pool.begin(); it2 != m_pool.end(); ++it2)
80 AssertMsg(it2->LastAddr < a_Range.FirstAddr || it2->FirstAddr > a_Range.LastAddr,
81 ("%08RX32-%08RX32 conflicts with %08RX32-%08RX32\n",
82 a_Range.FirstAddr, a_Range.LastAddr, it2->FirstAddr, it2->LastAddr));
83#endif
84
85 /*
86 * No overlaps, insert it.
87 */
88 m_pool.insert(itHint, a_Range);
89 return VINF_SUCCESS;
90}
91
92
93/**
94 * Allocates an available IPv4 address from the pool.
95 *
96 * @returns Non-zero network order IPv4 address on success, zero address
97 * (0.0.0.0) on failure.
98 */
99RTNETADDRIPV4 IPv4Pool::allocate()
100{
101 RTNETADDRIPV4 RetAddr;
102 if (!m_pool.empty())
103 {
104 /* Grab the first address in the pool: */
105 it_t itBeg = m_pool.begin();
106 RetAddr.u = RT_H2N_U32(itBeg->FirstAddr);
107
108 if (itBeg->FirstAddr == itBeg->LastAddr)
109 m_pool.erase(itBeg);
110 else
111 {
112 /* Trim the entry (re-inserting it): */
113 IPv4Range trimmed = *itBeg;
114 trimmed.FirstAddr += 1;
115 m_pool.erase(itBeg);
116 m_pool.insert(trimmed);
117 }
118 }
119 else
120 RetAddr.u = 0;
121 return RetAddr;
122}
123
124
125/**
126 * Allocate the given address.
127 *
128 * @returns Success indicator.
129 * @param a_Addr The IP address to allocate (network order).
130 */
131bool IPv4Pool::allocate(RTNETADDRIPV4 a_Addr)
132{
133 /*
134 * Find the range containing a_Addr.
135 */
136 it_t it = m_pool.lower_bound(IPv4Range(a_Addr)); /* candidate range */
137 if (it != m_pool.end())
138 {
139 Assert(RT_N2H_U32(a_Addr.u) <= it->LastAddr); /* by definition of < and lower_bound */
140
141 if (it->contains(a_Addr))
142 {
143 /*
144 * Remove a_Addr from the range by way of re-insertion.
145 */
146 const IPV4HADDR haddr = RT_N2H_U32(a_Addr.u);
147 IPV4HADDR first = it->FirstAddr;
148 IPV4HADDR last = it->LastAddr;
149
150 m_pool.erase(it);
151 if (first != last)
152 {
153 if (haddr == first)
154 insert(++first, last);
155 else if (haddr == last)
156 insert(first, --last);
157 else
158 {
159 insert(first, haddr - 1);
160 insert(haddr + 1, last);
161 }
162 }
163
164 return true;
165 }
166 }
167 return false;
168}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette