func (_ requestRebindState) do(ctx *dhcpContext) iState { ipAddr := ctx.IpAddr.Load().(net.IP) // Set up all the layers' fields we can. eth := &layers.Ethernet{ SrcMAC: ctx.MacAddr, DstMAC: arp.HwAddrBcast, EthernetType: layers.EthernetTypeIPv4, } ipv4 := &layers.IPv4{ Version: 4, TTL: 255, Protocol: layers.IPProtocolUDP, SrcIP: net.IPv4zero, DstIP: net.IPv4bcast, } udp := &layers.UDP{ SrcPort: network.Bootpc, DstPort: network.Bootps, } udp.SetNetworkLayerForChecksum(ipv4) buf := network.GetBuffer() defer network.ReleaseBuffer(buf) request := new(dhcpv4.DhcpPacket) request.ConstructWithPreAllocatedBuffer(buf, option.DHCPREQUEST) request.SetXid(ctx.xid[:]) request.SetMacAddr(ctx.MacAddr) opt50 := new(option.Option50RequestedIpAddress) opt50.Construct(util.Convert4byteToUint32(ipAddr)) request.AddOption(opt50) opt61 := new(option.Option61ClientIdentifier) opt61.Construct(byte(1), ctx.MacAddr) request.AddOption(opt61) if DhcRelay { request.SetGiAddr(ctx.giaddr) request.AddOption(generateOption82(ctx.MacAddr)) } if Option90 { request.AddOption(generateOption90(ctx.login)) } bootp := &layer.PayloadLayer{ Contents: request.Raw, } for { // send request for err := network.SentPacket(eth, ipv4, udp, bootp); err != nil; { log.Println(ctx.MacAddr, "REBIND: error sending request", err) time.Sleep(2 * time.Second) } var ( payload []byte timeout time.Duration deadline = time.Now().Add(2 * time.Second) ) for { timeout = deadline.Sub(time.Now()) select { case <-time.After(timeout): log.Println(ctx.MacAddr, "REBIND: timeout") return timeoutRebindState{} case payload = <-ctx.dhcpIn: dp, err := dhcpv4.Parse(payload) if err != nil { // it is not DHCP packet... continue } if !bytes.Equal(ctx.xid[:], dp.GetXid()) { // bug of DHCP Server ? log.Println(ctx.MacAddr, fmt.Sprintf("REBIND: unexpected xid [Expected: 0x%v] [Actual: 0x%v]", hex.EncodeToString(ctx.xid[:]), hex.EncodeToString(dp.GetXid()))) continue } if msgType, err := dp.GetTypeMessage(); err == nil { switch msgType { case option.DHCPACK: ctx.t0, ctx.t1, ctx.t2 = extractAllLeaseTime(dp) return sleepState{} case option.DHCPNAK: log.Println(ctx.MacAddr, "REBIND: receive NAK") return discoverState{} default: log.Println(ctx.MacAddr, fmt.Sprintf("REBIND: unexpected message [Excpected: %s] [Actual: %s]", option.DHCPACK, msgType)) continue } } else { log.Println(ctx.MacAddr, "REBIND: option 53 is missing") continue } } } } }
func fuzzParse(data []byte) (int, *DhcpPacket, option.SpecificOption) { var o option.SpecificOption p, err := Parse(data) if err != nil { if p != nil { panic("packet != nil on error") } return 0, nil, o } if p == nil { panic("packet == nil when no error") } if !p.ContainsMagicCookie() { panic("No magic Cookie...") } if p.GetMacAddr() == nil { panic("MacAddr is nil") } if len(p.GetMacAddr()) > 16 { panic("MacAddr is greater than 16") } { // option 53 opt := new(option.Option53MessageType) if f, e := p.GetOption(opt); e == nil { if f { if opt.GetLength() != 1 { panic("len opt53 != 1") } if len(opt.GetValue()) != int(opt.GetLength()) { panic("len opt53 inconsistency") } o = opt } } } { // option 51 and all TypeUint32 option type (e.g. option 54, option 58, option 59 ...) opt := new(option.Option51IpAddressLeaseTime) if f, e := p.GetOption(opt); e == nil { if f { if opt.GetLength() != 4 { panic("len opt51 != 4") } if len(opt.GetValue()) != int(opt.GetLength()) { panic("len opt51 inconsistency") } o = opt } } } { // option 82 opt := new(option.Option82DhcpAgentOption) if f, e := p.GetOption(opt); e == nil { if f { if len(opt.GetValue()) != int(opt.GetLength()) { panic("len opt82 inconsistency") } { // option 82.1 ssOpt := new(option.Option82_1CircuitId) opt.GetSubOptions(ssOpt) } { // option 82.2 ssOpt := new(option.Option82_2RemoteId) opt.GetSubOptions(ssOpt) } { // option 82.9 ssOpt := new(option.Option82_9VendorSpecificInformation) _, _ = opt.GetSubOptions(ssOpt) } o = opt } } } { // option 60 and all TypeString option type (option 15 ...) opt := new(option.Option60VendorClassIdentifier) if f, e := p.GetOption(opt); e == nil { if f { if len(opt.GetString()) != int(opt.GetLength()) { panic("len opt60 inconsistency") } } } } { // option 6 and all TypeListUint32 option type (option 10, option 11 ...) opt := new(option.Option6DomainNameServerOption) if f, e := p.GetOption(opt); e == nil { if f { if len(opt.GetValue()) != int(opt.GetLength()) { panic("len opt6 inconsistency") } } } } { // option 119 opt := new(option.Option119DomainSearch) if f, e := p.GetOption(opt); e == nil { if f { _ = opt.GetSearchString() } } } { // option 120 opt := new(option.Option120SipServers) if f, e := p.GetOption(opt); e == nil { if f { switch opt.GetEnc() { case option.ENC_FQDN: fqdns, e := opt.GetFqdnList() if e != nil && fqdns != nil { panic("opt120 ENC_FQDN fqdns != nil on error") } case option.ENC_IP: addrs, e := opt.GetIpAddresses() if e != nil && addrs != nil { panic("opt120 ENC_IP addrs != nil on error") } default: panic("opt120 with ENC_UNKNOWN is not possible to have error == nil on p.GetOption(opt)") } } } } { // option 119 opt := new(option.Option119DomainSearch) if f, e := p.GetOption(opt); e == nil { if f { _ = opt.GetSearchString() } } } { // option 61 opt := new(option.Option61ClientIdentifier) if f, e := p.GetOption(opt); e == nil { if f { _ = opt.GetClientIdentifier() } } } { // option 77 opt := new(option.Option77UserClass) if f, e := p.GetOption(opt); e == nil { if f { if len(opt.GetValue()) != int(opt.GetLength()) { panic("len opt77 inconsistency") } for _, uc := range opt.UserClassDatas { if len(uc.GetUcData()) != int(uc.GetUcLen()) { panic("opt77 UserClass len inconsistency") } } } } } { // option 90 opt := new(option.Option90Authentificiation) if f, e := p.GetOption(opt); e == nil { if f { opt.GetProtocol() opt.GetAlgorithm() opt.GetRdm() opt.GetReplayDetection() opt.GetAuthenticationInformation() } } } { // option 121 opt := new(option.Option121ClasslessStaticRoute) p.GetOption(opt) } return 1, p, o }