static void PollNow(object o) { //Debug.WriteLine("Poll Now"); if (nic != null && nic.IsLinkUp) { if (!Adapter.DhcpDisabled && AreRenewing && IPAddress != null) { DHCP.SendMessage(DHCP.Request); } else if (!Adapter.DhcpDisabled && IPAddress == null) { DHCP.SendMessage(DHCP.Discover); } if (Adapter.IPAddress != null && Adapter.Gateway != null && Adapter.GatewayMac == null) { ARP.SendARP_Probe(Adapter.Gateway); } if (IPAddress != null) { ARP.SendARP_Gratuitus(); } } }
// event handler for new ethernet frame arrivals static void nic_OnFrameArrived(ENC28J60Driver sender, byte[] frame, DateTime timeReceived) { //if (buf[0] == 0x01) //{ // Debug.WriteLine("Probable Multicast Message Detected - " + buf.Length.ToString()); // if (buf[29] == 0x65) Debug.WriteLine("IP ending in 101"); //} //if (buf[29] == 0x65) //{ // Debug.WriteLine("IP ending in 101 - size: " + buf.Length.ToString()); // if (buf.Length == 541) // Debug.WriteLine("What is this? "); //} //var packetID = Guid.NewGuid().ToString(); if (frame == null) { return; } //Debug.WriteLine("Memory: " + Microsoft.SPOT.Debug.GC(false).ToString() + ", packetID = " + packetID + ", age = " + timeReceived.Subtract(DateTime.Now).Seconds + "s, size = " + frame.Length + ", addys = " + Utility.ExtractRangeFromArray(frame, 0, 14).ToAddress()); if (frame[13] == 0x06 && frame[12] == 0x08) // ARP Packet Type { if (IPAddress != null) { // If message request, and IP matches ours, we need to respond! if (frame[41] == IPAddress[3] && frame[40] == IPAddress[2] && frame[39] == IPAddress[1] && frame[38] == IPAddress[0]) { ARP.HandlePacket(frame); } else if (frame[21] == 0x02 && frame[31] == IPAddress[3] && frame[30] == IPAddress[2] && frame[29] == IPAddress[1] && frame[28] == IPAddress[0]) { Debug.WriteLine("Possible IP Address Conflict Detected"); Adapter.Stop(); // IP Address Conflict! //TODO: if DHCP is enabled, don't stop the networking! Just reset and get a new IP!!!! } } } else if (frame[13] == 0x00 && frame[12] == 0x08) // Handle IP packets { if (frame[23] == 0x01) // Protocol 1 -- PING { // Debug.WriteLine("Received ICMP (Ping) Packet -- " + frame.Length + " bytes"); ICMP.HandlePacket(frame); } else if (frame[23] == 0x11) // Protocol 17 -- UDP { if (frame[37] == 0x44 && !DhcpDisabled && frame[36] == 0x00) // DHCP port 68 -- Order of conditions to short-circuit earlier! { //Debug.WriteLine("Received DHCP Packet -- " + frame.Length + " bytes"); DHCP.HandlePacket(frame); } else if (frame[37] == 0x89 && frame[36] == 0x00 && Name != null && Name != string.Empty && IPAddress != null) // NetBIOS port 137 and name is set { //Debug.WriteLine("Received NBNS Packet -- " + frame.Length + " bytes"); // Uncomment the line below to enable Netbios over TCP Name resolution NetBiosNaming.HandlePacket(frame); } else if (frame[35] == 0x35 && frame[34] == 0x00) // DNS Source Port of 53 (0x35h) { //Debug.WriteLine("Received DNS Packet -- " + frame.Length + " bytes"); DNS.HandlePacket(frame); } else if (frame[37] == 0xe9 && frame[36] == 0x14 && frame[35] == 0xe9 && frame[34] == 0x14 && Name != null && Name != string.Empty && IPAddress != null) // mDNS Source and Destination Port of 5353 or LLMNR Destination Port of 5355 { //Debug.WriteLine("Received MDNS Packet -- " + frame.Length + " bytes"); MDNS.HandlePacket(frame); } else if (frame[37] == 0xeb && frame[36] == 0x14 && Name != null && Name != string.Empty && IPAddress != null) { // Debug.WriteLine("Received LLMNR Packet -- " + frame.Length + " bytes"); LLMNR.HandlePacket(frame); } else if (OnUdpReceivedPacketEvent != null && IPAddress != null) // Check Listening ports { //Debug.WriteLine("Received UDP Packet -- " + frame.Length + " bytes"); foreach (byte[] aPort in ListeningPorts.Values) { if (aPort[0] == frame[36] && aPort[1] == frame[37]) { UDP.HandlePacket(frame); } } } } else if (frame[23] == 0x06 && IPAddress != null) // Protocol 6 -- TCP { //Debug.WriteLine("Received TCP Packet -- " + frame.Length + " bytes"); foreach (byte[] aPort in ListeningPorts.Values) { if (aPort[0] == frame[36] && aPort[1] == frame[37]) { TCP.HandlePacket(frame); return; } } // Handle a response from a currently open connection ulong conID = TCP.GenerateConnectionID(frame); if (TCP.Connections.Contains(conID)) { TCP.HandlePacket(frame); } //else //TODO: Send a RST as a response to a closed port. //var port = (new byte[2] { frame[36], frame[37] }).ToShort(); //foreach (Connection aCon in TCP.Connections) //{ // if (aCon.LocalPort == port) // TCP.HandlePacket(frame); // return; //} } } // All other packets are ignored... like throwing back a fish :) //Debug.WriteLine("Memory: " + Microsoft.SPOT.Debug.GC(false).ToString() + ", packetID = " + packetID); //Microsoft.SPOT.Debug.EnableGCMessages(true); }
/// <summary> /// Take care of a packet of DHCP stuff /// </summary> /// <param name="payload"></param> public static void HandlePacket(byte[] payload) { //Debug.WriteLine("Handling DHCP packet"); // Check Transaction ID! if (transactionID == null || payload[46] != transactionID[0] || payload[47] != transactionID[1] || payload[48] != transactionID[2] || payload[49] != transactionID[3]) { return; } // To determine the type, we need to find the magic cookie, then find option 0x35h // 02 == Offer, 05 == ACK, 06 = NAK var options = ParseOptions(payload); //Debug.WriteLine("DHCP PKT"); if (options.Contains("53")) { //Debug.WriteLine("Rec'd DHCP OFFER - 1"); if (((byte[])(options["53"]))[0] == 0x02) // Offer { //Debug.WriteLine("Rec'd DHCP OFFER"); ushort ipHeaderLength = (ushort)((payload[14] & 0x0f) * 4); PendingIpAddress = Utility.ExtractRangeFromArray(payload, ipHeaderLength + 38, 4); if (options.Contains("54")) { Adapter.Gateway = (byte[])options["54"]; // DHCP Server } if (options.Contains("6")) { Adapter.DomainNameServer = (byte[])options["6"]; // DNS Server } if (options.Contains("1")) { Adapter.SubnetMask = (byte[])options["1"]; // Subnet } if (options.Contains("3")) { Adapter.Gateway = (byte[])options["3"]; // Router } if (options.Contains("58")) { RenewTimer.Change((int)(((byte[])options["58"]).ToInt() * 1050), TwoHoursInMilliseconds); // Got a Renew time } if (options.Contains("51")) { RenewTimer.Change((int)(((byte[])options["51"]).ToInt() * 750), TwoHoursInMilliseconds); // Got a Lease Time (I am using 750, so we renew after 75% of lease has been consumed) } Adapter.GatewayMac = Utility.ExtractRangeFromArray(payload, 6, 6); // Initial gateway MAC. Will get confirmed/updated by an ARP Probe SendMessage(DHCP.Request); } else if (((byte[])options["53"])[0] == 0x05) // ACK or Acknowledgement { // Parse out the Gateway, DNS Servers, IP address, and apply set all the variables with it... //Debug.WriteLine("Rec'd DHCP ACK"); if (options.Contains("54")) { Adapter.Gateway = (byte[])options["54"]; // DHCP Server } if (options.Contains("6")) { Adapter.DomainNameServer = (byte[])options["6"]; // DNS Server } if (options.Contains("1")) { Adapter.SubnetMask = (byte[])options["1"]; // Subnet } if (options.Contains("3")) { Adapter.Gateway = (byte[])options["3"]; // Router } if (options.Contains("58")) { RenewTimer.Change((int)(((byte[])options["58"]).ToInt() * 1050), TwoHoursInMilliseconds); // Got a Renew time } if (options.Contains("51")) { RenewTimer.Change((int)(((byte[])options["51"]).ToInt() * 750), TwoHoursInMilliseconds); // Got a Lease Time (I am using 750, so we renew after 75% of lease has been consumed) } Adapter.GatewayMac = Utility.ExtractRangeFromArray(payload, 6, 6); // Initial gateway MAC. Will get confirmed/updated by an ARP Probe transactionID = null; Adapter.AreRenewing = false; Adapter.IPAddress = PendingIpAddress ?? Adapter.IPAddress; Adapter.startupHold.Set(); // This will release the Adapter.Start() Method! (if waiting) Debug.WriteLine("DHCP SUCCESS! We have an IP Address - " + Adapter.IPAddress.ToAddress() + "; Gateway: " + Adapter.Gateway.ToAddress()); ARP.SendARP_Probe(Adapter.Gateway); // Confirm Gateway MAC address } else if (((byte[])options["53"])[0] == 0x06) // NACK or Not Acknowledged! { Debug.WriteLine("DHCP N-ACK"); transactionID = null; Adapter.AreRenewing = false; // We have failed to get an IP address for some reason...! Adapter.IPAddress = null; Adapter.Gateway = null; Adapter.GatewayMac = null; } } }