private void UpdatePendingRequests(IPv4 ipAddress, EthernetAddress macAddress) { using (pendingRequestsLock.Lock()) { //Sigh...we're missing a linked list in the current Singularity C# runtime foreach (PendingArpRequest pendingRequest in pendingRequests) { VTable.Assert(pendingRequest != null); if (pendingRequest.address == ipAddress) { pendingRequest.active = false; DebugStub.WriteLine("found waiting arp request...sending on out"); VectorQueueByte txBuffer = pendingRequest.txContainer.Acquire(); Bytes header = txBuffer.ExtractHead(); Bytes buffer = txBuffer.ExtractHead(); VTable.Assert(header != null); VTable.Assert(buffer != null); pendingRequest.txContainer.Release(txBuffer); //Format ethernet header EthernetHeader.Write(header, pendingRequest.localMac, macAddress, EthernetHeader.PROTOCOL_IP); //send it! VTable.Assert(pendingRequest.adapter != null); pendingRequest.adapter.PopulateTxRing(header, buffer); continue; } } } }
public void ArpRequest(IPv4 sourceIP, IPv4 targetIP, EthernetAddress localMac, Bytes header, Bytes buffer, IAdapter adapter) { // AutoResetEvent requestComplete = AddPendingRequest(targetIP, TimeSpan.FromSeconds(3), localMac, header, buffer, adapter); // initiate an arp request... DebugPrint("Initiating request " + "({0},{1}) --> ({2},{3})\n", sourceIP, localMac, targetIP, EthernetAddress.Zero); //eventially we'll want to follow Orion's conservation of //packets philosophy Bytes arpHeader = new Bytes(new byte [EthernetHeader.Size]); Bytes arpMsg = new Bytes(new byte [ArpHeader.Size]); //xxx I'd like to get rid of EthernetHeader eventually... EthernetHeader.Write(arpHeader, localMac, EthernetAddress.Broadcast, EthernetHeader.PROTOCOL_ARP); ArpHeader.Write(arpMsg, localMac, sourceIP, ArpHeader.ARP_REQUEST, EthernetAddress.Zero, targetIP); adapter.PopulateTxRing(arpHeader, arpMsg); // DebugPrint("ArpRequest: waiting for reply\n"); //requestComplete.WaitOne(); // DebugPrint("ArpRequest: reply received!\n"); }
internal bool Send(EthernetAddress dstAddr, DhcpFormat dhcp) { int packetSize = dhcp.Size; int headerSize = EthernetHeader.Size + UDPHeader.Size + IpHeader.Size; Bytes packet = new Bytes(new byte [packetSize]); Bytes header = new Bytes(new byte [headerSize]); // Write out DHCP packet dhcp.Write(packet, 0); //the correct ports/addresses should already be bound up in instance of the UDP object udp.WriteCompleteUDPHeader(header, packet, dhcp.Size); // Add Ethernet Header EthernetHeader.Write(header, adapter.HardwareAddress, dstAddr, EthernetHeader.PROTOCOL_IP); adapter.PopulateTxRing(header, packet); return(true); }
// Original note from Yaron: // ARP logic: see RFC 826 http://www.faqs.org/rfcs/rfc826.html // public void ProcessIncomingPacket(Bytes packet, IAdapter adapter) { //Get the ARP packet info located after the ethernet header ArpHeader arpHeader = new ArpHeader(packet, 14); DebugPrint("ARP: ProcessIncomingPacket\n"); //do some checks to make sure the packet is copacetic if (arpHeader.htype != 0x1) { DebugPrint("ARP: ProcessIncomingPacket got wrong hardware type? 0x{0,8:x}\n", arpHeader.htype); //delete packet; return; } if (arpHeader.ptype != 0x0800) { DebugPrint("ARP: ProcessIncomingPacket got wrong protocol? 0x{0,8:x}\n", arpHeader.ptype); //delete packet; return; } //ethernet address should be 6 bytes if (arpHeader.hlen != 6) { DebugPrint("ARP: ProcessIncomingPacket got wrong hw length? 0x{0,8:x}\n", arpHeader.hlen); //delete packet; return; } if (arpHeader.plen != 4) { DebugPrint("ARP: ProcessIncomingPacket got wrong protocol address length? 0x{0,8:x}\n", arpHeader.plen); //delete packet; return; } DebugPrint("Incoming packet\n"); bool merged = false; bool updated = false; ArpEntry target = arpTable.Lookup(arpHeader.senderIPAddr); if (target != null && target.Dynamic == true) { DebugPrint("ARP UPDATE\n"); // we have it already - just update the details... target.MacAddress = arpHeader.senderEthernetAddr; target.EntryAge = arpTable.Age; merged = true; updated = true; } if (merged == false) { DebugPrint("ARP ADDITION\n"); arpTable.AddEntry(new ArpEntry(arpHeader.senderIPAddr, arpHeader.senderEthernetAddr, true)); merged = true; UpdatePendingRequests(arpHeader.senderIPAddr, arpHeader.senderEthernetAddr); } //Is this a local address bool forSelf = IP.IsLocalAddress(arpHeader.destIPAddr); if (forSelf == false) { //delete packet; return; } // now figure out the opcode if (arpHeader.op == ARP_REQUEST) { DebugPrint("Handling request ({0},{1}) ---> ({2},{3} \npkt dest {4} {5})\n", arpHeader.senderIPAddr, arpHeader.senderEthernetAddr, arpHeader.destIPAddr, adapter.HardwareAddress, arpHeader.destIPAddr, arpHeader.destEthernetAddr ); int dataLength = EthernetHeader.Size + ArpHeader.Size; VTable.Assert(packet.Length >= dataLength); Bytes data = Bitter.SplitOff(ref packet, EthernetHeader.Size); EthernetHeader.Write(packet, adapter.HardwareAddress, arpHeader.senderEthernetAddr, EthernetHeader.PROTOCOL_ARP); //use arp header to format reply ArpHeader.Write(data, adapter.HardwareAddress, arpHeader.destIPAddr, ArpHeader.ARP_REPLY, arpHeader.senderEthernetAddr, arpHeader.senderIPAddr); adapter.PopulateTxRing(packet, data); } else { // otherwise we are done DebugPrint( "Handling reply ({2},{3}) <--- ({0},{1})\n", arpHeader.senderIPAddr, arpHeader.senderEthernetAddr, arpHeader.destIPAddr, arpHeader.destEthernetAddr ); //delete packet; } if (merged && !updated) { DebugPrint(arpTable.ToString()); } }
//This function will format the higher layer packet to //have to correct ethernet and ip header? //Routing to multiple cards was broken in the old netstack... //for now we support a single interface //ipheader is already written...we just need to write the ethernet header public static void SendOutgoingPacket(Bytes header, Bytes buffer, IPv4 destinationAddress) { DebugPrint("IP.SendOutgoingPacket: dst {0}\n", destinationAddress); RouteEntry e = hostConfiguration.RoutingTable.Lookup(destinationAddress); if (e == null) { //delete header; //delete buffer; DebugPrint("Packet dropped -- no route\n"); return; } IPv4 ifaddr = e.InterfaceAddress; IPv4 nextHop; if (e.Gateway == e.InterfaceAddress) { nextHop = destinationAddress; } else { nextHop = e.Gateway; } DebugPrint("Selected destination {0}\n", nextHop); DebugStub.Assert(e.Gateway == e.InterfaceAddress); IAdapter adapter = hostConfiguration.Bindings.GetAdapter(ifaddr); VTable.Assert(adapter != null); EthernetAddress localMac = adapter.HardwareAddress; EthernetAddress remoteMac; IAdapter targetAdapter = hostConfiguration.Bindings.GetAdapter(nextHop); if (targetAdapter != null) { remoteMac = targetAdapter.HardwareAddress; } else { if (arp.Lookup(nextHop, out remoteMac) == false) { DebugStub.WriteLine("Outgoing packet, no ARP Entry for: {0}...about to wait\n", DebugStub.ArgList(nextHop)); arp.ArpRequest(ifaddr, nextHop, localMac, header, buffer, adapter); // DebugPrint("ArpRequest complete...sending packet\n"); // bool rc = arp.Lookup(nextHop, out remoteMac); // DebugStub.Assert(rc == true); return; } } //Format ethernet header EthernetHeader.Write(header, localMac, remoteMac, EthernetHeader.PROTOCOL_IP); //send it! adapter.PopulateTxRing(header, buffer); }