overflow_discovery/service/matcher/dhcp/dhcp.go

190 lines
4.4 KiB
Go
Raw Normal View History

2017-11-21 12:47:55 +00:00
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
}