/* * 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()) } }
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 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 }
func StartDHCPService(configuration *Configuration) { //This allows us to deactivate DHCP if configuration.DHCP.Disabled { log.Println("Warning: DHCP is disabled by configuration (config.json)") return } leasePool, err := datastore.GetLeaseHelper() if err != nil { log.Fatal("Unable to Start Lease Pool") } //Lets work out the number of leases numLeases := dhcp4.IPRange(net.ParseIP(configuration.DHCP.Leases.Start), net.ParseIP(configuration.DHCP.Leases.End)) //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 < numLeases; i++ { err = leasePool.AddLease(leasepool.Lease{IP: dhcp4.IPAdd(net.ParseIP(configuration.DHCP.Leases.Start), i)}) if err != nil { log.Fatalln("Error Adding IPs to pool:" + err.Error()) } } //If we don't have an IP configured then use the first Active IP interface (warn if there is more than 1) if configuration.DHCP.Server.IP == nil || configuration.DHCP.Server.IP.Equal(net.IPv4(0, 0, 0, 0)) { //Get IP And Subnet (Windows doesn't seem to give subnet) mainActiveIPNetwork, err := networktools.MainActiveIPNetwork() if err != nil { log.Fatalln("Error Getting Local Interfaces:" + err.Error()) } if mainActiveIPNetwork.IP.Equal(net.IP{}) { log.Fatal("No Interface Found With a Valid IP") } configuration.DHCP.Server.IP = mainActiveIPNetwork.IP if !bytes.Equal(mainActiveIPNetwork.Mask, net.IPMask{}) && (configuration.DHCP.Server.SubnetMask == nil || configuration.DHCP.Server.SubnetMask.Equal(net.IPv4(0, 0, 0, 0))) { configuration.DHCP.Server.SubnetMask = net.ParseIP(mainActiveIPNetwork.Mask.String()) } } //Make Sure we Now have a Subnet Mask if configuration.DHCP.Server.SubnetMask == nil || configuration.DHCP.Server.SubnetMask.Equal(net.IPv4(0, 0, 0, 0)) { log.Fatalln("DHCP SubnetMask Missing in Configuration and Unable to Calculate...") } //If For some reason We've setup alternative DNS servers (I Can't think why we should) use them otherwise add ourself. if configuration.DHCP.Server.DNSServers == nil || len(configuration.DHCP.Server.DNSServers) == 0 { configuration.DHCP.Server.DNSServers = append(configuration.DHCP.Server.DNSServers, configuration.DHCP.Server.IP) } else { log.Printf("Warning: Using Preconfigured DNS Servers %v\n", configuration.DHCP.Server.DNSServers) } //If For some reason We've setup alternative Gateway (I Can't think why we should) use them otherwise add ourself. if configuration.DHCP.Server.DefaultGateway == nil { configuration.DHCP.Server.DefaultGateway = configuration.DHCP.Server.IP } else { log.Printf("Warning: Using Preconfigured Default Gateway %v\n", configuration.DHCP.Server.DefaultGateway) } //Create The Server myServer := dhcp4server.Server{} myServer.Configuration = &configuration.DHCP.Server myServer.LeasePool = leasePool //Start GC on the Leases. go func() { for { select { case <-time.After(configuration.DHCP.Server.LeaseDuration): } err := myServer.GC() if err != nil { log.Printf("Error: DHCP GC Failed Error: \"%v\"\n", err) return } } }() //Start the Server... err = myServer.ListenAndServe() if err != nil { log.Fatalln("Error Starting Server:" + err.Error()) } }
/* * 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 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()) } } }