func (c *client) isCompletePacket(p *dhcp.Packet) bool { complete := !ip.IsUnspecifiedIP(p.YourIP()) && !ip.IsUnspecifiedIP(p.ServerIP()) if !complete { return false } for _, param := range c.params { switch dhcp4.OptionCode(param) { case dhcp4.OptionSubnetMask: ones, bits := p.SubnetMask().Size() if ones == 0 || bits == 0 { return false } case dhcp4.OptionRouter: if ip.IsUnspecifiedIP(p.Gateway()) { return false } case dhcp4.OptionDomainNameServer: if len(p.DNS()) == 0 { return false } } } if p.LeaseTime().Seconds() == 0 { return false } return true }
/* * 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 }
func GetOffer() (ip net.IP, subnet net.IPNet, err error) { ip = nil subnet.IP = nil subnet.Mask = nil // Generate a random mac address for this request hwaddr, e := GenerateMacAddr() if e != nil { err = e return } // Setup DHCP socket //socket, e := dhcp4client.NewInetSock(local_addr, remote_addr) socket, e := dhcp4client.NewInetSock() if e != nil { err = e return } // Setup DHCP client client, e := dhcp4client.New( dhcp4client.HardwareAddr(hwaddr), dhcp4client.Connection(socket), ) // Send a DHCPREQUEST result, packet, e := client.Request() if !result { msg := fmt.Sprintf("DHCPREQUEST failed: %v", e) err = errors.New(msg) return } if e != nil { networkError, ok := e.(*net.OpError) if ok && networkError.Timeout() { msg := fmt.Sprintf("Cannot find DHCP server: %v", networkError) err = errors.New(msg) } else { msg := fmt.Sprintf("DHCPREQUEST failed: %v", networkError) err = errors.New(msg) } return } // Determine the netmask of the network options := packet.ParseOptions() mask := make(net.IPMask, net.IPv4len) mask = options[dhcp4.OptionCode(dhcp4.OptionSubnetMask)] // Setup the return structures ip = packet.YIAddr() subnet.IP = ip.To4().Mask(mask) subnet.Mask = mask return }