package server import ( "errors" "net" "git.wntrmute.dev/kyle/kdhcp/config" "git.wntrmute.dev/kyle/kdhcp/dhcp" "git.wntrmute.dev/kyle/kdhcp/log" ) const ( MaxPacketSize = 512 ) type Server struct { Conn net.PacketConn Config *config.Config } func (s *Server) Close() error { return s.Conn.Close() } func (s *Server) Bind() (err error) { // In order to read DHCP packets, we'll need to listen on all addresses. ip := net.IP([]byte{0, 0, 0, 0}) s.Conn, err = BindInterface(ip, s.Config.Port, s.Config.Interface) return err } func (s *Server) ReadFrom() ([]byte, net.Addr, error) { b := make([]byte, MaxPacketSize) n, addr, err := s.Conn.ReadFrom(b) if err != nil { return nil, nil, err } b = b[:n] return b, addr, nil } func (s *Server) ReadDHCPRequest() (*dhcp.BootRequest, error) { pkt, addr, err := s.ReadFrom() if err != nil { return nil, err } log.Debugf("server: read %db packet from %s", len(pkt), addr) return dhcp.ReadRequest(pkt) } func (s *Server) WriteTo(b []byte, addr net.Addr) error { return errors.New("server: not implemented") } func (s *Server) AcceptPacket() error { request, err := s.ReadDHCPRequest() if err != nil { return err } log.Debugf("BOOTP request received from %x", request.HardwareAddress) return nil } func (s *Server) Listen() { for { if err := s.AcceptPacket(); err != nil { log.Errf("server: error reading packet: %s", err) continue } break } } func New(cfg *config.Config) (*Server, error) { srv := &Server{ Config: cfg, } err := srv.Bind() if err != nil { return nil, err } log.Infof("server: bound to %s:%s", cfg.Interface, srv.Conn.LocalAddr()) return srv, nil }