Example #1
0
// YourIP returns the YIP field in the packet (this is IP assigned by server to the client)
func (p *Packet) YourIP() net.IP {
	if len(p.Packet) == 0 {
		return nil
	}

	return dhcp4.Packet(p.Packet).YIAddr()
}
Example #2
0
/*
 * Retreive Acknowledgement
 * Wait for the offer for a specific Request Packet.
 */
func (c *Client) GetAcknowledgement(requestPacket *dhcp4.Packet) (dhcp4.Packet, error) {
	for {
		c.connection.SetReadTimeout(c.timeout)
		readBuffer, source, err := c.connection.ReadFrom()
		if err != nil {
			return dhcp4.Packet{}, err
		}

		acknowledgementPacket := dhcp4.Packet(readBuffer)
		acknowledgementPacketOptions := acknowledgementPacket.ParseOptions()

		// Ignore Servers in my Ignore list
		for _, ignoreServer := range c.ignoreServers {
			if source.Equal(ignoreServer) {
				continue
			}

			if acknowledgementPacket.SIAddr().Equal(ignoreServer) {
				continue
			}
		}

		if !bytes.Equal(requestPacket.XId(), acknowledgementPacket.XId()) || len(acknowledgementPacketOptions[dhcp4.OptionDHCPMessageType]) < 1 || (dhcp4.MessageType(acknowledgementPacketOptions[dhcp4.OptionDHCPMessageType][0]) != dhcp4.ACK && dhcp4.MessageType(acknowledgementPacketOptions[dhcp4.OptionDHCPMessageType][0]) != dhcp4.NAK) {
			continue
		}

		return acknowledgementPacket, nil
	}
}
Example #3
0
/*
 * Retreive Offer...
 * Wait for the offer for a specific Discovery Packet.
 */
func (c *Client) GetOffer(discoverPacket *dhcp4.Packet) (dhcp4.Packet, error) {
	for {
		c.connection.SetReadTimeout(c.timeout)
		readBuffer, source, err := c.connection.ReadFrom()
		if err != nil {
			return dhcp4.Packet{}, err
		}

		offerPacket := dhcp4.Packet(readBuffer)
		offerPacketOptions := offerPacket.ParseOptions()

		// Ignore Servers in my Ignore list
		for _, ignoreServer := range c.ignoreServers {
			if source.Equal(ignoreServer) {
				continue
			}

			if offerPacket.SIAddr().Equal(ignoreServer) {
				continue
			}
		}

		if len(offerPacketOptions[dhcp4.OptionDHCPMessageType]) < 1 || dhcp4.MessageType(offerPacketOptions[dhcp4.OptionDHCPMessageType][0]) != dhcp4.Offer || !bytes.Equal(discoverPacket.XId(), offerPacket.XId()) {
			continue
		}

		return offerPacket, nil
	}

}
Example #4
0
func (c *client) Renew(id ID, ack *dhcp.Packet) (*dhcp.Packet, error) {
	c.Lock()
	defer c.Unlock()

	log.Debugf("renewing IP %s", ack.YourIP())

	cl, err := c.newClient(ack)
	if err != nil {
		return nil, err
	}
	defer cl.Close()

	p := dhcp4.Packet(ack.Packet)
	var newack dhcp4.Packet
	err = withRetry(func() error {
		var err error
		newack, err = c.renew(id, p, cl)
		return err
	})

	if err != nil {
		return nil, err
	}

	return dhcp.NewPacket([]byte(newack)), nil
}
Example #5
0
func (c *client) Release(ack *dhcp.Packet) error {
	c.Lock()
	defer c.Unlock()

	log.Debugf("releasing IP %s", ack.YourIP())

	cl, err := c.newClient(ack)
	if err != nil {
		return err
	}
	defer cl.Close()

	return withRetry(func() error {
		return cl.Release(dhcp4.Packet(ack.Packet))
	})
}
Example #6
0
/*
 * 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.shutdown {
			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
				}
			}
		}

	}
}
Example #7
0
func NewPacket(p []byte) *Packet {
	return &Packet{Packet: p, Options: Options(dhcp4.Packet(p).ParseOptions())}
}