dhcp test

This commit is contained in:
insanity 2018-08-29 16:48:24 +09:00
parent 01b201266c
commit 69c2837a31
2 changed files with 57 additions and 105 deletions

View File

@ -5,41 +5,12 @@ import (
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"net" "net"
"strings"
)
const ( "github.com/google/gopacket/layers"
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 { "github.com/google/gopacket"
MsgType byte gl "github.com/google/gopacket/layers"
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 doDiscover(address string) (map[string]string, error) { func doDiscover(address string) (map[string]string, error) {
@ -51,13 +22,9 @@ func doDiscover(address string) (map[string]string, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
if err != nil {
return nil, err
}
defer conn.Close() defer conn.Close()
sendDiscover(conn) // broadcast 255.255.255.255:67 sendDiscover(conn) // broadcast 255.255.255.255:67
return readOffer(conn) // unicast return readOffer(conn) // unicast
} }
@ -70,32 +37,27 @@ func sendDiscover(conn *net.UDPConn) error {
return err return err
} }
dhcp := dhcpDiscover{ dhcp := &gl.DHCPv4{Operation: gl.DHCPOpRequest, HardwareType: gl.LinkTypeEthernet, Xid: 0x12345678,
MsgType: 0x01, ClientIP: net.IP{0, 0, 0, 0}, YourClientIP: net.IP{0, 0, 0, 0}, NextServerIP: net.IP{0, 0, 0, 0}, RelayAgentIP: net.IP{0, 0, 0, 0},
HwType: 0x01, ClientHWAddr: net.HardwareAddr{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc},
HwAddrLen: 0x06, ServerName: make([]byte, 64), File: make([]byte, 128)}
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.Options = append(dhcp.Options, gl.NewDHCPOption(gl.DHCPOptMessageType, []byte{byte(gl.DHCPMsgTypeDiscover)}))
dhcp.BootpFlags = ^flag // flag = unicast , ^flag = broadcast dhcp.Options = append(dhcp.Options, gl.NewDHCPOption(gl.DHCPOptHostname, []byte{'o', 'v', 'e', 'r', 'f', 'l', 'o', 'w', '.', 'c', 'o', 'm'}))
dhcp.Options = append(dhcp.Options, gl.NewDHCPOption(gl.DHCPOptPad, nil))
dhcp.Options = append(dhcp.Options, gl.NewDHCPOption(gl.DHCPOptParamsRequest,
[]byte{byte(gl.DHCPOptSubnetMask), byte(gl.DHCPOptBroadcastAddr), byte(gl.DHCPOptTimeOffset),
byte(gl.DHCPOptRouter), byte(gl.DHCPOptDomainName), byte(gl.DHCPOptDNS), byte(gl.DHCPOptDomainSearch),
byte(gl.DHCPOptHostname), byte(gl.DHCPOptNetBIOSTCPNS), byte(gl.DHCPOptInterfaceMTU), byte(gl.DHCPOptClasslessStaticRoute),
byte(gl.DHCPOptNTPServers)}))
writer := new(bytes.Buffer) buf := gopacket.NewSerializeBuffer()
if err := binary.Write(writer, binary.BigEndian, dhcp); err != nil { opts := gopacket.SerializeOptions{FixLengths: true}
err = gopacket.SerializeLayers(buf, opts, dhcp)
if err != nil {
return err return err
} }
_, err = conn.WriteToUDP(writer.Bytes(), serverAddr) _, err = conn.WriteToUDP(buf.Bytes(), serverAddr)
if err != nil { if err != nil {
return err return err
} }
@ -107,62 +69,52 @@ func readOffer(conn *net.UDPConn) (map[string]string, error) {
offerOptions := make(map[string]string) offerOptions := make(map[string]string)
buf := make([]byte, 1024) buf := make([]byte, 1024)
_, _, err := conn.ReadFromUDP(buf) n, _, err := conn.ReadFromUDP(buf)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if n <= 0 {
offer := dhcpDiscover{} return nil, fmt.Errorf("%s", "Emptry response.")
reader := new(bytes.Buffer)
reader.Write(buf)
if err := binary.Read(reader, binary.BigEndian, &offer); err != nil {
return nil, err
}
if offer.MagicCookie != MAGIC_COOKIE {
return nil, err
} }
//option searching var dhcp gl.DHCPv4
r := new(bytes.Buffer) decoded := []gopacket.LayerType{}
r.Write(offer.Opts[:]) parser := gopacket.NewDecodingLayerParser(gl.LayerTypeDHCPv4, &dhcp)
if err = parser.DecodeLayers(buf, &decoded); err != nil {
for i := 0; i < r.Len(); i++ { return nil, err
v := r.Next(1)[0] }
for _, layerType := range decoded {
if v == OPT_CODE_SUBNET_MASK && r.Next(1)[0] == 4 { switch layerType {
ipStr := byteToIPString(r.Next(4)) case layers.LayerTypeDHCPv4:
offerOptions["SUBNETMASK"] = ipStr for _, opt := range dhcp.Options {
} switch opt.Type {
case gl.DHCPOptServerID:
if v == OPT_CODE_ROUTER && r.Next(1)[0] == 4 { offerOptions["DHCP_SERVER"] = optDataToIPString(opt.Data)
ipStr := byteToIPString(r.Next(4)) break
offerOptions["ROUTER"] = ipStr case gl.DHCPOptLeaseTime:
} var sec int32
if err = binary.Read(bytes.NewReader(opt.Data), binary.BigEndian, &sec); err == nil {
if v == OPT_CODE_DNS { offerOptions["LEASE_TIME"] = fmt.Sprintf("%d", sec)
len := r.Next(1)[0] }
var dns []string break
var ipStr string case gl.DHCPOptSubnetMask:
ipStr = byteToIPString(r.Next(4)) offerOptions["SUBNET_MASK"] = optDataToIPString(opt.Data)
dns = append(dns, ipStr) break
if len == 8 { case gl.DHCPOptRouter:
ipStr = byteToIPString(r.Next(4)) offerOptions["ROUTER"] = optDataToIPString(opt.Data)
dns = append(dns, ipStr) break
case gl.DHCPOptDNS:
offerOptions["DNS_SERVER"] = optDataToIPString(opt.Data)
break
}
} }
offerOptions["DNS"] = strings.Join(dns, ",")
}
if v == OPT_CODE_SERVER_IDENTIFIER && r.Next(1)[0] == 4 {
ipStr := byteToIPString(r.Next(4))
offerOptions["DHCP_SERVER"] = ipStr
} }
} }
return offerOptions, nil return offerOptions, nil
} }
func byteToIPString(b []byte) string { func optDataToIPString(b []byte) string {
var ipStr string var ipStr string
len := len(b) len := len(b)
for i := 0; i < len; i++ { for i := 0; i < len; i++ {

View File

@ -5,7 +5,7 @@ import (
) )
func TestDHCP(t *testing.T) { func TestDHCP(t *testing.T) {
offer, err := doDiscover("192.168.1.201") offer, err := doDiscover("192.168.1.203")
if err != nil { if err != nil {
t.Errorf("ERROR : %s", err.Error()) t.Errorf("ERROR : %s", err.Error())
} }