public static void SetUdpChecksum(Bytes buffer, Bytes payload, int ipOffset, ushort udplength) { // sum IP pseudo ushort ipPayloadSize = 0; ushort headerSum = IpHeader.SumPseudoHeader(buffer, ipOffset, ref ipPayloadSize); DebugStub.Assert(udplength == ipPayloadSize); // now add it to the udp header + data int ipHeaderSize = (buffer[ipOffset] & 0xf) * 4; int udpOffset = ipOffset + ipHeaderSize; ushort udpsum = IpHeader.SumShortValues(buffer, ipOffset + IpHeader.Size, UDPHeader.Size); DebugStub.Assert(buffer[udpOffset + 6] == 0); DebugStub.Assert(buffer[udpOffset + 7] == 0); ushort payloadSum = IpHeader.SumShortValues(payload, 0, payload.Length); ushort hdrSum = IpHeader.SumShortValues(headerSum, udpsum); ushort chksum; chksum = (ushort)~( IpHeader.SumShortValues(hdrSum, payloadSum) ); buffer[udpOffset + 6] = (byte)(chksum >> 8); buffer[udpOffset + 7] = (byte)(chksum & 0xff); }
//process incoming packet public static bool ProcessIncomingPacket(Bytes packet, IpHeader ipHeader) { int offset = EthernetHeader.Size + IpHeader.Size; //14 byte ethernet header + 20 byte IP header VTable.Assert(offset == 34); UDPHeader udpHeader = new UDPHeader(packet, offset); DebugPrint("ProcessIncomingPacket: Received packet from address {0} port {1}\n", ipHeader.srcAddress.ToString(), udpHeader.srcPort); UDP udp = GetUDPSession(udpHeader.dstPort); //now we check to see whether the udp session wants to packet //XXX review this logic... //todo: check if udp is bound to local IP that dest IP matches. //UDP header? if ((udp != null) && ((udp.LocalAddress == IPv4.Any) || (udp.RemoteAddress == ipHeader.srcAddress && udp.RemotePort == udpHeader.srcPort) || (udp.RemotePort == 0))) { offset += UDPHeader.Size; Bytes data = Bitter.SplitOff(ref packet, offset); //delete packet; udp.PushPacket(data); udp.udpWaitEvent.Set(); return(true); } DebugPrint("Received packe destined for inactive UDP port {0}" + " source address {1} source port {2}\n", udpHeader.dstPort, ipHeader.srcAddress.ToString(), udpHeader.srcPort); //delete packet; return(false); }
//assume ethernet //we have to expose this for the DhcpClient //Once we move the Dhcp client into an app this can be hidden again public void WriteCompleteUDPHeader(Bytes header, Bytes data, int payloadLength) { int totalLength = IpHeader.Size + UDPHeader.Size + payloadLength; //write ip header int offset = EthernetHeader.Size; int o = EthernetHeader.Size; DebugStub.Assert(payloadLength < 0xffff); header[o++] = 0x45; //default version 4, header_len 5 header[o++] = 0; //tos header[o++] = (byte)(((ushort)totalLength) >> 8); //total length of the ip header header[o++] = (byte)(((ushort)totalLength) & 0xff); header[o++] = (byte)(((ushort)0) >> 8); //fragment id header[o++] = (byte)(((ushort)0) & 0xff); //fragment id header[o++] = (byte)(((ushort)0) >> 8); //fragment offset header[o++] = (byte)(((ushort)0) & 0xff); //fragment offset header[o++] = 128; //default ttl header[o++] = 17; // protocol ID --> udp header[o++] = 0; //ipchecksum (fill it in later) header[o++] = 0; //ipchecksum // set the ip addresses localIPAddress.CopyOut(header.Array, header.Start + o); o += IPv4.Length; remoteIPAddress.CopyOut(header.Array, header.Start + o); o += IPv4.Length; // calculate checksum ushort chk = IpHeader.CalculateChecksum(header, offset, IpHeader.Size); header[offset + 10] = (byte)(((ushort)chk) >> 8); header[offset + 11] = (byte)(((ushort)chk) & 0xff); //write the udp header header[o++] = (byte)(((ushort)localPort) >> 8); header[o++] = (byte)(((ushort)localPort) & 0xff); header[o++] = (byte)(((ushort)remotePort) >> 8); header[o++] = (byte)(((ushort)remotePort) & 0xff); ushort udpLength = (ushort)(UDPHeader.Size + payloadLength); header[o++] = (byte)(((ushort)udpLength) >> 8); header[o++] = (byte)(((ushort)udpLength) & 0xff); // udp checksum (forget for now) header[o++] = 0; header[o++] = 0; UDPHeader.SetUdpChecksum(header, data, EthernetHeader.Size, udpLength); }
//dirt simple is the name of the game public static void ProcessIncomingPacket(Bytes packet, IAdapter adapter) { IpHeader ipHeader = new IpHeader(packet, EthernetHeader.Size); //since we apparently don't support fragments yet. if (ipHeader.MoreFragmentsFollowing() == true) { DebugPrint("ACK! ip fragmentation!\n"); return; } // DebugStub.Assert(ipHeader.MoreFragmentsFollowing() == false); //VTable.Assert(ipHeader.MoreFragmentsFollowing() == false); if (ipHeader.IsChecksumValid() == false) { DebugPrint("ProcessIncomingPacket: bad checksum...dropping packets\n"); //delete packet; return; } //make sure the address is 'local' if (hostConfiguration == null) { DebugPrint("ACK hostConfiguration is NULL\n"); return; } if ((hostConfiguration.IsLocalAddress(ipHeader.destAddress) == false) && (ipHeader.destAddress != IPv4.Broadcast)) { // DebugPrint("ProcessIncomingPacket: wrong address ...dropping packets\n"); // DebugPrint("Dest address {0}\n", ipHeader.destAddress); //delete packet; return; } try { //figure out to which protocol the packet belongs switch (ipHeader.protocol) { case IpHeader.TCP: DebugPrint("ProcessIncomingPacket: Got TCP packet\n"); //TCP.ProcessIncomingPacket(packet, ipHeader); break; case IpHeader.UDP: //DebugPrint("ProcessIncomingPacket: Got UDP packet\n"); UDP.ProcessIncomingPacket(packet, ipHeader); break; case IpHeader.ICMP: DebugPrint("ProcessIncomingPacket: Got ICMP packet\n"); //delete packet; break; default: DebugPrint("Got unexpected packet!!\n"); //delete packet; DebugStub.Break(); break; } } catch (Exception e) { DebugStub.Print("Caught exception {0}\n", DebugStub.ArgList(e)); DebugStub.Break(); } }