basic UDP server bound to an interface
This commit is contained in:
15
server/BUILD.bazel
Normal file
15
server/BUILD.bazel
Normal file
@@ -0,0 +1,15 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "server",
|
||||
srcs = [
|
||||
"ifi.go",
|
||||
"server.go",
|
||||
],
|
||||
importpath = "git.wntrmute.dev/kyle/kdhcp/server",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//config",
|
||||
"//log",
|
||||
],
|
||||
)
|
||||
39
server/ifi.go
Normal file
39
server/ifi.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func BindInterface(ip net.IP, port int, dev string) (net.PacketConn, error) {
|
||||
if port == 0 {
|
||||
port = 67
|
||||
}
|
||||
|
||||
udpAddr := &net.UDPAddr{
|
||||
IP: ip,
|
||||
Port: port,
|
||||
}
|
||||
|
||||
conn, err := net.ListenUDP("udp4", udpAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sysconn, err := conn.SyscallConn()
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sysconn.Control(func(fd uintptr) {
|
||||
err = syscall.BindToDevice(int(fd), dev)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return conn, nil
|
||||
}
|
||||
76
server/server.go
Normal file
76
server/server.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
|
||||
"git.wntrmute.dev/kyle/kdhcp/config"
|
||||
"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) {
|
||||
s.Conn, err = BindInterface(s.Config.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) WriteTo(b []byte, addr net.Addr) error {
|
||||
return errors.New("server: not implemented")
|
||||
}
|
||||
|
||||
func (s *Server) AcceptPacket() error {
|
||||
packet, addr, err := s.ReadFrom()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Debugf("accepted %d byte packet from %s", len(packet), addr)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) Listen() {
|
||||
for {
|
||||
if err := s.AcceptPacket(); err != nil {
|
||||
log.Errf("server: error reading packet: %s", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user