190 lines
4.4 KiB
Go
190 lines
4.4 KiB
Go
|
package dhcp
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"encoding/binary"
|
||
|
"fmt"
|
||
|
"net"
|
||
|
"time"
|
||
|
|
||
|
"git.loafle.net/commons_go/logging"
|
||
|
"git.loafle.net/overflow/overflow_discovery/api/module/discovery/model"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
MAGIC_COOKIE uint32 = 0x63825363
|
||
|
OPT_CODE_SERVER_IDENTIFIER uint8 = 54
|
||
|
OPT_CODE_SUBNET_MASK uint8 = 1
|
||
|
OPT_CODE_ROUTER uint8 = 3
|
||
|
OPT_CODE_DNS uint8 = 6
|
||
|
)
|
||
|
|
||
|
type dhcpDiscover struct {
|
||
|
MsgType byte
|
||
|
HwType byte
|
||
|
HwAddrLen byte
|
||
|
Hops byte
|
||
|
Xid uint32
|
||
|
Secs uint16
|
||
|
BootpFlags uint16
|
||
|
ClientIp uint32
|
||
|
YourIp uint32
|
||
|
NextServerIp uint32
|
||
|
RelayAgentIp uint32
|
||
|
ClientMacAddr [6]byte
|
||
|
ClientHwAddrPadding [10]byte
|
||
|
ServerHostName [64]byte
|
||
|
BootFileName [128]byte
|
||
|
MagicCookie uint32
|
||
|
Mtype byte
|
||
|
MtypeLen byte
|
||
|
MtypeVal byte
|
||
|
Opts [200]byte
|
||
|
End byte
|
||
|
Padding [16]byte
|
||
|
}
|
||
|
|
||
|
func DiscoverDHCP(zone *model.DiscoveryZone) {
|
||
|
err := sendDHCPDiscovery()
|
||
|
if err != nil {
|
||
|
logging.Logger().Error(fmt.Sprintf("Discovery: DHCP Matcher %v", err))
|
||
|
return
|
||
|
}
|
||
|
recvDHCPOffer(zone)
|
||
|
}
|
||
|
|
||
|
func sendDHCPDiscovery() error {
|
||
|
dhcp := dhcpDiscover{
|
||
|
MsgType: 0x01,
|
||
|
HwType: 0x01,
|
||
|
HwAddrLen: 0x06,
|
||
|
Hops: 0x00,
|
||
|
Xid: 0x00000000,
|
||
|
Secs: 0x0000,
|
||
|
ClientIp: 0x00000000,
|
||
|
YourIp: 0x00000000,
|
||
|
NextServerIp: 0x00000000,
|
||
|
RelayAgentIp: 0x00000000,
|
||
|
MagicCookie: MAGIC_COOKIE,
|
||
|
Mtype: 0x35,
|
||
|
MtypeLen: 0x01,
|
||
|
MtypeVal: 0x01,
|
||
|
End: 0xff,
|
||
|
}
|
||
|
|
||
|
var flag uint16 = 0
|
||
|
dhcp.BootpFlags = ^flag // flag = unicast , ^flag = broadcast
|
||
|
|
||
|
//TODO : getting mac addr from zone
|
||
|
//dhcp.ClientMacAddr[0] = 0x50
|
||
|
//dhcp.ClientMacAddr[1] = 0xe5
|
||
|
//dhcp.ClientMacAddr[2] = 0x49
|
||
|
//dhcp.ClientMacAddr[3] = 0x46
|
||
|
//dhcp.ClientMacAddr[4] = 0x93
|
||
|
//dhcp.ClientMacAddr[5] = 0x28
|
||
|
|
||
|
writer := new(bytes.Buffer)
|
||
|
binary.Write(writer, binary.BigEndian, dhcp)
|
||
|
conn, err := net.Dial("udp", "255.255.255.255:67")
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
conn.Write(writer.Bytes())
|
||
|
defer conn.Close()
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func recvDHCPOffer(zone *model.DiscoveryZone) {
|
||
|
|
||
|
socket, err := net.ListenUDP("udp4", &net.UDPAddr{
|
||
|
IP: net.IPv4(255, 255, 255, 255),
|
||
|
Port: 68,
|
||
|
})
|
||
|
if err != nil {
|
||
|
logging.Logger().Error(fmt.Sprintf("Discovery: DHCP Matcher %v", err))
|
||
|
return
|
||
|
}
|
||
|
err = socket.SetDeadline(time.Now().Add(3 * time.Second))
|
||
|
if err != nil {
|
||
|
logging.Logger().Error(fmt.Sprintf("Discovery: DHCP Matcher %v", err))
|
||
|
return
|
||
|
}
|
||
|
|
||
|
buf := make([]byte, 4096)
|
||
|
n, _, err := socket.ReadFromUDP(buf)
|
||
|
if err != nil {
|
||
|
logging.Logger().Error(fmt.Sprintf("Discovery: DHCP Matcher %v", err))
|
||
|
return
|
||
|
}
|
||
|
if n <= 0 {
|
||
|
logging.Logger().Error(fmt.Sprintf("Discovery: DHCP Matcher has no DHCP offer."))
|
||
|
return
|
||
|
}
|
||
|
|
||
|
offer := dhcpDiscover{}
|
||
|
|
||
|
reader := new(bytes.Buffer)
|
||
|
reader.Write(buf)
|
||
|
if err := binary.Read(reader, binary.BigEndian, &offer); err != nil {
|
||
|
logging.Logger().Error(fmt.Sprintf("Discovery: DHCP Matcher %v", err))
|
||
|
return
|
||
|
}
|
||
|
if offer.MagicCookie != MAGIC_COOKIE {
|
||
|
logging.Logger().Error(fmt.Sprintf("Discovery: DHCP Matcher is not a DHCP packet."))
|
||
|
return
|
||
|
}
|
||
|
|
||
|
//option searching
|
||
|
r := new(bytes.Buffer)
|
||
|
r.Write(offer.Opts[:])
|
||
|
|
||
|
for i := 0; i < r.Len(); i++ {
|
||
|
v := r.Next(1)[0]
|
||
|
|
||
|
if v == OPT_CODE_SUBNET_MASK && r.Next(1)[0] == 4 {
|
||
|
ipStr := byteToIpString(r.Next(4))
|
||
|
logging.Logger().Info(fmt.Sprintf("Discovery: DHCP Matcher SUBNET MASK: %s", ipStr))
|
||
|
}
|
||
|
|
||
|
if v == OPT_CODE_ROUTER && r.Next(1)[0] == 4 {
|
||
|
ipStr := byteToIpString(r.Next(4))
|
||
|
logging.Logger().Info(fmt.Sprintf("Discovery: DHCP Matcher ROUTER: %s", ipStr))
|
||
|
}
|
||
|
|
||
|
if v == OPT_CODE_DNS {
|
||
|
len := r.Next(1)[0]
|
||
|
var dns []string = make([]string, 0)
|
||
|
var ipStr string
|
||
|
ipStr = byteToIpString(r.Next(4))
|
||
|
dns = append(dns, ipStr)
|
||
|
if len == 8 {
|
||
|
ipStr = byteToIpString(r.Next(4))
|
||
|
dns = append(dns, ipStr)
|
||
|
}
|
||
|
logging.Logger().Info(fmt.Sprintf("Discovery: DHCP Matcher DNS: %s", dns))
|
||
|
}
|
||
|
|
||
|
if v == OPT_CODE_SERVER_IDENTIFIER && r.Next(1)[0] == 4 {
|
||
|
ipStr := byteToIpString(r.Next(4))
|
||
|
logging.Logger().Info(fmt.Sprintf("Discovery: DHCP Matcher DHCP SERVER: %s", ipStr))
|
||
|
}
|
||
|
}
|
||
|
logging.Logger().Sync()
|
||
|
|
||
|
}
|
||
|
|
||
|
func byteToIpString(b []byte) string {
|
||
|
var ipStr string
|
||
|
len := len(b)
|
||
|
for i := 0; i < len; i++ {
|
||
|
v := b[i]
|
||
|
ipStr += fmt.Sprintf("%d", v)
|
||
|
if i < len-1 {
|
||
|
ipStr += "."
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ipStr
|
||
|
}
|