public void ArpRequest(IPv4 sourceIP, IPv4 targetIP, Multiplexer !targetMux, ArpRequestCallback callback, object cookie, TimeSpan timeout) { // //XXXX Check pending request does not already exist! // EthernetAddress localMac = targetMux.Adapter.HardwareAddress; AddPendingRequest(targetIP, callback, cookie, timeout); // initiate an arp request... DebugPrint("Initiating request " + "({0},{1}) --> ({2},{3})\n", sourceIP, localMac, targetIP, EthernetAddress.Zero); byte[] data = new byte[ArpFormat.Size + EthernetFormat.Size]; int pos = EthernetFormat.Write(data, 0, localMac, EthernetAddress.Broadcast, EthernetFormat.PROTOCOL_ARP); ArpFormat.Write(data, pos, localMac, sourceIP, ArpFormat.Type.ARP_REQUEST, EthernetAddress.Zero, targetIP); NetPacket pkt = new NetPacket(data); pkt.Mux = targetMux; OnProtocolSend(pkt); }
/// // ARP logic: see RFC 826 http://www.faqs.org/rfcs/rfc826.html // public NetStatus OnProtocolReceive(NetPacket !pkt) { NetStatus res = NetStatus.Code.PROTOCOL_OK; Debug.Assert(pkt != null); ArpFormat.Type opcode; EthernetAddress senderMAC, targetMAC; IPv4 senderIP, targetIP; bool ok = ArpFormat.Read(pkt, out opcode, out senderMAC, out senderIP, out targetMAC, out targetIP); DebugPrint("ARP RESPONSE\n"); // check for problems if (ok == false) { DebugPrint("ARP READ ERROR\n"); return(NetStatus.Code.PROTOCOL_DROP_ERROR); } bool merged = false; bool updated = false; ArpEntry target = arpTable.Lookup(senderIP); if (target != null && target.Dynamic == true) { DebugPrint("ARP UPDATE\n"); // we have it already - just update the details... target.MacAddress = senderMAC; target.EntryAge = arpTable.Age; merged = true; updated = true; } bool forSelf = ipModule.HostConfiguration.IsLocalAddress(targetIP); if (forSelf == false) { return(NetStatus.Code.PROTOCOL_OK); } if (merged == false) { DebugPrint("ARP ADDITION\n"); arpTable.AddEntry(new ArpEntry(senderIP, senderMAC, true)); merged = true; UpdatePendingRequests(senderIP, senderMAC); } // now figure out the opcode if (opcode == ArpFormat.Type.ARP_REQUEST) { DebugPrint("Handling request ({0},{1}) ---> ({2},{3})\n", senderIP, senderMAC, targetIP, targetMAC ); // send reply... // we reuse the received packet for sending a fast response // so we should NOT return it to the Demux's free list!!! // (we replace it with a new one instead) // we use the adapter from which the request arrived // (available in the context) Multiplexer mux = Core.Instance().GetMuxForAdapter((IAdapter !)pkt.AdapterContext); if (mux == null) { // some internal bug, for now just panic Core.Panic("At ArpModule.PacketReceive: " + "context isn't Multiplexer!\n"); assert(false); } int dataLength = EthernetFormat.Size + ArpFormat.Size; if (dataLength < pkt.Length) { dataLength = pkt.Length; } byte[] !data = new byte[dataLength]; Array.Copy(pkt.GetRawData(), 0, data, 0, pkt.Length); ArpFormat.CreateArpReply(ref data, targetIP, mux.Adapter.HardwareAddress); mux.SendDirect(new NetPacket(data)); } else { // otherwise we are done DebugPrint( "Handling reply ({2},{3}) <--- ({0},{1})\n", senderIP, senderMAC, targetIP, targetMAC ); } if (merged && !updated) { DebugPrint(arpTable.ToString()); } return(res); }