package dhcp import ( "bytes" "encoding/binary" "fmt" "net" "time" "git.loafle.net/commons_go/logging" ) 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() { err := sendDHCPDiscovery() if err != nil { logging.Logger().Error(fmt.Sprintf("Discovery: DHCP Matcher %v", err)) return } recvDHCPOffer() } 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() { 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 }