void SendIcmpMessage(UInt32 destinationIPAddress, IcmpMessageType icmpMessageType, IcmpMessageCode icmpMessageCode, byte[] restOfHeader, byte[] data, Int64 timeoutInMachineTicks)
        {
            if (_isDisposed)
            {
                return;
            }

            lock (_icmpFrameBufferLock)
            {
                // configure ICMPv4 frame
                /* Type */
                _icmpFrameBuffer[0] = (byte)icmpMessageType;
                /* Code (Subtype) */
                _icmpFrameBuffer[1] = (byte)icmpMessageCode;
                /* checksum (clear this for now; we will calculate it shortly) */
                Array.Clear(_icmpFrameBuffer, 2, 2);
                /* restOfHeader */
                if (restOfHeader.Length < 4)
                {
                    Array.Clear(_icmpFrameBuffer, 4, 4);
                }
                Array.Copy(restOfHeader, 0, _icmpFrameBuffer, 4, System.Math.Min(4, restOfHeader.Length));

                UInt16 checksum;
                lock (_checksumLock)
                {
                    // calculate checksum over entire ICMP frame including data
                    _checksumBufferArray[0] = _icmpFrameBuffer;
                    _checksumOffsetArray[0] = 0;
                    _checksumCountArray[0]  = ICMP_FRAME_BUFFER_LENGTH;
                    _checksumBufferArray[1] = data;
                    _checksumOffsetArray[1] = 0;
                    _checksumCountArray[1]  = data.Length;
                    checksum = Utility.CalculateInternetChecksum(_checksumBufferArray, _checksumOffsetArray, _checksumCountArray, 2);
                }
                _icmpFrameBuffer[2] = (byte)((checksum >> 8) & 0xFF);
                _icmpFrameBuffer[3] = (byte)(checksum & 0xFF);

                _bufferArray[0] = _icmpFrameBuffer;
                _indexArray[0]  = 0;
                _countArray[0]  = ICMP_FRAME_BUFFER_LENGTH;
                _bufferArray[1] = data;
                _indexArray[1]  = 0;
                _countArray[1]  = data.Length;
                _ipv4Layer.Send(1 /* PROTOCOL for ICMP */, _ipv4Layer.IPAddress, destinationIPAddress, _bufferArray, _indexArray, _countArray, timeoutInMachineTicks);
            }
        }
Beispiel #2
0
        internal void SendTcpSegment(UInt32 sourceIPAddress, UInt32 destinationIPAddress, UInt16 sourceIPPort, UInt16 destinationIPPort, UInt32 sequenceNumber, UInt32 acknowledgementNumber, UInt16 windowSize, bool sendAck, bool sendPsh, bool sendRst, bool sendSyn, bool sendFin, TcpOption[] tcpOptions, byte[] buffer, Int32 offset, Int32 count, Int64 timeoutInMachineTicks)
        {
            if (_isDisposed)
            {
                return;
            }

            lock (_tcpHeaderBufferLockObject)
            {
                Int32 tcpHeaderLength = TCP_HEADER_MIN_LENGTH + (sendSyn ? 4 : 0);

                // TCP basic header: 20 bytes
                _tcpHeaderBuffer[0] = (byte)((sourceIPPort >> 8) & 0xFF);
                _tcpHeaderBuffer[1] = (byte)(sourceIPPort & 0xFF);
                _tcpHeaderBuffer[2] = (byte)((destinationIPPort >> 8) & 0xFF);
                _tcpHeaderBuffer[3] = (byte)(destinationIPPort & 0xFF);
                // sequence number
                _tcpHeaderBuffer[4] = (byte)((sequenceNumber >> 24) & 0xFF);
                _tcpHeaderBuffer[5] = (byte)((sequenceNumber >> 16) & 0xFF);
                _tcpHeaderBuffer[6] = (byte)((sequenceNumber >> 8) & 0xFF);
                _tcpHeaderBuffer[7] = (byte)(sequenceNumber & 0xFF);
                // acknowledment number
                if (sendAck)
                {
                    _tcpHeaderBuffer[8]  = (byte)((acknowledgementNumber >> 24) & 0xFF);
                    _tcpHeaderBuffer[9]  = (byte)((acknowledgementNumber >> 16) & 0xFF);
                    _tcpHeaderBuffer[10] = (byte)((acknowledgementNumber >> 8) & 0xFF);
                    _tcpHeaderBuffer[11] = (byte)(acknowledgementNumber & 0xFF);
                }
                else
                {
                    Array.Clear(_tcpHeaderBuffer, 8, 4);
                }
                // header length and flags
                _tcpHeaderBuffer[12] = (byte)((tcpHeaderLength / 4) << 4);
                // more flags
                _tcpHeaderBuffer[13] = (byte)(
                    (sendFin ? 1 << 0 : 0) |
                    (sendSyn ? 1 << 1 : 0) |
                    (sendRst ? 1 << 2 : 0) |
                    (sendPsh ? 1 << 3 : 0) |
                    (sendAck ? 1 << 4 : 0)
                    );
                // window size (i.e. how much data we are willing to receive)
                _tcpHeaderBuffer[14] = (byte)((windowSize >> 8) & 0xFF);
                _tcpHeaderBuffer[15] = (byte)(windowSize & 0xFF);
                // tcp checksum
                Array.Clear(_tcpHeaderBuffer, 16, 2);
                // urgent pointer
                /* NOTE: bytes 18-19, never populated */

                // TCP options: empty by default policy -- but zero-initialized under any circumstance
                Array.Clear(_tcpHeaderBuffer, TCP_HEADER_MIN_LENGTH, TCP_HEADER_MAX_LENGTH - TCP_HEADER_MIN_LENGTH);

                /* TCP options */
                if (tcpOptions != null)
                {
                    int headerPos = TCP_HEADER_MIN_LENGTH;
                    for (int iOption = 0; iOption < tcpOptions.Length; iOption++)
                    {
                        _tcpHeaderBuffer[headerPos++] = tcpOptions[iOption].Kind;
                        switch (tcpOptions[iOption].Kind)
                        {
                        case 0:     /* EOL = End of Option List */
                        case 1:     /* NOP = No OPeration; used for padding */
                            break;

                        default:
                        {
                            if (tcpOptions[iOption].Data != null)
                            {
                                _tcpHeaderBuffer[headerPos++] = (byte)(tcpOptions[iOption].Data.Length + 2);
                                Array.Copy(tcpOptions[iOption].Data, 0, _tcpHeaderBuffer, headerPos, tcpOptions[iOption].Data.Length);
                                headerPos += tcpOptions[iOption].Data.Length;
                            }
                            else
                            {
                                _tcpHeaderBuffer[headerPos++] = 2;         /* only 2 bytes--the kind and the length--with no data */
                            }
                        }
                        break;
                        }
                    }
                }

                UInt16 checksum;
                lock (_tcpPseudoHeaderBufferLockObject)
                {
                    // create temporary pseudo header
                    _tcpPseudoHeaderBuffer[0] = (byte)((sourceIPAddress >> 24) & 0xFF);
                    _tcpPseudoHeaderBuffer[1] = (byte)((sourceIPAddress >> 16) & 0xFF);
                    _tcpPseudoHeaderBuffer[2] = (byte)((sourceIPAddress >> 8) & 0xFF);
                    _tcpPseudoHeaderBuffer[3] = (byte)(sourceIPAddress & 0xFF);
                    _tcpPseudoHeaderBuffer[4] = (byte)((destinationIPAddress >> 24) & 0xFF);
                    _tcpPseudoHeaderBuffer[5] = (byte)((destinationIPAddress >> 16) & 0xFF);
                    _tcpPseudoHeaderBuffer[6] = (byte)((destinationIPAddress >> 8) & 0xFF);
                    _tcpPseudoHeaderBuffer[7] = (byte)(destinationIPAddress & 0xFF);
                    _tcpPseudoHeaderBuffer[8] = 0;                                // ZERO
                    _tcpPseudoHeaderBuffer[9] = (byte)IPv4Layer.ProtocolType.Tcp; // Protocol Number
                    UInt16 tcpLength = (UInt16)(tcpHeaderLength + count);
                    _tcpPseudoHeaderBuffer[10] = (byte)((tcpLength >> 8) & 0xFF);
                    _tcpPseudoHeaderBuffer[11] = (byte)(tcpLength & 0xFF);

                    // calculate checksum over entire pseudo-header, UDP header and data
                    _checksumBufferArray[0] = _tcpPseudoHeaderBuffer;
                    _checksumOffsetArray[0] = 0;
                    _checksumCountArray[0]  = TCP_PSEUDO_HEADER_LENGTH;
                    _checksumBufferArray[1] = _tcpHeaderBuffer;
                    _checksumOffsetArray[1] = 0;
                    _checksumCountArray[1]  = tcpHeaderLength;
                    _checksumBufferArray[2] = buffer;
                    _checksumOffsetArray[2] = offset;
                    _checksumCountArray[2]  = count;
                    checksum = Utility.CalculateInternetChecksum(_checksumBufferArray, _checksumOffsetArray, _checksumCountArray); /* NOTE: this function will append a pad byte if necessary for 16-bit alignment before calculation */
                }

                // insert checksujm into UDP header
                _tcpHeaderBuffer[16] = (byte)((checksum >> 8) & 0xFF);
                _tcpHeaderBuffer[17] = (byte)(checksum & 0xFF);

                // queue up our buffer arrays
                _bufferArray[0] = _tcpHeaderBuffer;
                _indexArray[0]  = 0;
                _countArray[0]  = tcpHeaderLength;
                _bufferArray[1] = buffer;
                _indexArray[1]  = offset;
                _countArray[1]  = count;

                /* TODO: deal with our flags and timeout_ms; we shouldn't just be sending while blocking -- and ignoring the flags */
                _ipv4Layer.Send((byte)IPv4Layer.ProtocolType.Tcp, sourceIPAddress, destinationIPAddress, _bufferArray, _indexArray, _countArray, timeoutInMachineTicks);
            }
        }
Beispiel #3
0
        /* TODO: we can't lock permanently while waiting for another UDP packet to be sent; get rid of the _udpHeaderBufferLock "lock that could stay locked forever" */
        public override Int32 SendTo(byte[] buffer, Int32 offset, Int32 count, Int32 flags, Int64 timeoutInMachineTicks, UInt32 ipAddress, UInt16 ipPort)
        {
            if (!_sourceIpAddressAndPortAssigned)
            {
                Bind(IP_ADDRESS_ANY, IP_PORT_ANY);
            }

            lock (_udpHeaderBufferLockObject)
            {
                // UDP header: 8 bytes
                _udpHeaderBuffer[0] = (byte)((_srcIPPort >> 8) & 0xFF);
                _udpHeaderBuffer[1] = (byte)(_srcIPPort & 0xFF);
                _udpHeaderBuffer[2] = (byte)((ipPort >> 8) & 0xFF);
                _udpHeaderBuffer[3] = (byte)(ipPort & 0xFF);
                UInt16 udpLength = (UInt16)(UDP_HEADER_LENGTH + count);
                _udpHeaderBuffer[4] = (byte)((udpLength >> 8) & 0xFF);
                _udpHeaderBuffer[5] = (byte)(udpLength & 0xFF);
                _udpHeaderBuffer[6] = 0; // for now, no checksum; we'll populate this when we calculate checksum over the pseudoheader + header + data + 16-bit-alignment-if-necessary-zero-pad-byte
                _udpHeaderBuffer[7] = 0; // checksum (continued)

                UInt16 checksum;
                lock (_udpPseudoHeaderBufferLockObject)
                {
                    // create temporary pseudo header
                    _udpPseudoHeaderBuffer[0]  = (byte)((_srcIPAddress >> 24) & 0xFF);
                    _udpPseudoHeaderBuffer[1]  = (byte)((_srcIPAddress >> 16) & 0xFF);
                    _udpPseudoHeaderBuffer[2]  = (byte)((_srcIPAddress >> 8) & 0xFF);
                    _udpPseudoHeaderBuffer[3]  = (byte)(_srcIPAddress & 0xFF);
                    _udpPseudoHeaderBuffer[4]  = (byte)((ipAddress >> 24) & 0xFF);
                    _udpPseudoHeaderBuffer[5]  = (byte)((ipAddress >> 16) & 0xFF);
                    _udpPseudoHeaderBuffer[6]  = (byte)((ipAddress >> 8) & 0xFF);
                    _udpPseudoHeaderBuffer[7]  = (byte)(ipAddress & 0xFF);
                    _udpPseudoHeaderBuffer[8]  = 0;                                // ZERO
                    _udpPseudoHeaderBuffer[9]  = (byte)IPv4Layer.ProtocolType.Udp; // Protocol Number
                    _udpPseudoHeaderBuffer[10] = (byte)((udpLength >> 8) & 0xFF);
                    _udpPseudoHeaderBuffer[11] = (byte)(udpLength & 0xFF);

                    // calculate checksum over entire pseudo-header, UDP header and data
                    _checksumBufferArray[0] = _udpPseudoHeaderBuffer;
                    _checksumOffsetArray[0] = 0;
                    _checksumCountArray[0]  = UDP_PSEUDO_HEADER_LENGTH;
                    _checksumBufferArray[1] = _udpHeaderBuffer;
                    _checksumOffsetArray[1] = 0;
                    _checksumCountArray[1]  = UDP_HEADER_LENGTH;
                    _checksumBufferArray[2] = buffer;
                    _checksumOffsetArray[2] = offset;
                    _checksumCountArray[2]  = count;
                    checksum = Utility.CalculateInternetChecksum(_checksumBufferArray, _checksumOffsetArray, _checksumCountArray); /* NOTE: this function will append a pad byte if necessary for 16-bit alignment before calculation */
                }

                // insert checksujm into UDP header
                _udpHeaderBuffer[6] = (byte)((checksum >> 8) & 0xFF);
                _udpHeaderBuffer[7] = (byte)(checksum & 0xFF);

                // queue up our buffer arrays
                _bufferArray[0] = _udpHeaderBuffer;
                _indexArray[0]  = 0;
                _countArray[0]  = UDP_HEADER_LENGTH;
                _bufferArray[1] = buffer;
                _indexArray[1]  = offset;
                _countArray[1]  = count;

                /* TODO: deal with our flags and timeout_ms; we shouldn't just be sending while blocking -- and ignoring the flags */
                _ipv4Layer.Send((byte)IPv4Layer.ProtocolType.Udp, _srcIPAddress, ipAddress, _bufferArray, _indexArray, _countArray, timeoutInMachineTicks);
            }

            /* TODO: return actual # of bytes sent, if different; this may be caused by a limit on UDP datagram size, timeout while sending data, etc. */
            return(count);
        }