vendor: add d2g/dhcp4server
This commit is contained in:
354
vendor/github.com/d2g/dhcp4server/LICENSE
generated
vendored
Normal file
354
vendor/github.com/d2g/dhcp4server/LICENSE
generated
vendored
Normal file
@ -0,0 +1,354 @@
|
||||
Mozilla Public License, version 2.0
|
||||
|
||||
1. Definitions
|
||||
|
||||
1.1. “Contributor”
|
||||
|
||||
means each individual or legal entity that creates, contributes to the
|
||||
creation of, or owns Covered Software.
|
||||
|
||||
1.2. “Contributor Version”
|
||||
|
||||
means the combination of the Contributions of others (if any) used by a
|
||||
Contributor and that particular Contributor’s Contribution.
|
||||
|
||||
1.3. “Contribution”
|
||||
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. “Covered Software”
|
||||
|
||||
means Source Code Form to which the initial Contributor has attached the
|
||||
notice in Exhibit A, the Executable Form of such Source Code Form, and
|
||||
Modifications of such Source Code Form, in each case including portions
|
||||
thereof.
|
||||
|
||||
1.5. “Incompatible With Secondary Licenses”
|
||||
means
|
||||
|
||||
a. that the initial Contributor has attached the notice described in
|
||||
Exhibit B to the Covered Software; or
|
||||
|
||||
b. that the Covered Software was made available under the terms of version
|
||||
1.1 or earlier of the License, but not also under the terms of a
|
||||
Secondary License.
|
||||
|
||||
1.6. “Executable Form”
|
||||
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. “Larger Work”
|
||||
|
||||
means a work that combines Covered Software with other material, in a separate
|
||||
file or files, that is not Covered Software.
|
||||
|
||||
1.8. “License”
|
||||
|
||||
means this document.
|
||||
|
||||
1.9. “Licensable”
|
||||
|
||||
means having the right to grant, to the maximum extent possible, whether at the
|
||||
time of the initial grant or subsequently, any and all of the rights conveyed by
|
||||
this License.
|
||||
|
||||
1.10. “Modifications”
|
||||
|
||||
means any of the following:
|
||||
|
||||
a. any file in Source Code Form that results from an addition to, deletion
|
||||
from, or modification of the contents of Covered Software; or
|
||||
|
||||
b. any new file in Source Code Form that contains any Covered Software.
|
||||
|
||||
1.11. “Patent Claims” of a Contributor
|
||||
|
||||
means any patent claim(s), including without limitation, method, process,
|
||||
and apparatus claims, in any patent Licensable by such Contributor that
|
||||
would be infringed, but for the grant of the License, by the making,
|
||||
using, selling, offering for sale, having made, import, or transfer of
|
||||
either its Contributions or its Contributor Version.
|
||||
|
||||
1.12. “Secondary License”
|
||||
|
||||
means either the GNU General Public License, Version 2.0, the GNU Lesser
|
||||
General Public License, Version 2.1, the GNU Affero General Public
|
||||
License, Version 3.0, or any later versions of those licenses.
|
||||
|
||||
1.13. “Source Code Form”
|
||||
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. “You” (or “Your”)
|
||||
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, “You” includes any entity that controls, is
|
||||
controlled by, or is under common control with You. For purposes of this
|
||||
definition, “control” means (a) the power, direct or indirect, to cause
|
||||
the direction or management of such entity, whether by contract or
|
||||
otherwise, or (b) ownership of more than fifty percent (50%) of the
|
||||
outstanding shares or beneficial ownership of such entity.
|
||||
|
||||
|
||||
2. License Grants and Conditions
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
a. under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or as
|
||||
part of a Larger Work; and
|
||||
|
||||
b. under Patent Claims of such Contributor to make, use, sell, offer for
|
||||
sale, have made, import, and otherwise transfer either its Contributions
|
||||
or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution become
|
||||
effective for each Contribution on the date the Contributor first distributes
|
||||
such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under this
|
||||
License. No additional rights or licenses will be implied from the distribution
|
||||
or licensing of Covered Software under this License. Notwithstanding Section
|
||||
2.1(b) above, no patent license is granted by a Contributor:
|
||||
|
||||
a. for any code that a Contributor has removed from Covered Software; or
|
||||
|
||||
b. for infringements caused by: (i) Your and any other third party’s
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
c. under Patent Claims infringed by Covered Software in the absence of its
|
||||
Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks, or
|
||||
logos of any Contributor (except as may be necessary to comply with the
|
||||
notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this License
|
||||
(see Section 10.2) or under the terms of a Secondary License (if permitted
|
||||
under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its Contributions
|
||||
are its original creation(s) or it has sufficient rights to grant the
|
||||
rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under applicable
|
||||
copyright doctrines of fair use, fair dealing, or other equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
|
||||
Section 2.1.
|
||||
|
||||
|
||||
3. Responsibilities
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under the
|
||||
terms of this License. You must inform recipients that the Source Code Form
|
||||
of the Covered Software is governed by the terms of this License, and how
|
||||
they can obtain a copy of this License. You may not attempt to alter or
|
||||
restrict the recipients’ rights in the Source Code Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
a. such Covered Software must also be made available in Source Code Form,
|
||||
as described in Section 3.1, and You must inform recipients of the
|
||||
Executable Form how they can obtain a copy of such Source Code Form by
|
||||
reasonable means in a timely manner, at a charge no more than the cost
|
||||
of distribution to the recipient; and
|
||||
|
||||
b. You may distribute such Executable Form under the terms of this License,
|
||||
or sublicense it under different terms, provided that the license for
|
||||
the Executable Form does not attempt to limit or alter the recipients’
|
||||
rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for the
|
||||
Covered Software. If the Larger Work is a combination of Covered Software
|
||||
with a work governed by one or more Secondary Licenses, and the Covered
|
||||
Software is not Incompatible With Secondary Licenses, this License permits
|
||||
You to additionally distribute such Covered Software under the terms of
|
||||
such Secondary License(s), so that the recipient of the Larger Work may, at
|
||||
their option, further distribute the Covered Software under the terms of
|
||||
either this License or such Secondary License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices (including
|
||||
copyright notices, patent notices, disclaimers of warranty, or limitations
|
||||
of liability) contained within the Source Code Form of the Covered
|
||||
Software, except that You may alter any license notices to the extent
|
||||
required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on behalf
|
||||
of any Contributor. You must make it absolutely clear that any such
|
||||
warranty, support, indemnity, or liability obligation is offered by You
|
||||
alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this License
|
||||
with respect to some or all of the Covered Software due to statute, judicial
|
||||
order, or regulation then You must: (a) comply with the terms of this License
|
||||
to the maximum extent possible; and (b) describe the limitations and the code
|
||||
they affect. Such description must be placed in a text file included with all
|
||||
distributions of the Covered Software under this License. Except to the
|
||||
extent prohibited by statute or regulation, such description must be
|
||||
sufficiently detailed for a recipient of ordinary skill to be able to
|
||||
understand it.
|
||||
|
||||
5. Termination
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically if You
|
||||
fail to comply with any of its terms. However, if You become compliant,
|
||||
then the rights granted under this License from a particular Contributor
|
||||
are reinstated (a) provisionally, unless and until such Contributor
|
||||
explicitly and finally terminates Your grants, and (b) on an ongoing basis,
|
||||
if such Contributor fails to notify You of the non-compliance by some
|
||||
reasonable means prior to 60 days after You have come back into compliance.
|
||||
Moreover, Your grants from a particular Contributor are reinstated on an
|
||||
ongoing basis if such Contributor notifies You of the non-compliance by
|
||||
some reasonable means, this is the first time You have received notice of
|
||||
non-compliance with this License from such Contributor, and You become
|
||||
compliant prior to 30 days after Your receipt of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions, counter-claims,
|
||||
and cross-claims) alleging that a Contributor Version directly or
|
||||
indirectly infringes any patent, then the rights granted to You by any and
|
||||
all Contributors for the Covered Software under Section 2.1 of this License
|
||||
shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
|
||||
license agreements (excluding distributors and resellers) which have been
|
||||
validly granted by You or Your distributors under this License prior to
|
||||
termination shall survive termination.
|
||||
|
||||
6. Disclaimer of Warranty
|
||||
|
||||
Covered Software is provided under this License on an “as is” basis, without
|
||||
warranty of any kind, either expressed, implied, or statutory, including,
|
||||
without limitation, warranties that the Covered Software is free of defects,
|
||||
merchantable, fit for a particular purpose or non-infringing. The entire
|
||||
risk as to the quality and performance of the Covered Software is with You.
|
||||
Should any Covered Software prove defective in any respect, You (not any
|
||||
Contributor) assume the cost of any necessary servicing, repair, or
|
||||
correction. This disclaimer of warranty constitutes an essential part of this
|
||||
License. No use of any Covered Software is authorized under this License
|
||||
except under this disclaimer.
|
||||
|
||||
7. Limitation of Liability
|
||||
|
||||
Under no circumstances and under no legal theory, whether tort (including
|
||||
negligence), contract, or otherwise, shall any Contributor, or anyone who
|
||||
distributes Covered Software as permitted above, be liable to You for any
|
||||
direct, indirect, special, incidental, or consequential damages of any
|
||||
character including, without limitation, damages for lost profits, loss of
|
||||
goodwill, work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses, even if such party shall have been
|
||||
informed of the possibility of such damages. This limitation of liability
|
||||
shall not apply to liability for death or personal injury resulting from such
|
||||
party’s negligence to the extent applicable law prohibits such limitation.
|
||||
Some jurisdictions do not allow the exclusion or limitation of incidental or
|
||||
consequential damages, so this exclusion and limitation may not apply to You.
|
||||
|
||||
8. Litigation
|
||||
|
||||
Any litigation relating to this License may be brought only in the courts of
|
||||
a jurisdiction where the defendant maintains its principal place of business
|
||||
and such litigation shall be governed by laws of that jurisdiction, without
|
||||
reference to its conflict-of-law provisions. Nothing in this Section shall
|
||||
prevent a party’s ability to bring cross-claims or counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
|
||||
This License represents the complete agreement concerning the subject matter
|
||||
hereof. If any provision of this License is held to be unenforceable, such
|
||||
provision shall be reformed only to the extent necessary to make it
|
||||
enforceable. Any law or regulation which provides that the language of a
|
||||
contract shall be construed against the drafter shall not be used to construe
|
||||
this License against a Contributor.
|
||||
|
||||
|
||||
10. Versions of the License
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version of
|
||||
the License under which You originally received the Covered Software, or
|
||||
under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a modified
|
||||
version of this License if you rename the license and remove any
|
||||
references to the name of the license steward (except to note that such
|
||||
modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses
|
||||
If You choose to distribute Source Code Form that is Incompatible With
|
||||
Secondary Licenses under the terms of this version of the License, the
|
||||
notice described in Exhibit B of this License must be attached.
|
||||
|
||||
Exhibit A - Source Code Form License Notice
|
||||
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
2.0. If a copy of the MPL was not
|
||||
distributed with this file, You can
|
||||
obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular file, then
|
||||
You may include the notice in a location (such as a LICENSE file in a relevant
|
||||
directory) where a recipient would be likely to look for such a notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
|
||||
Exhibit B - “Incompatible With Secondary Licenses” Notice
|
||||
|
||||
This Source Code Form is “Incompatible
|
||||
With Secondary Licenses”, as defined by
|
||||
the Mozilla Public License, v. 2.0.
|
||||
|
4
vendor/github.com/d2g/dhcp4server/README.md
generated
vendored
Normal file
4
vendor/github.com/d2g/dhcp4server/README.md
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
dhcp4server [](http://godoc.org/github.com/d2g/dhcp4server) [](https://coveralls.io/r/d2g/dhcp4server) [](https://codeship.com/projects/59804)
|
||||
===========
|
||||
|
||||
DHCP Server
|
95
vendor/github.com/d2g/dhcp4server/leasepool/lease.go
generated
vendored
Normal file
95
vendor/github.com/d2g/dhcp4server/leasepool/lease.go
generated
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
package leasepool
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
type LeaseStatus int
|
||||
|
||||
const (
|
||||
Free LeaseStatus = 0
|
||||
Reserved LeaseStatus = 1
|
||||
Active LeaseStatus = 2
|
||||
)
|
||||
|
||||
type Lease struct {
|
||||
IP net.IP //The IP of the Lease
|
||||
Status LeaseStatus //Are Reserved, Active or Free
|
||||
MACAddress net.HardwareAddr //Mac Address of the Device
|
||||
Hostname string //Hostname From option 12
|
||||
Expiry time.Time //Expiry Time
|
||||
}
|
||||
|
||||
func (this Lease) MarshalJSON() ([]byte, error) {
|
||||
stringMarshal := struct {
|
||||
IP string
|
||||
Status int
|
||||
MACAddress string
|
||||
Hostname string
|
||||
Expiry time.Time
|
||||
}{
|
||||
(this.IP.String()),
|
||||
int(this.Status),
|
||||
(this.MACAddress.String()),
|
||||
this.Hostname,
|
||||
this.Expiry,
|
||||
}
|
||||
|
||||
return json.Marshal(stringMarshal)
|
||||
}
|
||||
|
||||
func (this *Lease) UnmarshalJSON(data []byte) error {
|
||||
stringUnMarshal := struct {
|
||||
IP string
|
||||
Status int
|
||||
MACAddress string
|
||||
Hostname string
|
||||
Expiry time.Time
|
||||
}{}
|
||||
|
||||
err := json.Unmarshal(data, &stringUnMarshal)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
this.IP = net.ParseIP(stringUnMarshal.IP)
|
||||
this.Status = LeaseStatus(stringUnMarshal.Status)
|
||||
if stringUnMarshal.MACAddress != "" {
|
||||
this.MACAddress, err = net.ParseMAC(stringUnMarshal.MACAddress)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
this.Hostname = stringUnMarshal.Hostname
|
||||
this.Expiry = stringUnMarshal.Expiry
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this Lease) Equal(other Lease) bool {
|
||||
if !this.IP.Equal(other.IP) {
|
||||
return false
|
||||
}
|
||||
|
||||
if int(this.Status) != int(other.Status) {
|
||||
return false
|
||||
}
|
||||
|
||||
if this.MACAddress.String() != other.MACAddress.String() {
|
||||
return false
|
||||
}
|
||||
|
||||
if this.Hostname != other.Hostname {
|
||||
return false
|
||||
}
|
||||
|
||||
if !this.Expiry.Equal(other.Expiry) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
51
vendor/github.com/d2g/dhcp4server/leasepool/lease_test.go
generated
vendored
Normal file
51
vendor/github.com/d2g/dhcp4server/leasepool/lease_test.go
generated
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
package leasepool
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
/*
|
||||
* The Leases are Marshalled and Unmarshalled for storage.
|
||||
* I JSON Marshal these for gvklite
|
||||
*/
|
||||
func TestMarshaling(test *testing.T) {
|
||||
var err error
|
||||
|
||||
startLease := Lease{}
|
||||
startLease.IP = net.IPv4(192, 168, 0, 1)
|
||||
startLease.Hostname = "ExampleHostname"
|
||||
startLease.Status = Active
|
||||
startLease.Expiry = time.Now()
|
||||
startLease.MACAddress, err = net.ParseMAC("01:23:45:67:89:ab")
|
||||
if err != nil {
|
||||
test.Error("Error Parsing Mac Address:" + err.Error())
|
||||
}
|
||||
|
||||
byteStartLease, err := json.Marshal(startLease)
|
||||
if err != nil {
|
||||
test.Error("Error Marshaling to JSON:" + err.Error())
|
||||
}
|
||||
|
||||
test.Log("StartLease As JSON:" + string(byteStartLease))
|
||||
|
||||
endLease := Lease{}
|
||||
err = json.Unmarshal(byteStartLease, &endLease)
|
||||
if err != nil {
|
||||
test.Error("Error Unmarshaling to JSON:" + err.Error())
|
||||
}
|
||||
|
||||
test.Logf("End Lease Object:%v\n", endLease)
|
||||
|
||||
if !startLease.Equal(endLease) {
|
||||
byteEndLease, err := json.Marshal(endLease)
|
||||
if err != nil {
|
||||
test.Error("Can't Marshal End Lease For Debuging:" + err.Error())
|
||||
}
|
||||
test.Log("End Lease as JSON:" + string(byteEndLease))
|
||||
test.Error("Starting Lease Doesn't Match End Lease")
|
||||
}
|
||||
|
||||
}
|
49
vendor/github.com/d2g/dhcp4server/leasepool/leasepool.go
generated
vendored
Normal file
49
vendor/github.com/d2g/dhcp4server/leasepool/leasepool.go
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
package leasepool
|
||||
|
||||
import (
|
||||
"net"
|
||||
)
|
||||
|
||||
/*
|
||||
* Lease.IP is the Key.
|
||||
*/
|
||||
type LeasePool interface {
|
||||
//Add A Lease To The Pool
|
||||
AddLease(Lease) error
|
||||
|
||||
//Remove
|
||||
RemoveLease(net.IP) error
|
||||
|
||||
//Remove All Leases from the Pool (Required for Persistant LeaseManagers)
|
||||
PurgeLeases() error
|
||||
|
||||
/*
|
||||
* Get the Lease
|
||||
* -Found
|
||||
* -Copy Of the Lease
|
||||
* -Any Error
|
||||
*/
|
||||
GetLease(net.IP) (bool, Lease, error)
|
||||
|
||||
//Get the lease already in use by that hardware address.
|
||||
GetLeaseForHardwareAddress(net.HardwareAddr) (bool, Lease, error)
|
||||
|
||||
/*
|
||||
* -Lease Available
|
||||
* -Lease
|
||||
* -Error
|
||||
*/
|
||||
GetNextFreeLease() (bool, Lease, error)
|
||||
|
||||
/*
|
||||
* Return All Leases
|
||||
*/
|
||||
GetLeases() ([]Lease, error)
|
||||
|
||||
/*
|
||||
* Update Lease
|
||||
* - Has Updated
|
||||
* - Error
|
||||
*/
|
||||
UpdateLease(Lease) (bool, error)
|
||||
}
|
150
vendor/github.com/d2g/dhcp4server/leasepool/memorypool/memorypool.go
generated
vendored
Normal file
150
vendor/github.com/d2g/dhcp4server/leasepool/memorypool/memorypool.go
generated
vendored
Normal file
@ -0,0 +1,150 @@
|
||||
package memorypool
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"github.com/d2g/dhcp4server/leasepool"
|
||||
"net"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type MemoryPool struct {
|
||||
pool []leasepool.Lease
|
||||
poolLock sync.Mutex
|
||||
}
|
||||
|
||||
//Add A Lease To The Pool
|
||||
func (t *MemoryPool) AddLease(newLease leasepool.Lease) error {
|
||||
t.poolLock.Lock()
|
||||
defer t.poolLock.Unlock()
|
||||
|
||||
if t.pool == nil {
|
||||
t.pool = make([]leasepool.Lease, 0)
|
||||
}
|
||||
|
||||
for i := range t.pool {
|
||||
if t.pool[i].IP.Equal(newLease.IP) {
|
||||
//Lease Already Exists In Pool
|
||||
return errors.New("Error: Lease IP \"" + newLease.IP.String() + "\" alreay exists in Pool")
|
||||
}
|
||||
}
|
||||
|
||||
t.pool = append([]leasepool.Lease{newLease}, t.pool...)
|
||||
return nil
|
||||
}
|
||||
|
||||
//Remove a Lease From The Pool
|
||||
func (t *MemoryPool) RemoveLease(leaseIP net.IP) error {
|
||||
t.poolLock.Lock()
|
||||
defer t.poolLock.Unlock()
|
||||
|
||||
for i := range t.pool {
|
||||
if t.pool[i].IP.Equal(leaseIP) {
|
||||
|
||||
//Move the Last Element to This Position.
|
||||
t.pool[i] = t.pool[len(t.pool)-1]
|
||||
|
||||
//Shortern the Pool By One.
|
||||
t.pool = t.pool[0:(len(t.pool) - 1)]
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return errors.New("Error: Lease IP \"" + leaseIP.String() + "\" Is Not In The Pool")
|
||||
}
|
||||
|
||||
//Remove All Leases from the Pool (Required for Persistant LeaseManagers)
|
||||
func (t *MemoryPool) PurgeLeases() error {
|
||||
t.poolLock.Lock()
|
||||
defer t.poolLock.Unlock()
|
||||
|
||||
t.pool = nil
|
||||
t.pool = make([]leasepool.Lease, 0)
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the Lease
|
||||
* -Found
|
||||
* -Copy Of the Lease
|
||||
* -Any Error
|
||||
*/
|
||||
func (t *MemoryPool) GetLease(leaseIP net.IP) (bool, leasepool.Lease, error) {
|
||||
t.poolLock.Lock()
|
||||
defer t.poolLock.Unlock()
|
||||
|
||||
for i := range t.pool {
|
||||
if t.pool[i].IP.Equal(leaseIP) {
|
||||
return true, t.pool[i], nil
|
||||
}
|
||||
}
|
||||
return false, leasepool.Lease{}, nil
|
||||
}
|
||||
|
||||
//Get the lease already in use by that hardware address.
|
||||
func (t *MemoryPool) GetLeaseForHardwareAddress(macAddress net.HardwareAddr) (bool, leasepool.Lease, error) {
|
||||
t.poolLock.Lock()
|
||||
defer t.poolLock.Unlock()
|
||||
|
||||
for i := range t.pool {
|
||||
if bytes.Equal(t.pool[i].MACAddress, macAddress) {
|
||||
return true, t.pool[i], nil
|
||||
}
|
||||
}
|
||||
return false, leasepool.Lease{}, nil
|
||||
}
|
||||
|
||||
/*
|
||||
* -Lease Available
|
||||
* -Lease
|
||||
* -Error
|
||||
*/
|
||||
func (t *MemoryPool) GetNextFreeLease() (bool, leasepool.Lease, error) {
|
||||
t.poolLock.Lock()
|
||||
defer t.poolLock.Unlock()
|
||||
|
||||
//Loop Through the elements backwards.
|
||||
for i := (len(t.pool) - 1); i >= 0; i-- {
|
||||
//If the Lease Is Free
|
||||
if t.pool[i].Status == leasepool.Free {
|
||||
//Take the Element
|
||||
iLease := t.pool[i]
|
||||
//Shrink the Pool By 1
|
||||
t.pool = t.pool[:(len(t.pool) - 1)]
|
||||
//Place the Lease At the Begining (This saves us having some sort of counter...)
|
||||
t.pool = append([]leasepool.Lease{iLease}, t.pool...)
|
||||
return true, iLease, nil
|
||||
}
|
||||
}
|
||||
return false, leasepool.Lease{}, nil
|
||||
}
|
||||
|
||||
/*
|
||||
* Return All Leases
|
||||
*/
|
||||
func (t *MemoryPool) GetLeases() ([]leasepool.Lease, error) {
|
||||
return t.pool, nil
|
||||
}
|
||||
|
||||
/*
|
||||
* Update Lease
|
||||
* - Has Updated
|
||||
* - Error
|
||||
*/
|
||||
func (t *MemoryPool) UpdateLease(lease leasepool.Lease) (bool, error) {
|
||||
t.poolLock.Lock()
|
||||
defer t.poolLock.Unlock()
|
||||
|
||||
for i := range t.pool {
|
||||
if t.pool[i].IP.Equal(lease.IP) {
|
||||
|
||||
t.pool[i].MACAddress = lease.MACAddress
|
||||
t.pool[i].Hostname = lease.Hostname
|
||||
t.pool[i].Expiry = lease.Expiry
|
||||
t.pool[i].Status = lease.Status
|
||||
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
51
vendor/github.com/d2g/dhcp4server/leasepool/memorypool/memorypool_test.go
generated
vendored
Normal file
51
vendor/github.com/d2g/dhcp4server/leasepool/memorypool/memorypool_test.go
generated
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
package memorypool
|
||||
|
||||
import (
|
||||
"github.com/d2g/dhcp4"
|
||||
"github.com/d2g/dhcp4server/leasepool"
|
||||
"net"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLeaseCycle(test *testing.T) {
|
||||
myMemoryLeasePool := MemoryPool{}
|
||||
|
||||
//Lets add a list of IPs to the pool these will be served to the clients so make sure they work for you.
|
||||
// So Create Array of IPs 192.168.1.1 to 192.168.1.30
|
||||
for i := 0; i < 30; i++ {
|
||||
err := myMemoryLeasePool.AddLease(leasepool.Lease{IP: dhcp4.IPAdd(net.IPv4(192, 168, 1, 1), i)})
|
||||
if err != nil {
|
||||
test.Error("Error Creating Lease:" + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < 30; i++ {
|
||||
hasLease, iLease, err := myMemoryLeasePool.GetNextFreeLease()
|
||||
if err != nil || !hasLease {
|
||||
test.Error("Error Getting Lease:" + err.Error())
|
||||
}
|
||||
|
||||
if !dhcp4.IPAdd(net.IPv4(192, 168, 1, 1), i).Equal(iLease.IP) {
|
||||
test.Error("Expected Lease:" + dhcp4.IPAdd(net.IPv4(192, 168, 1, 1), i).String() + " Received:" + iLease.IP.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSingleLease(test *testing.T) {
|
||||
myMemoryLeasePool := MemoryPool{}
|
||||
|
||||
err := myMemoryLeasePool.AddLease(leasepool.Lease{IP: dhcp4.IPAdd(net.IPv4(192, 168, 1, 5), 0)})
|
||||
if err != nil {
|
||||
test.Error("Error Creating Lease:" + err.Error())
|
||||
}
|
||||
|
||||
hasLease, iLease, err := myMemoryLeasePool.GetNextFreeLease()
|
||||
if err != nil || !hasLease {
|
||||
test.Error("Error Getting Lease:" + err.Error())
|
||||
}
|
||||
|
||||
if !dhcp4.IPAdd(net.IPv4(192, 168, 1, 5), 0).Equal(iLease.IP) {
|
||||
test.Error("Expected Lease:" + dhcp4.IPAdd(net.IPv4(192, 168, 1, 5), 0).String() + " Received:" + iLease.IP.String())
|
||||
}
|
||||
}
|
||||
|
572
vendor/github.com/d2g/dhcp4server/server.go
generated
vendored
Normal file
572
vendor/github.com/d2g/dhcp4server/server.go
generated
vendored
Normal file
@ -0,0 +1,572 @@
|
||||
package dhcp4server
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"log"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/d2g/dhcp4"
|
||||
"github.com/d2g/dhcp4server/leasepool"
|
||||
|
||||
"golang.org/x/net/ipv4"
|
||||
)
|
||||
|
||||
/*
|
||||
* The DHCP Server Structure
|
||||
*/
|
||||
type Server struct {
|
||||
//Configuration Options
|
||||
ip net.IP //The IP Address We Tell Clients The Server Is On.
|
||||
defaultGateway net.IP //The Default Gateway Address
|
||||
dnsServers []net.IP //DNS Servers
|
||||
subnetMask net.IP //ie. 255.255.255.0
|
||||
leaseDuration time.Duration //Number of Seconds
|
||||
ignoreIPs []net.IP //Slice of IP's that should be ignored by the Server.
|
||||
ignoreHardwareAddress []net.HardwareAddr //Slice of Hardware Addresses we should ignore.
|
||||
|
||||
//Local Address
|
||||
laddr net.UDPAddr
|
||||
|
||||
//Remote address
|
||||
raddr net.UDPAddr
|
||||
|
||||
//LeasePool
|
||||
leasePool leasepool.LeasePool //Lease Pool Manager
|
||||
|
||||
//Used to Gracefully Close the Server
|
||||
shutdownLock sync.Mutex
|
||||
shutdown bool
|
||||
//Listeners & Response Connection.
|
||||
connection *ipv4.PacketConn
|
||||
}
|
||||
|
||||
// Create A New Server
|
||||
func New(ip net.IP, l leasepool.LeasePool, options ...func(*Server) error) (*Server, error) {
|
||||
s := Server{
|
||||
ip: ip,
|
||||
defaultGateway: ip,
|
||||
dnsServers: []net.IP{net.IPv4(208, 67, 222, 222), net.IPv4(208, 67, 220, 220)}, //OPENDNS
|
||||
subnetMask: net.IPv4(255, 255, 255, 0),
|
||||
leaseDuration: 24 * time.Hour,
|
||||
leasePool: l,
|
||||
laddr: net.UDPAddr{IP: net.IPv4(0, 0, 0, 0), Port: 67},
|
||||
raddr: net.UDPAddr{IP: net.IPv4bcast, Port: 68},
|
||||
}
|
||||
|
||||
err := s.setOptions(options...)
|
||||
if err != nil {
|
||||
return &s, err
|
||||
}
|
||||
|
||||
return &s, err
|
||||
}
|
||||
|
||||
func (s *Server) setOptions(options ...func(*Server) error) error {
|
||||
for _, opt := range options {
|
||||
if err := opt(s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Set the Server IP
|
||||
func IP(i net.IP) func(*Server) error {
|
||||
return func(s *Server) error {
|
||||
s.ip = i
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Set the Default Gateway Address.
|
||||
func DefaultGateway(r net.IP) func(*Server) error {
|
||||
return func(s *Server) error {
|
||||
s.defaultGateway = r
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Set the DNS servers.
|
||||
func DNSServers(dnss []net.IP) func(*Server) error {
|
||||
return func(s *Server) error {
|
||||
s.dnsServers = dnss
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Set the Subnet Mask
|
||||
func SubnetMask(m net.IP) func(*Server) error {
|
||||
return func(s *Server) error {
|
||||
s.subnetMask = m
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Set Lease Duration
|
||||
func LeaseDuration(d time.Duration) func(*Server) error {
|
||||
return func(s *Server) error {
|
||||
s.leaseDuration = d
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Set Ignore IPs
|
||||
func IgnoreIPs(ips []net.IP) func(*Server) error {
|
||||
return func(s *Server) error {
|
||||
s.ignoreIPs = ips
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Set Ignore Hardware Addresses
|
||||
func IgnoreHardwareAddresses(h []net.HardwareAddr) func(*Server) error {
|
||||
return func(s *Server) error {
|
||||
s.ignoreHardwareAddress = h
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Set LeasePool
|
||||
func LeasePool(p leasepool.LeasePool) func(*Server) error {
|
||||
return func(s *Server) error {
|
||||
s.leasePool = p
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Set The Local Address
|
||||
func SetLocalAddr(a net.UDPAddr) func(*Server) error {
|
||||
return func(s *Server) error {
|
||||
s.laddr = a
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Set The Remote Address
|
||||
func SetRemoteAddr(a net.UDPAddr) func(*Server) error {
|
||||
return func(s *Server) error {
|
||||
s.raddr = a
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) shouldShutdown() bool {
|
||||
s.shutdownLock.Lock()
|
||||
defer s.shutdownLock.Unlock()
|
||||
return s.shutdown
|
||||
}
|
||||
|
||||
/*
|
||||
* Start The DHCP Server
|
||||
*/
|
||||
func (s *Server) ListenAndServe() error {
|
||||
var err error
|
||||
|
||||
connection, err := net.ListenPacket("udp4", s.laddr.String())
|
||||
if err != nil {
|
||||
log.Printf("Debug: Error Returned From ListenPacket On \"%s\" Because of \"%s\"\n", s.laddr.String(), err.Error())
|
||||
return err
|
||||
}
|
||||
s.connection = ipv4.NewPacketConn(connection)
|
||||
defer s.connection.Close()
|
||||
|
||||
//We Currently Don't Use this Feature Which is the only bit that is Linux Only.
|
||||
//if err := s.connection.SetControlMessage(ipv4.FlagInterface, true); err != nil {
|
||||
// return err
|
||||
//}
|
||||
|
||||
//Make Our Buffer (Max Buffer is 574) "I believe this 576 size comes from RFC 791" - Random Mailing list quote of the day.
|
||||
buffer := make([]byte, 576)
|
||||
|
||||
log.Println("Trace: DHCP Server Listening.")
|
||||
|
||||
for {
|
||||
ListenForDHCPPackets:
|
||||
if s.shouldShutdown() {
|
||||
return nil
|
||||
}
|
||||
|
||||
//Set Read Deadline
|
||||
s.connection.SetReadDeadline(time.Now().Add(time.Second))
|
||||
// Read Packet
|
||||
n, control_message, source, err := s.connection.ReadFrom(buffer)
|
||||
|
||||
if err != nil {
|
||||
|
||||
switch v := err.(type) {
|
||||
case *net.OpError:
|
||||
if v.Timeout() {
|
||||
goto ListenForDHCPPackets
|
||||
}
|
||||
case *net.AddrError:
|
||||
if v.Timeout() {
|
||||
goto ListenForDHCPPackets
|
||||
}
|
||||
case *net.UnknownNetworkError:
|
||||
if v.Timeout() {
|
||||
goto ListenForDHCPPackets
|
||||
}
|
||||
}
|
||||
|
||||
log.Println("Debug: Unexpect Error from Connection Read From:" + err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
//We seem to have an issue with undersized packets?
|
||||
if n < 240 {
|
||||
log.Printf("Error: Invalid Packet Size \"%d\" Received:%v\n", n, buffer[:n])
|
||||
continue
|
||||
}
|
||||
|
||||
//We should ignore some requests
|
||||
//It shouldn't be possible to ignore IP's because they shouldn't have them as we're the DHCP server.
|
||||
//However, they can have i.e. if you're the client & server :S.
|
||||
for _, ipToIgnore := range s.ignoreIPs {
|
||||
if ipToIgnore.Equal(source.(*net.UDPAddr).IP) {
|
||||
log.Println("Debug: Ignoring DHCP Request From IP:" + ipToIgnore.String())
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
packet := dhcp4.Packet(buffer[:n])
|
||||
|
||||
//We can ignore hardware addresses.
|
||||
//Usefull for ignoring a range of hardware addresses
|
||||
for _, hardwareAddressToIgnore := range s.ignoreHardwareAddress {
|
||||
if bytes.Equal(hardwareAddressToIgnore, packet.CHAddr()) {
|
||||
log.Println("Debug: Ignoring DHCP Request From Hardware Address:" + hardwareAddressToIgnore.String())
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("Trace: Packet Received ID:%v\n", packet.XId())
|
||||
log.Printf("Trace: Packet Options:%v\n", packet.ParseOptions())
|
||||
log.Printf("Trace: Packet Client IP : %v\n", packet.CIAddr().String())
|
||||
log.Printf("Trace: Packet Your IP : %v\n", packet.YIAddr().String())
|
||||
log.Printf("Trace: Packet Server IP : %v\n", packet.SIAddr().String())
|
||||
log.Printf("Trace: Packet Gateway IP: %v\n", packet.GIAddr().String())
|
||||
log.Printf("Trace: Packet Client Mac: %v\n", packet.CHAddr().String())
|
||||
|
||||
//We need to stop butting in with other servers.
|
||||
if packet.SIAddr().Equal(net.IPv4(0, 0, 0, 0)) || packet.SIAddr().Equal(net.IP{}) || packet.SIAddr().Equal(s.ip) {
|
||||
|
||||
returnPacket, err := s.ServeDHCP(packet)
|
||||
if err != nil {
|
||||
log.Println("Debug: Error Serving DHCP:" + err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
if len(returnPacket) > 0 {
|
||||
log.Printf("Trace: Packet Returned ID:%v\n", returnPacket.XId())
|
||||
log.Printf("Trace: Packet Options:%v\n", returnPacket.ParseOptions())
|
||||
log.Printf("Trace: Packet Client IP : %v\n", returnPacket.CIAddr().String())
|
||||
log.Printf("Trace: Packet Your IP : %v\n", returnPacket.YIAddr().String())
|
||||
log.Printf("Trace: Packet Server IP : %v\n", returnPacket.SIAddr().String())
|
||||
log.Printf("Trace: Packet Gateway IP: %v\n", returnPacket.GIAddr().String())
|
||||
log.Printf("Trace: Packet Client Mac: %v\n", returnPacket.CHAddr().String())
|
||||
|
||||
_, err = s.connection.WriteTo(returnPacket, control_message, &s.raddr)
|
||||
if err != nil {
|
||||
log.Println("Debug: Error Writing:" + err.Error())
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) ServeDHCP(packet dhcp4.Packet) (dhcp4.Packet, error) {
|
||||
packetOptions := packet.ParseOptions()
|
||||
|
||||
switch dhcp4.MessageType(packetOptions[dhcp4.OptionDHCPMessageType][0]) {
|
||||
case dhcp4.Discover:
|
||||
|
||||
//Discover Received from client
|
||||
//Lets get the lease we're going to send them
|
||||
found, lease, err := s.GetLease(packet)
|
||||
if err != nil {
|
||||
return dhcp4.Packet{}, err
|
||||
}
|
||||
|
||||
if !found {
|
||||
log.Println("Warning: It Looks Like Our Leases Are Depleted...")
|
||||
return dhcp4.Packet{}, nil
|
||||
}
|
||||
|
||||
offerPacket := s.OfferPacket(packet)
|
||||
offerPacket.SetYIAddr(lease.IP)
|
||||
|
||||
//Sort out the packet options
|
||||
offerPacket.PadToMinSize()
|
||||
|
||||
lease.Status = leasepool.Reserved
|
||||
lease.MACAddress = packet.CHAddr()
|
||||
|
||||
//If the lease expires within the next 5 Mins increase the lease expiary (Giving the Client 5 mins to complete)
|
||||
if lease.Expiry.Before(time.Now().Add(time.Minute * 5)) {
|
||||
lease.Expiry = time.Now().Add(time.Minute * 5)
|
||||
}
|
||||
|
||||
if packetOptions[dhcp4.OptionHostName] != nil && string(packetOptions[dhcp4.OptionHostName]) != "" {
|
||||
lease.Hostname = string(packetOptions[dhcp4.OptionHostName])
|
||||
}
|
||||
|
||||
updated, err := s.leasePool.UpdateLease(lease)
|
||||
if err != nil {
|
||||
return dhcp4.Packet{}, err
|
||||
}
|
||||
|
||||
if !updated {
|
||||
//Unable to reserve lease (It's now active else where maybe?)
|
||||
return dhcp4.Packet{}, errors.New("Unable to Reserve Lease:" + lease.IP.String())
|
||||
}
|
||||
|
||||
return offerPacket, nil
|
||||
case dhcp4.Request:
|
||||
//Request Received from client
|
||||
//Lets get the lease we're going to send them
|
||||
found, lease, err := s.GetLease(packet)
|
||||
if err != nil {
|
||||
return dhcp4.Packet{}, err
|
||||
}
|
||||
|
||||
if !found {
|
||||
log.Println("Warning: It Looks Like Our Leases Are Depleted...")
|
||||
return dhcp4.Packet{}, nil
|
||||
}
|
||||
|
||||
//If the lease is not the one requested We should send a NAK..
|
||||
if len(packetOptions) > 0 && !net.IP(packetOptions[dhcp4.OptionRequestedIPAddress]).Equal(lease.IP) {
|
||||
//NAK
|
||||
declinePacket := s.DeclinePacket(packet)
|
||||
declinePacket.PadToMinSize()
|
||||
|
||||
return declinePacket, nil
|
||||
} else {
|
||||
lease.Status = leasepool.Active
|
||||
lease.MACAddress = packet.CHAddr()
|
||||
|
||||
lease.Expiry = time.Now().Add(s.leaseDuration)
|
||||
|
||||
if packetOptions[dhcp4.OptionHostName] != nil && string(packetOptions[dhcp4.OptionHostName]) != "" {
|
||||
lease.Hostname = string(packetOptions[dhcp4.OptionHostName])
|
||||
}
|
||||
|
||||
updated, err := s.leasePool.UpdateLease(lease)
|
||||
if err != nil {
|
||||
return dhcp4.Packet{}, err
|
||||
}
|
||||
|
||||
if updated {
|
||||
//ACK
|
||||
acknowledgementPacket := s.AcknowledgementPacket(packet)
|
||||
acknowledgementPacket.SetYIAddr(lease.IP)
|
||||
|
||||
//Lease time.
|
||||
acknowledgementPacket.AddOption(dhcp4.OptionIPAddressLeaseTime, dhcp4.OptionsLeaseTime(lease.Expiry.Sub(time.Now())))
|
||||
acknowledgementPacket.PadToMinSize()
|
||||
|
||||
return acknowledgementPacket, nil
|
||||
} else {
|
||||
//NAK
|
||||
declinePacket := s.DeclinePacket(packet)
|
||||
declinePacket.PadToMinSize()
|
||||
|
||||
return declinePacket, nil
|
||||
}
|
||||
}
|
||||
case dhcp4.Decline:
|
||||
//Decline from the client:
|
||||
log.Printf("Debug: Decline Message:%v\n", packet)
|
||||
|
||||
case dhcp4.Release:
|
||||
//Decline from the client:
|
||||
log.Printf("Debug: Release Message:%v\n", packet)
|
||||
|
||||
default:
|
||||
log.Printf("Debug: Unexpected Packet Type:%v\n", dhcp4.MessageType(packetOptions[dhcp4.OptionDHCPMessageType][0]))
|
||||
}
|
||||
|
||||
return dhcp4.Packet{}, nil
|
||||
}
|
||||
|
||||
/*
|
||||
* Create DHCP Offer Packet
|
||||
*/
|
||||
func (s *Server) OfferPacket(discoverPacket dhcp4.Packet) dhcp4.Packet {
|
||||
|
||||
offerPacket := dhcp4.NewPacket(dhcp4.BootReply)
|
||||
offerPacket.SetXId(discoverPacket.XId())
|
||||
offerPacket.SetFlags(discoverPacket.Flags())
|
||||
|
||||
offerPacket.SetCHAddr(discoverPacket.CHAddr())
|
||||
offerPacket.SetGIAddr(discoverPacket.GIAddr())
|
||||
offerPacket.SetSecs(discoverPacket.Secs())
|
||||
|
||||
//53
|
||||
offerPacket.AddOption(dhcp4.OptionDHCPMessageType, []byte{byte(dhcp4.Offer)})
|
||||
//54
|
||||
offerPacket.AddOption(dhcp4.OptionServerIdentifier, s.ip.To4())
|
||||
//51
|
||||
offerPacket.AddOption(dhcp4.OptionIPAddressLeaseTime, dhcp4.OptionsLeaseTime(s.leaseDuration))
|
||||
|
||||
//Other options go in requested order...
|
||||
discoverPacketOptions := discoverPacket.ParseOptions()
|
||||
|
||||
ourOptions := make(dhcp4.Options)
|
||||
|
||||
//1
|
||||
ourOptions[dhcp4.OptionSubnetMask] = s.subnetMask.To4()
|
||||
//3
|
||||
ourOptions[dhcp4.OptionRouter] = s.defaultGateway.To4()
|
||||
//6
|
||||
ourOptions[dhcp4.OptionDomainNameServer] = dhcp4.JoinIPs(s.dnsServers)
|
||||
|
||||
if discoverPacketOptions[dhcp4.OptionParameterRequestList] != nil {
|
||||
//Loop through the requested options and if we have them add them.
|
||||
for _, optionCode := range discoverPacketOptions[dhcp4.OptionParameterRequestList] {
|
||||
if !bytes.Equal(ourOptions[dhcp4.OptionCode(optionCode)], []byte{}) {
|
||||
offerPacket.AddOption(dhcp4.OptionCode(optionCode), ourOptions[dhcp4.OptionCode(optionCode)])
|
||||
delete(ourOptions, dhcp4.OptionCode(optionCode))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Add all the options not requested.
|
||||
for optionCode, optionValue := range ourOptions {
|
||||
offerPacket.AddOption(optionCode, optionValue)
|
||||
}
|
||||
|
||||
return offerPacket
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Create DHCP Acknowledgement
|
||||
*/
|
||||
func (s *Server) AcknowledgementPacket(requestPacket dhcp4.Packet) dhcp4.Packet {
|
||||
|
||||
acknowledgementPacket := dhcp4.NewPacket(dhcp4.BootReply)
|
||||
acknowledgementPacket.SetXId(requestPacket.XId())
|
||||
acknowledgementPacket.SetFlags(requestPacket.Flags())
|
||||
|
||||
acknowledgementPacket.SetGIAddr(requestPacket.GIAddr())
|
||||
acknowledgementPacket.SetCHAddr(requestPacket.CHAddr())
|
||||
acknowledgementPacket.SetSecs(requestPacket.Secs())
|
||||
|
||||
acknowledgementPacket.AddOption(dhcp4.OptionDHCPMessageType, []byte{byte(dhcp4.ACK)})
|
||||
acknowledgementPacket.AddOption(dhcp4.OptionSubnetMask, s.subnetMask.To4())
|
||||
acknowledgementPacket.AddOption(dhcp4.OptionRouter, s.defaultGateway.To4())
|
||||
acknowledgementPacket.AddOption(dhcp4.OptionDomainNameServer, dhcp4.JoinIPs(s.dnsServers))
|
||||
acknowledgementPacket.AddOption(dhcp4.OptionServerIdentifier, s.ip.To4())
|
||||
|
||||
return acknowledgementPacket
|
||||
}
|
||||
|
||||
/*
|
||||
* Create DHCP Decline
|
||||
*/
|
||||
func (s *Server) DeclinePacket(requestPacket dhcp4.Packet) dhcp4.Packet {
|
||||
|
||||
declinePacket := dhcp4.NewPacket(dhcp4.BootReply)
|
||||
declinePacket.SetXId(requestPacket.XId())
|
||||
declinePacket.SetFlags(requestPacket.Flags())
|
||||
|
||||
declinePacket.SetGIAddr(requestPacket.GIAddr())
|
||||
declinePacket.SetCHAddr(requestPacket.CHAddr())
|
||||
declinePacket.SetSecs(requestPacket.Secs())
|
||||
|
||||
declinePacket.AddOption(dhcp4.OptionDHCPMessageType, []byte{byte(dhcp4.NAK)})
|
||||
declinePacket.AddOption(dhcp4.OptionSubnetMask, s.subnetMask.To4())
|
||||
declinePacket.AddOption(dhcp4.OptionRouter, s.defaultGateway.To4())
|
||||
declinePacket.AddOption(dhcp4.OptionDomainNameServer, dhcp4.JoinIPs(s.dnsServers))
|
||||
declinePacket.AddOption(dhcp4.OptionServerIdentifier, s.ip.To4())
|
||||
|
||||
return declinePacket
|
||||
}
|
||||
|
||||
/*
|
||||
* Get Lease tries to work out the best lease for the packet supplied.
|
||||
* Taking into account all Requested IP, Exisitng MACAddresses and Free leases.
|
||||
*/
|
||||
func (s *Server) GetLease(packet dhcp4.Packet) (found bool, lease leasepool.Lease, err error) {
|
||||
packetOptions := packet.ParseOptions()
|
||||
|
||||
//Requested an IP
|
||||
if (len(packetOptions) > 0) &&
|
||||
packetOptions[dhcp4.OptionRequestedIPAddress] != nil &&
|
||||
!net.IP(packetOptions[dhcp4.OptionRequestedIPAddress]).Equal(net.IP{}) {
|
||||
//An IP Has Been Requested Let's Try and Get that One.
|
||||
|
||||
found, lease, err = s.leasePool.GetLease(net.IP(packetOptions[dhcp4.OptionRequestedIPAddress]))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if found {
|
||||
if lease.Status == leasepool.Free {
|
||||
//Lease Is Free you Can Have it.
|
||||
return
|
||||
}
|
||||
if lease.Status != leasepool.Free && bytes.Equal(lease.MACAddress, packet.CHAddr()) {
|
||||
//Lease isn't free but it's yours
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Ok Even if you requested an IP you can't have it.
|
||||
found, lease, err = s.leasePool.GetLeaseForHardwareAddress(packet.CHAddr())
|
||||
if found || err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
//Just get the next free lease if you can.
|
||||
found, lease, err = s.leasePool.GetNextFreeLease()
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
* Shutdown The Server Gracefully
|
||||
*/
|
||||
func (s *Server) Shutdown() {
|
||||
s.shutdownLock.Lock()
|
||||
defer s.shutdownLock.Unlock()
|
||||
s.shutdown = true
|
||||
}
|
||||
|
||||
/*
|
||||
* Garbage Collection
|
||||
* Run Garbage Collection On Your Leases To Free Expired Leases.
|
||||
*/
|
||||
func (s *Server) GC() error {
|
||||
leases, err := s.leasePool.GetLeases()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i := range leases {
|
||||
if leases[i].Status != leasepool.Free {
|
||||
//Lease Is Not Free
|
||||
|
||||
if time.Now().After(leases[i].Expiry) {
|
||||
//Lease has expired.
|
||||
leases[i].Status = leasepool.Free
|
||||
updated, err := s.leasePool.UpdateLease(leases[i])
|
||||
if err != nil {
|
||||
log.Printf("Warning: Error trying to Free Lease %s \"%v\"\n", leases[i].IP.To4().String(), err)
|
||||
}
|
||||
if !updated {
|
||||
log.Printf("Warning: Unable to Free Lease %s\n", leases[i].IP.To4().String())
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
426
vendor/github.com/d2g/dhcp4server/server_test.go
generated
vendored
Normal file
426
vendor/github.com/d2g/dhcp4server/server_test.go
generated
vendored
Normal file
@ -0,0 +1,426 @@
|
||||
package dhcp4server_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"log"
|
||||
"net"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/d2g/dhcp4"
|
||||
"github.com/d2g/dhcp4client"
|
||||
"github.com/d2g/dhcp4server"
|
||||
"github.com/d2g/dhcp4server/leasepool"
|
||||
"github.com/d2g/dhcp4server/leasepool/memorypool"
|
||||
"github.com/d2g/hardwareaddr"
|
||||
)
|
||||
|
||||
/*
|
||||
* Example Server :D
|
||||
*/
|
||||
func ExampleServer() {
|
||||
|
||||
//Create a Lease Pool We're going to use a memory pool
|
||||
//Remember the memory is cleared on restart so you will reissue the same IP Addresses.
|
||||
myMemoryLeasePool := memorypool.MemoryPool{}
|
||||
|
||||
//Lets add a list of IPs to the pool these will be served to the clients so make sure they work for you.
|
||||
// So Create Array of IPs 192.168.1.1 to 192.168.1.30
|
||||
for i := 0; i < 30; i++ {
|
||||
err := myMemoryLeasePool.AddLease(leasepool.Lease{IP: dhcp4.IPAdd(net.IPv4(192, 168, 1, 1), i)})
|
||||
if err != nil {
|
||||
log.Fatalln("Error Adding IP to pool:" + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// We set the port numbers to over 1024 (1067 & 1068) as the automated test don't have root access
|
||||
tServer, err := dhcp4server.New(
|
||||
net.IPv4(192, 168, 1, 201),
|
||||
&myMemoryLeasePool,
|
||||
dhcp4server.SetLocalAddr(net.UDPAddr{IP: net.IPv4(0, 0, 0, 0), Port: 1067}),
|
||||
dhcp4server.SetRemoteAddr(net.UDPAddr{IP: net.IPv4bcast, Port: 1068}),
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalln("Error Configuring Server:" + err.Error())
|
||||
}
|
||||
|
||||
//Start the Server...
|
||||
err = tServer.ListenAndServe()
|
||||
if err != nil {
|
||||
log.Fatalln("Error Starting Server:" + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Test Discovering a Lease That's not Within Our Lease Range.
|
||||
* This Happens When a devce switches network.
|
||||
* Example: Mobile Phone on Mobile internet Has IP 100.123.123.123 Switch To Home Wifi
|
||||
* The device requests 100.123.123.123 on Home Wifi which is out of range...
|
||||
*/
|
||||
func TestDiscoverOutOfRangeLease(test *testing.T) {
|
||||
//Setup the Server
|
||||
myServer, err := dhcp4server.New(
|
||||
net.IPv4(192, 168, 1, 201),
|
||||
getTestLeasePool(),
|
||||
dhcp4server.SetLocalAddr(net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1067}),
|
||||
dhcp4server.SetRemoteAddr(net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1068}),
|
||||
)
|
||||
if err != nil {
|
||||
test.Error("Error: Can't Configure Server " + err.Error())
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
err := myServer.ListenAndServe()
|
||||
if err != nil {
|
||||
log.Fatalln("Error Starting Server:" + err.Error())
|
||||
}
|
||||
}()
|
||||
|
||||
time.Sleep(time.Duration(5) * time.Second)
|
||||
|
||||
//Generate Hardware Address
|
||||
HardwareMACAddress, err := hardwareaddr.GenerateEUI48()
|
||||
if err != nil {
|
||||
test.Error("Error: Can't Generate Valid MACAddress" + err.Error())
|
||||
}
|
||||
|
||||
//Lets Be A Client
|
||||
|
||||
//We need to set the connection ports to 1068 and 1067 so we don't need root access
|
||||
c, err := dhcp4client.NewInetSock(dhcp4client.SetLocalAddr(net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1068}), dhcp4client.SetRemoteAddr(net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1067}))
|
||||
if err != nil {
|
||||
test.Error("Client Conection Generation:" + err.Error())
|
||||
}
|
||||
|
||||
client, err := dhcp4client.New(dhcp4client.HardwareAddr(HardwareMACAddress), dhcp4client.Connection(c))
|
||||
defer client.Close()
|
||||
if err != nil {
|
||||
test.Error("Conection Error:" + err.Error())
|
||||
}
|
||||
|
||||
discoveryPacket := client.DiscoverPacket()
|
||||
discoveryPacket.SetCIAddr(net.IPv4(100, 102, 96, 123))
|
||||
discoveryPacket.PadToMinSize()
|
||||
|
||||
err = client.SendPacket(discoveryPacket)
|
||||
if err != nil {
|
||||
test.Error("Error: Sending Discover Packet" + err.Error())
|
||||
}
|
||||
|
||||
test.Log("--Discovery Packet--")
|
||||
test.Logf("Client IP : %v\n", discoveryPacket.CIAddr().String())
|
||||
test.Logf("Your IP : %v\n", discoveryPacket.YIAddr().String())
|
||||
test.Logf("Server IP : %v\n", discoveryPacket.SIAddr().String())
|
||||
test.Logf("Gateway IP: %v\n", discoveryPacket.GIAddr().String())
|
||||
test.Logf("Client Mac: %v\n", discoveryPacket.CHAddr().String())
|
||||
|
||||
if !bytes.Equal(discoveryPacket.CHAddr(), HardwareMACAddress) {
|
||||
test.Error("MACAddresses Don't Match??")
|
||||
}
|
||||
|
||||
offerPacket, err := client.GetOffer(&discoveryPacket)
|
||||
if err != nil {
|
||||
test.Error("Error Getting Offer:" + err.Error())
|
||||
}
|
||||
|
||||
test.Log("--Offer Packet--")
|
||||
test.Logf("Client IP : %v\n", offerPacket.CIAddr().String())
|
||||
test.Logf("Your IP : %v\n", offerPacket.YIAddr().String())
|
||||
test.Logf("Server IP : %v\n", offerPacket.SIAddr().String())
|
||||
test.Logf("Gateway IP: %v\n", offerPacket.GIAddr().String())
|
||||
test.Logf("Client Mac: %v\n", offerPacket.CHAddr().String())
|
||||
|
||||
requestPacket, err := client.SendRequest(&offerPacket)
|
||||
if err != nil {
|
||||
test.Error("Error Sending Request:" + err.Error())
|
||||
}
|
||||
|
||||
test.Log("--Request Packet--")
|
||||
test.Logf("Client IP : %v\n", requestPacket.CIAddr().String())
|
||||
test.Logf("Your IP : %v\n", requestPacket.YIAddr().String())
|
||||
test.Logf("Server IP : %v\n", requestPacket.SIAddr().String())
|
||||
test.Logf("Gateway IP: %v\n", requestPacket.GIAddr().String())
|
||||
test.Logf("Client Mac: %v\n", requestPacket.CHAddr().String())
|
||||
|
||||
acknowledgement, err := client.GetAcknowledgement(&requestPacket)
|
||||
if err != nil {
|
||||
test.Error("Error Getting Acknowledgement:" + err.Error())
|
||||
}
|
||||
|
||||
test.Log("--Acknowledgement Packet--")
|
||||
test.Logf("Client IP : %v\n", acknowledgement.CIAddr().String())
|
||||
test.Logf("Your IP : %v\n", acknowledgement.YIAddr().String())
|
||||
test.Logf("Server IP : %v\n", acknowledgement.SIAddr().String())
|
||||
test.Logf("Gateway IP: %v\n", acknowledgement.GIAddr().String())
|
||||
test.Logf("Client Mac: %v\n", acknowledgement.CHAddr().String())
|
||||
|
||||
acknowledgementOptions := acknowledgement.ParseOptions()
|
||||
if dhcp4.MessageType(acknowledgementOptions[dhcp4.OptionDHCPMessageType][0]) != dhcp4.ACK {
|
||||
test.Error("Didn't get ACK?:" + err.Error())
|
||||
}
|
||||
|
||||
test.Log("Shutting Down Server")
|
||||
myServer.Shutdown()
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
/*
|
||||
* Try Renewing A Lease From A Different Network.
|
||||
*/
|
||||
func TestRequestOutOfRangeLease(test *testing.T) {
|
||||
//Setup the Server
|
||||
myServer, err := dhcp4server.New(
|
||||
net.IPv4(192, 168, 1, 201),
|
||||
getTestLeasePool(),
|
||||
dhcp4server.SetLocalAddr(net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1067}),
|
||||
dhcp4server.SetRemoteAddr(net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1068}),
|
||||
)
|
||||
if err != nil {
|
||||
test.Error("Error: Can't Configure Server " + err.Error())
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
err := myServer.ListenAndServe()
|
||||
if err != nil {
|
||||
log.Fatalln("Error Starting Server:" + err.Error())
|
||||
}
|
||||
}()
|
||||
|
||||
//Sleep some so the server starts....
|
||||
time.Sleep(time.Duration(5) * time.Second)
|
||||
|
||||
//Generate Hardware Address
|
||||
HardwareMACAddress, err := hardwareaddr.GenerateEUI48()
|
||||
if err != nil {
|
||||
test.Error("Error: Can't Generate Valid MACAddress" + err.Error())
|
||||
}
|
||||
|
||||
HardwareMACAddress, err = net.ParseMAC("58-94-6B-73-57-0C")
|
||||
if err != nil {
|
||||
log.Printf("MAC Error:%v\n", err)
|
||||
}
|
||||
|
||||
//Lets Be A Client
|
||||
c, err := dhcp4client.NewInetSock(dhcp4client.SetLocalAddr(net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1068}), dhcp4client.SetRemoteAddr(net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1067}))
|
||||
if err != nil {
|
||||
test.Error("Client Conection Generation:" + err.Error())
|
||||
}
|
||||
|
||||
client, err := dhcp4client.New(dhcp4client.HardwareAddr(HardwareMACAddress), dhcp4client.Connection(c))
|
||||
defer client.Close()
|
||||
|
||||
if err != nil {
|
||||
test.Error("Conection Error:" + err.Error())
|
||||
}
|
||||
|
||||
//Create a dummy offer packet
|
||||
offerPacket := client.DiscoverPacket()
|
||||
|
||||
offerPacket.SetCIAddr(net.IPv4(100, 102, 96, 123))
|
||||
offerPacket.SetSIAddr(net.IPv4(192, 168, 1, 201))
|
||||
offerPacket.SetYIAddr(net.IPv4(100, 102, 96, 123))
|
||||
offerPacket.AddOption(dhcp4.OptionDHCPMessageType, []byte{byte(dhcp4.Offer)})
|
||||
|
||||
requestPacket, err := client.SendRequest(&offerPacket)
|
||||
if err != nil {
|
||||
test.Error("Error Sending Request:" + err.Error())
|
||||
}
|
||||
|
||||
test.Log("--Request Packet--")
|
||||
test.Logf("Client IP : %v\n", requestPacket.CIAddr().String())
|
||||
test.Logf("Your IP : %v\n", requestPacket.YIAddr().String())
|
||||
test.Logf("Server IP : %v\n", requestPacket.SIAddr().String())
|
||||
test.Logf("Gateway IP: %v\n", requestPacket.GIAddr().String())
|
||||
test.Logf("Client Mac: %v\n", requestPacket.CHAddr().String())
|
||||
|
||||
acknowledgement, err := client.GetAcknowledgement(&requestPacket)
|
||||
if err != nil {
|
||||
test.Error("Error Getting Acknowledgement:" + err.Error())
|
||||
}
|
||||
|
||||
test.Log("--Acknowledgement Packet--")
|
||||
test.Logf("Client IP : %v\n", acknowledgement.CIAddr().String())
|
||||
test.Logf("Your IP : %v\n", acknowledgement.YIAddr().String())
|
||||
test.Logf("Server IP : %v\n", acknowledgement.SIAddr().String())
|
||||
test.Logf("Gateway IP: %v\n", acknowledgement.GIAddr().String())
|
||||
test.Logf("Client Mac: %v\n", acknowledgement.CHAddr().String())
|
||||
|
||||
acknowledgementOptions := acknowledgement.ParseOptions()
|
||||
if len(acknowledgementOptions[dhcp4.OptionDHCPMessageType]) <= 0 || dhcp4.MessageType(acknowledgementOptions[dhcp4.OptionDHCPMessageType][0]) != dhcp4.NAK {
|
||||
test.Errorf("Didn't get NAK got DHCP4 Message Type:%v\n", dhcp4.MessageType(acknowledgementOptions[dhcp4.OptionDHCPMessageType][0]))
|
||||
}
|
||||
|
||||
test.Log("Shutting Down Server")
|
||||
myServer.Shutdown()
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
func TestConsumeLeases(test *testing.T) {
|
||||
//Setup the Server
|
||||
myServer, err := dhcp4server.New(
|
||||
net.IPv4(127, 0, 0, 1),
|
||||
getTestLeasePool(),
|
||||
)
|
||||
if err != nil {
|
||||
test.Error("Error: Can't Configure Server " + err.Error())
|
||||
}
|
||||
|
||||
// Setup A Client
|
||||
// Although We Won't send the packets over the network we'll use the client to create the requests.
|
||||
c, err := dhcp4client.NewInetSock(dhcp4client.SetLocalAddr(net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1068}), dhcp4client.SetRemoteAddr(net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1067}))
|
||||
if err != nil {
|
||||
test.Error("Client Conection Generation:" + err.Error())
|
||||
}
|
||||
|
||||
client, err := dhcp4client.New(dhcp4client.Connection(c))
|
||||
if err != nil {
|
||||
test.Error("Error: Can't Configure Client " + err.Error())
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
for i := 0; i < 30; i++ {
|
||||
//Generate Hardware Address
|
||||
HardwareMACAddress, err := hardwareaddr.GenerateEUI48()
|
||||
if err != nil {
|
||||
test.Error("Error: Can't Generate Valid MACAddress" + err.Error())
|
||||
}
|
||||
|
||||
client.SetOption(dhcp4client.HardwareAddr(HardwareMACAddress))
|
||||
test.Log("MAC:" + HardwareMACAddress.String())
|
||||
|
||||
discovery := client.DiscoverPacket()
|
||||
|
||||
//Run the Discovery On the Server
|
||||
offer, err := myServer.ServeDHCP(discovery)
|
||||
_, err = myServer.ServeDHCP(discovery)
|
||||
if err != nil {
|
||||
test.Error("Discovery Error:" + err.Error())
|
||||
}
|
||||
|
||||
request := client.RequestPacket(&offer)
|
||||
acknowledgement, err := myServer.ServeDHCP(request)
|
||||
if err != nil {
|
||||
test.Error("Acknowledge Error:" + err.Error())
|
||||
}
|
||||
|
||||
test.Logf("Received Lease:%v\n", acknowledgement.YIAddr().String())
|
||||
if !dhcp4.IPAdd(net.IPv4(192, 168, 1, 1), i).Equal(acknowledgement.YIAddr()) {
|
||||
test.Error("Expected IP:" + dhcp4.IPAdd(net.IPv4(192, 168, 1, 1), i).String() + " Received:" + acknowledgement.YIAddr().String())
|
||||
}
|
||||
|
||||
//How long the lease is for?
|
||||
acknowledgementOptions := acknowledgement.ParseOptions()
|
||||
if len(acknowledgementOptions) > 0 {
|
||||
test.Logf("Lease Options:%v\n", acknowledgementOptions)
|
||||
if acknowledgementOptions[dhcp4.OptionIPAddressLeaseTime] != nil {
|
||||
var result uint32
|
||||
buf := bytes.NewBuffer(acknowledgementOptions[dhcp4.OptionIPAddressLeaseTime])
|
||||
binary.Read(buf, binary.BigEndian, &result)
|
||||
test.Logf("Lease Time (Seconds):%d\n", result)
|
||||
}
|
||||
} else {
|
||||
test.Errorf("Lease:\"%v\" Has No Options\n", acknowledgement.YIAddr())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Benchmark the ServeDHCP Function
|
||||
*/
|
||||
func BenchmarkServeDHCP(test *testing.B) {
|
||||
//Create a Lease Pool We're going to use a memory pool
|
||||
//Remember the memory is cleared on restart so you will reissue the same IP Addresses.
|
||||
myMemoryLeasePool := memorypool.MemoryPool{}
|
||||
|
||||
//Lets add a list of IPs to the pool these will be served to the clients so make sure they work for you.
|
||||
// So Create Array of IPs 192.168.1.1 to 192.168.1.30
|
||||
for i := 0; i < test.N; i++ {
|
||||
err := myMemoryLeasePool.AddLease(leasepool.Lease{IP: dhcp4.IPAdd(net.IPv4(192, 168, 1, 1), i)})
|
||||
if err != nil {
|
||||
log.Fatalln("Error Adding IP to pool:" + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
//Setup the Server
|
||||
myServer, err := dhcp4server.New(
|
||||
net.IPv4(127, 0, 0, 1),
|
||||
&myMemoryLeasePool,
|
||||
)
|
||||
if err != nil {
|
||||
test.Error("Error: Can't Configure Server " + err.Error())
|
||||
}
|
||||
|
||||
//Setup A Client
|
||||
// Although We Won't send the packets over the network we'll use the client to create the requests.
|
||||
c, err := dhcp4client.NewInetSock(dhcp4client.SetLocalAddr(net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1068}), dhcp4client.SetRemoteAddr(net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1067}))
|
||||
if err != nil {
|
||||
test.Error("Client Conection Generation:" + err.Error())
|
||||
}
|
||||
|
||||
client, err := dhcp4client.New(dhcp4client.Connection(c))
|
||||
if err != nil {
|
||||
test.Error("Error: Can't Configure Client " + err.Error())
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
test.ResetTimer()
|
||||
|
||||
for i := 0; i < test.N; i++ {
|
||||
test.StopTimer()
|
||||
//Generate Hardware Address
|
||||
HardwareMACAddress, err := hardwareaddr.GenerateEUI48()
|
||||
if err != nil {
|
||||
test.Error("Error: Can't Generate Valid MACAddress" + err.Error())
|
||||
}
|
||||
|
||||
client.SetOption(dhcp4client.HardwareAddr(HardwareMACAddress))
|
||||
discovery := client.DiscoverPacket()
|
||||
|
||||
//Run the Discovery On the Server
|
||||
test.StartTimer()
|
||||
offer, err := myServer.ServeDHCP(discovery)
|
||||
if err != nil {
|
||||
test.Error("Discovery Error:" + err.Error())
|
||||
}
|
||||
|
||||
if len(offer) == 0 {
|
||||
test.Error("No Valid Offer")
|
||||
} else {
|
||||
request := client.RequestPacket(&offer)
|
||||
_, err := myServer.ServeDHCP(request)
|
||||
if err != nil {
|
||||
test.Error("Acknowledge Error:" + err.Error())
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getTestLeasePool() *memorypool.MemoryPool {
|
||||
//Create a Lease Pool We're going to use a memory pool
|
||||
//Remember the memory is cleared on restart so you will reissue the same IP Addresses.
|
||||
myMemoryLeasePool := memorypool.MemoryPool{}
|
||||
|
||||
//Lets add a list of IPs to the pool these will be served to the clients so make sure they work for you.
|
||||
// So Create Array of IPs 192.168.1.1 to 192.168.1.30
|
||||
for i := 0; i < 30; i++ {
|
||||
err := myMemoryLeasePool.AddLease(leasepool.Lease{IP: dhcp4.IPAdd(net.IPv4(192, 168, 1, 1), i)})
|
||||
if err != nil {
|
||||
log.Fatalln("Error Adding IP to pool:" + err.Error())
|
||||
}
|
||||
}
|
||||
return &myMemoryLeasePool
|
||||
}
|
Reference in New Issue
Block a user