From d92e7f61917098a18368c6a914693c38076995ef Mon Sep 17 00:00:00 2001 From: nadoo <287492+nadoo@users.noreply.github.com> Date: Thu, 10 Jun 2021 20:09:21 +0800 Subject: [PATCH] dhcpd: support static ip address for mac --- README.md | 4 ++-- config/glider.conf.example | 5 +++-- go.mod | 4 ++-- go.sum | 4 ++++ service/dhcpd/dhcpd.go | 29 ++++++++++++++++++++++++----- service/dhcpd/pool.go | 13 +++++++++++++ 6 files changed, 48 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index ee4b761..d49ee3d 100644 --- a/README.md +++ b/README.md @@ -363,8 +363,8 @@ Examples: ## Service - dhcpd: - - service=dhcpd,INTERFACE,START_IP,END_IP - - e.g., service=dhcpd,eth1,192.168.50.100,192.168.50.199 + - service=dhcpd,INTERFACE,START_IP,END_IP,LEASE_MINUTES[,MAC=IP,MAC=IP...] + - e.g., service=dhcpd,eth1,192.168.50.100,192.168.50.199,720,fc:23:ab:9e:25:01=192.168.2.101 ## Linux Service diff --git a/config/glider.conf.example b/config/glider.conf.example index 2db7b63..36e515a 100644 --- a/config/glider.conf.example +++ b/config/glider.conf.example @@ -241,9 +241,10 @@ dnsrecord=www.example.com/1.2.3.4 dnsrecord=www.example.com/2606:2800:220:1:248:1893:25c8:1946 # SERVICES -# service=dhcpd,INTERFACE,START_IP,END_IP +# service=dhcpd,INTERFACE,START_IP,END_IP,LEASE_MINUTES[,MAC=IP,MAC=IP...] # e.g.: -# service=dhcpd,eth1,192.168.50.100,192.168.50.199 +# service=dhcpd,eth1,192.168.1.100,192.168.1.199,720 +# service=dhcpd,eth2,192.168.2.100,192.168.2.199,720,fc:23:ab:9e:25:01=192.168.2.101,fc:23:ab:9e:25:02=192.168.2.102 # INTERFACE SPECIFIC # ------------------ diff --git a/go.mod b/go.mod index 9fb5b0b..270391e 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/dgryski/go-idea v0.0.0-20170306091226-d2fb45a411fb github.com/dgryski/go-rc2 v0.0.0-20150621095337-8a9021637152 github.com/ebfe/rc2 v0.0.0-20131011165748-24b9757f5521 // indirect - github.com/insomniacslk/dhcp v0.0.0-20210528123148-fb4eaaa00ad2 + github.com/insomniacslk/dhcp v0.0.0-20210608085346-465dd6c35f6c github.com/klauspost/cpuid/v2 v2.0.6 // indirect github.com/klauspost/reedsolomon v1.9.12 // indirect github.com/mdlayher/raw v0.0.0-20210412142147-51b895745faf // indirect @@ -19,7 +19,7 @@ require ( github.com/xtaci/kcp-go/v5 v5.6.1 golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a golang.org/x/net v0.0.0-20210525063256-abc453219eb5 // indirect - golang.org/x/sys v0.0.0-20210603125802-9665404d3644 // indirect + golang.org/x/sys v0.0.0-20210608053332-aa57babbf139 // indirect ) // Replace dependency modules with local developing copy diff --git a/go.sum b/go.sum index b90c019..e2169cf 100644 --- a/go.sum +++ b/go.sum @@ -41,6 +41,8 @@ github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714 h1:/jC7qQFrv8 github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Goc3h8EklBH5mspfHFxBnEoURQCGzQQH1ga9Myjvis= github.com/insomniacslk/dhcp v0.0.0-20210528123148-fb4eaaa00ad2 h1:WDOgJoE6rb7G6A7i1/Yyh5FJeydXeUrXHMRYJo7iFak= github.com/insomniacslk/dhcp v0.0.0-20210528123148-fb4eaaa00ad2/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E= +github.com/insomniacslk/dhcp v0.0.0-20210608085346-465dd6c35f6c h1:L3EHIOG1DrTVG4aBnY+Vu0s2t/KkgrV0AYkO7BSwu3M= +github.com/insomniacslk/dhcp v0.0.0-20210608085346-465dd6c35f6c/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E= github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw= github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGuG/smIU4J/54PblvSbh+xvCZmpJnFgr3ds6Z55XMQ= github.com/jsimonetti/rtnetlink v0.0.0-20201009170750-9c6f07d100c1/go.mod h1:hqoO/u39cqLeBLebZ8fWdE96O7FxrAsRYhnVOdgHxok= @@ -159,6 +161,8 @@ golang.org/x/sys v0.0.0-20210601080250-7ecdf8ef093b h1:qh4f65QIVFjq9eBURLEYWqaEX golang.org/x/sys v0.0.0-20210601080250-7ecdf8ef093b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603125802-9665404d3644 h1:CA1DEQ4NdKphKeL70tvsWNdT5oFh1lOjihRcEDROi0I= golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210608053332-aa57babbf139 h1:C+AwYEtBp/VQwoLntUmQ/yx3MS9vmZaKNdw5eOpoQe8= +golang.org/x/sys v0.0.0-20210608053332-aa57babbf139/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/service/dhcpd/dhcpd.go b/service/dhcpd/dhcpd.go index e889c11..11b1ded 100644 --- a/service/dhcpd/dhcpd.go +++ b/service/dhcpd/dhcpd.go @@ -4,6 +4,8 @@ import ( "context" "errors" "net" + "strconv" + "strings" "time" "github.com/insomniacslk/dhcp/dhcpv4" @@ -24,29 +26,46 @@ type dpcpd struct{} // Run runs the service. func (*dpcpd) Run(args ...string) { - if len(args) < 3 { + if len(args) < 4 { log.F("[dhcpd] not enough parameters, exiting") return } - iface := args[0] + iface, startIP, endIP, leaseMin := args[0], args[1], args[2], args[3] + if i, err := strconv.Atoi(leaseMin); err != nil { + leaseTime = time.Duration(i) * time.Minute + } + ip, mask, err := intfaceIP4(iface) if err != nil { log.F("[dhcpd] get ip of interface '%s' error: %s", iface, err) return } - if findExistServer(iface) { + if existsServer(iface) { log.F("[dhcpd] found existing dhcp server on interface %s, service exiting", iface) return } - pool, err := NewPool(leaseTime, net.ParseIP(args[1]), net.ParseIP(args[2])) + pool, err := NewPool(leaseTime, net.ParseIP(startIP), net.ParseIP(endIP)) if err != nil { log.F("[dhcpd] error in pool init: %s", err) return } + // static ips + for _, host := range args[4:] { + pair := strings.Split(host, "=") + if len(pair) == 2 { + mac, err := net.ParseMAC(pair[0]) + if err != nil { + break + } + ip := net.ParseIP(pair[1]) + pool.LeaseStaticIP(mac, ip) + } + } + laddr := net.UDPAddr{IP: net.IPv4(0, 0, 0, 0), Port: 67} server, err := server4.NewServer(iface, &laddr, handleDHCP(ip, mask, pool)) if err != nil { @@ -118,7 +137,7 @@ func handleDHCP(serverIP net.IP, mask net.IPMask, pool *Pool) server4.Handler { } } -func findExistServer(iface string) (exists bool) { +func existsServer(iface string) (exists bool) { client, err := nclient4.New(iface) if err != nil { log.F("[dhcpd] failed in dhcp client creation: %s", err) diff --git a/service/dhcpd/pool.go b/service/dhcpd/pool.go index 6b483d7..6a98247 100644 --- a/service/dhcpd/pool.go +++ b/service/dhcpd/pool.go @@ -87,6 +87,19 @@ func (p *Pool) LeaseIP(mac net.HardwareAddr) (net.IP, error) { return nil, errors.New("no more ip can be leased") } +// LeaseStaticIP leases static ip from pool according to the given mac. +func (p *Pool) LeaseStaticIP(mac net.HardwareAddr, ip net.IP) { + p.mutex.Lock() + defer p.mutex.Unlock() + + for _, item := range p.items { + if item.ip.Equal(ip) { + item.mac = mac + item.expire = time.Now().Add(time.Hour * 24 * 365 * 50) // 50 years + } + } +} + // ReleaseIP releases ip from pool according to the given mac. func (p *Pool) ReleaseIP(mac net.HardwareAddr) { p.mutex.Lock()