Esempio n. 1
0
        /// <summary>设置类型</summary>
        /// <param name="kind"></param>
        /// <returns></returns>
        public DhcpOption SetType(DhcpMessageType kind)
        {
            Option = DhcpOptions.MessageType;
            Length = 1;
            Data   = new Byte[] { (Byte)kind };

            return(this);
        }
        public DhcpMessageTypeOption(byte[] bytes)
            : base(bytes)
        {
            if (Length != 1)
            {
                throw new ArgumentException("Option length is not valid for this option");
            }

            MessageType = (DhcpMessageType)Value[0];
        }
Esempio n. 3
0
        protected override void ParseOptionValue(Stream s)
        {
            if (s.Length != 1)
            {
                throw new InvalidDataException();
            }

            int type = s.ReadByte();

            if (type < 0)
            {
                throw new EndOfStreamException();
            }

            _type = (DhcpMessageType)type;
        }
Esempio n. 4
0
        private void SendPacket(DhcpMessageType dhcpMessageType, DhcpPacket responsePacket, IPAddress address, int port)
        {
            Console.WriteLine("{0:X8}: Sending packet type {1} to {2}:{3}", responsePacket.xid, dhcpMessageType, address, port);

            responsePacket.Options.SetByte(DhcpPacketOptionId.DhcpMessageType, (Byte)dhcpMessageType);

            var broadcast = address == IPAddress.Broadcast;

            responsePacket.flags = (UInt16)(broadcast ? 0x8000 : 0x0000);

            var bytes = responsePacket.ToArray();

            DhcpPacket.TraceToFile(bytes);

            var endPoint = new IPEndPoint(address, port);

            SendData(bytes, endPoint);

            Console.WriteLine("{0:X8}: Packet sent", responsePacket.xid);
        }
Esempio n. 5
0
 public void AddOption(DhcpOptionCode opCode, DhcpMessageType messageType)
 {
     AddOption(opCode, (byte)messageType);
 }
Esempio n. 6
0
 public DhcpMessageTypeOption(DhcpMessageType messageType)
 {
     MessageType = messageType;
 }
        void SendDhcpMessage(UdpSocket socket, DhcpMessageType messageType, UInt32 dhcpServerIPAddress, UInt32 transactionID, UInt16 secondsElapsed, UInt32 clientIPAddress, UInt64 clientHardwareAddress, DhcpOption[] options, Int64 timeoutInMachineTicks)
        {
            if (_isDisposed) return;

            byte[] dhcpFrameBuffer = new byte[DHCP_FRAME_BUFFER_LENGTH];

            // configure DHCP frame
            /* op (bootp operation) */
            dhcpFrameBuffer[0] = (byte)BootpOperation.BOOTREQUEST;
            /* htype (hardware type) */
            dhcpFrameBuffer[1] = (byte)HARDWARE_TYPE_ETHERNET;
            /* hlen (hardware address length) */
            dhcpFrameBuffer[2] = (byte)HARDWARE_ADDRESS_SIZE;
            /* hops (bootp relay hops; we should always set this to zero) */
            dhcpFrameBuffer[3] = 0;
            /* xid (transaction id; this should be a randomly-generated number) */
            dhcpFrameBuffer[4] = (byte)((transactionID >> 24) & 0xFF);
            dhcpFrameBuffer[5] = (byte)((transactionID >> 16) & 0xFF);
            dhcpFrameBuffer[6] = (byte)((transactionID >> 8) & 0xFF);
            dhcpFrameBuffer[7] = (byte)(transactionID & 0xFF);
            /* secs (seconds elasped since start of DHCP config acquisition process) */
            dhcpFrameBuffer[8] = (byte)((secondsElapsed >> 8) & 0xFF);
            dhcpFrameBuffer[9] = (byte)(secondsElapsed & 0xFF);
            /* flags (most significant bit is broadcast flags; all others are zeroes) */
            /* some DHCP servers do not process the broadcast flag properly, so we allow all broadcast and unicast packets with our hardwareAddress to pass through to the UDP layer instead */
            /* see https://support.microsoft.com/en-us/kb/928233 for more details */
            dhcpFrameBuffer[10] = 0x00; // 0x80; 
            dhcpFrameBuffer[11] = 0x00;
            /* ciaddr (client ip address; only filled in if client can respond to ARP requests and is in BOUND, RENEW or REBINDING state) */
            dhcpFrameBuffer[12] = (byte)((clientIPAddress >> 24) & 0xFF);
            dhcpFrameBuffer[13] = (byte)((clientIPAddress >> 16) & 0xFF);
            dhcpFrameBuffer[14] = (byte)((clientIPAddress >> 8) & 0xFF);
            dhcpFrameBuffer[15] = (byte)(clientIPAddress & 0xFF);
            /* yiaddr (ip address, populated by server; this should always be zero in client requests */
            dhcpFrameBuffer[16] = 0;
            dhcpFrameBuffer[17] = 0;
            dhcpFrameBuffer[18] = 0;
            dhcpFrameBuffer[19] = 0;
            /* siaddr (ip address of next address to use in bootp boot process, populated by server; this should always be zero in client requests */
            dhcpFrameBuffer[20] = 0;
            dhcpFrameBuffer[21] = 0;
            dhcpFrameBuffer[22] = 0;
            dhcpFrameBuffer[23] = 0;
            /* giaddr (ip address of relay agent, populated by relay agents; this should always be zero in client requests */
            dhcpFrameBuffer[24] = 0;
            dhcpFrameBuffer[25] = 0;
            dhcpFrameBuffer[26] = 0;
            dhcpFrameBuffer[27] = 0;
            /* chaddr (client hardware address; we fill in the first 6 bytes with our MAC address) */
            dhcpFrameBuffer[28] = (byte)((clientHardwareAddress >> 40) & 0xFF);
            dhcpFrameBuffer[29] = (byte)((clientHardwareAddress >> 32) & 0xFF);
            dhcpFrameBuffer[30] = (byte)((clientHardwareAddress >> 24) & 0xFF);
            dhcpFrameBuffer[31] = (byte)((clientHardwareAddress >> 16) & 0xFF);
            dhcpFrameBuffer[32] = (byte)((clientHardwareAddress >> 8) & 0xFF);
            dhcpFrameBuffer[33] = (byte)(clientHardwareAddress & 0xFF);
            Array.Clear(dhcpFrameBuffer, 34, 10);
            /* sname (null-terminated server hostname, populated by server; always set to zero in client requests */
            Array.Clear(dhcpFrameBuffer, 44, 64);
            /* file (null-terminated boot file name, populaetd by server; always set to zero in client requests */
            Array.Clear(dhcpFrameBuffer, 108, 128);
            /* options; NOTE: we do support overflowing options into the sname and file fields in this implementation of DHCP. */
            /* magic cookie {99, 130, 83, 99} is the first 4-byte entry, as per RFC 1497 */
            dhcpFrameBuffer[236] = 99;
            dhcpFrameBuffer[237] = 130;
            dhcpFrameBuffer[238] = 83;
            dhcpFrameBuffer[239] = 99;
            /* now we fill in the options (starting with the DhcpMessageType, then all of the passed-in options, and then the END option */
            dhcpFrameBuffer[240] = (byte)DhcpOptionCode.DhcpMessageType;
            dhcpFrameBuffer[241] = 1; /* Length */
            dhcpFrameBuffer[242] = (byte)messageType;
            int currentOptionPos = 243;
            if (options != null)
            {
                for (int iOption = 0; iOption < options.Length; iOption++)
                {
                    /* do not include missing/empty options (or pad) */
                    if (options[iOption].Code != 0)
                    {
                        // if this option will not fit in the options section, stop processing options.
                        if (currentOptionPos + options.Length + 2 /* size of code + length bytes */ + 1 /* size of END option */ > DHCP_FRAME_BUFFER_LENGTH)
                            break;

                        dhcpFrameBuffer[currentOptionPos++] = (byte)options[iOption].Code;
                        dhcpFrameBuffer[currentOptionPos++] = (byte)options[iOption].Value.Length;
                        Array.Copy(options[iOption].Value, 0, dhcpFrameBuffer, currentOptionPos, options[iOption].Value.Length);
                        currentOptionPos += options[iOption].Value.Length;
                    }
                }
            }
            /* finish with "END" option */
            dhcpFrameBuffer[currentOptionPos++] = (byte)DhcpOptionCode.End;
            Array.Clear(dhcpFrameBuffer, currentOptionPos, DHCP_FRAME_BUFFER_LENGTH - currentOptionPos);

            // expand frame to word boundary, just in case DHCP servers have troubles processing non-aligned frames.
            Int32 lengthOfFrame = Math.Min(currentOptionPos + (currentOptionPos % 4 != 0 ? (4 - (currentOptionPos % 4)) : 0), DHCP_FRAME_BUFFER_LENGTH);

            socket.SendTo(dhcpFrameBuffer, 0, lengthOfFrame, 0, timeoutInMachineTicks, dhcpServerIPAddress, DHCP_SERVER_PORT);
        }
        bool RetrieveDhcpMessage(UdpSocket socket, DhcpMessageType[] messageTypes, UInt32 transactionID, UInt64 clientHardwareAddress, out UInt32 assignedIPAddress, out DhcpOption[] options, Int64 timeoutInMachineTicks)
        {
            byte[] dhcpFrameBuffer = new byte[DHCP_FRAME_BUFFER_LENGTH];
            while (timeoutInMachineTicks > Microsoft.SPOT.Hardware.Utility.GetMachineTime().Ticks)
            {
                Int32 bytesReceived = socket.Receive(dhcpFrameBuffer, 0, dhcpFrameBuffer.Length, 0, timeoutInMachineTicks);

                if (bytesReceived == 0) // timeout
                    break;

                /* parse our DHCP frame */
                // validate the operation
                if ((BootpOperation)dhcpFrameBuffer[0] != BootpOperation.BOOTREPLY)
                    continue; /* filter out this BOOTP/DHCP frame */
                /* verify magic cookie {99, 130, 83, 99} is the first 4-byte entry, as per RFC 1497 */
                if ((dhcpFrameBuffer[236] != 99) ||
                    (dhcpFrameBuffer[237] != 130) ||
                    (dhcpFrameBuffer[238] != 83) ||
                    (dhcpFrameBuffer[239] != 99))
                    continue; /* filter out this BOOTP non-DHCP frame */
                // verify that the transaction ID matches
                UInt32 verifyTransactionID = (
                    (UInt32)(dhcpFrameBuffer[4] << 24) +
                    (UInt32)(dhcpFrameBuffer[5] << 16) +
                    (UInt32)(dhcpFrameBuffer[6] << 8) +
                    (UInt32)(dhcpFrameBuffer[7])
                    );
                if (transactionID != verifyTransactionID)
                    continue; /* filter out this DHCP frame */
                // verify the the physical hardware type matches
                if (dhcpFrameBuffer[1] != (byte)HARDWARE_TYPE_ETHERNET)
                    continue; /* filter out this DHCP frame */
                if (dhcpFrameBuffer[2] != (byte)HARDWARE_ADDRESS_SIZE)
                    continue; /* filter out this DHCP frame */
                // verify that the physical address matches
                UInt64 verifyClientHardwareAddress = (
                    ((UInt64)(dhcpFrameBuffer[28]) << 40) +
                    ((UInt64)(dhcpFrameBuffer[29]) << 32) +
                    ((UInt64)(dhcpFrameBuffer[30]) << 24) +
                    ((UInt64)(dhcpFrameBuffer[31]) << 16) +
                    ((UInt64)(dhcpFrameBuffer[32]) << 8) +
                    (UInt64)(dhcpFrameBuffer[33])
                    );
                if (clientHardwareAddress != verifyClientHardwareAddress)
                    continue; /* filter out this DHCP frame */

                // retrieve allocated ip address
                /* yiaddr (ip address, populated by server */
                assignedIPAddress = (
                    (UInt32)(dhcpFrameBuffer[16] << 24) +
                    (UInt32)(dhcpFrameBuffer[17] << 16) +
                    (UInt32)(dhcpFrameBuffer[18] << 8) +
                    (UInt32)(dhcpFrameBuffer[19])
                    );
                // retrieve options
                System.Collections.ArrayList optionsArrayList = new System.Collections.ArrayList();
                bool optionOverloadReceived = false;
                DhcpOptionsBlockRange[] optionsBlocks = new DhcpOptionsBlockRange[]
                {
                    new DhcpOptionsBlockRange(240, DHCP_FRAME_BUFFER_LENGTH - 240 - 1),
                };
                int optionsBlocksIndex = 0;

                DhcpMessageType verifyMessageType = 0;
                while (optionsBlocksIndex < optionsBlocks.Length)
                {
                    Int32 index = optionsBlocks[optionsBlocksIndex].BeginOffset;
                    bool endOpcodeReceived = false;
                    while (!endOpcodeReceived && index <= optionsBlocks[optionsBlocksIndex].EndOffset)
                    {
                        DhcpOptionCode optionCode = (DhcpOptionCode)dhcpFrameBuffer[index];
                        switch ((DhcpOptionCode)optionCode)
                        {
                            case DhcpOptionCode.Pad:
                                {
                                    index++;
                                }
                                break;
                            case DhcpOptionCode.End:
                                {
                                    index++;
                                    endOpcodeReceived = true;
                                }
                                break;
                            case DhcpOptionCode.OptionOverload:
                                {
                                    if (optionsBlocksIndex == 0)
                                    {
                                        index++;
                                        if (dhcpFrameBuffer[index] != 1)
                                            break;
                                        index++;
                                        byte value = dhcpFrameBuffer[index];
                                        index++;
                                        int numBlocks = 1 + (((value & 0x01) == 0x01) ? 1 : 0) + (((value & 0x02) == 0x02) ? 1 : 0);
                                        optionsBlocks = new DhcpOptionsBlockRange[numBlocks];
                                        int iOptionBlock = 0;
                                        optionsBlocks[iOptionBlock++] = new DhcpOptionsBlockRange(240, DHCP_FRAME_BUFFER_LENGTH - 240 - 1);
                                        if ((value & 0x01) == 0x01)
                                        {
                                            /* use file field for extended options */
                                            optionsBlocks[iOptionBlock++] = new DhcpOptionsBlockRange(108, 235);
                                        }
                                        if ((value & 0x02) == 0x02)
                                        {
                                            /* use sname field for extended options */
                                            optionsBlocks[iOptionBlock++] = new DhcpOptionsBlockRange(44, 107);
                                        }
                                    }
                                }
                                break;
                            default:
                                {
                                    index++;
                                    byte[] value = new byte[Math.Min(dhcpFrameBuffer[index], DHCP_FRAME_BUFFER_LENGTH - index)];
                                    index++;
                                    Array.Copy(dhcpFrameBuffer, index, value, 0, value.Length);
                                    index += value.Length;

                                    // if the option already exists, append to it
                                    bool foundOption = false;
                                    for (int iExistingOption = 0; iExistingOption < optionsArrayList.Count; iExistingOption++)
                                    {
                                        if (((DhcpOption)optionsArrayList[iExistingOption]).Code == optionCode)
                                        {
                                            byte[] newValue = new byte[((DhcpOption)optionsArrayList[iExistingOption]).Value.Length + value.Length];
                                            Array.Copy(((DhcpOption)optionsArrayList[iExistingOption]).Value, 0, newValue, 0, ((DhcpOption)optionsArrayList[iExistingOption]).Value.Length);
                                            Array.Copy(value, 0, newValue, ((DhcpOption)optionsArrayList[iExistingOption]).Value.Length, value.Length);
                                            optionsArrayList.RemoveAt(iExistingOption);
                                            optionsArrayList.Add(new DhcpOption(optionCode, newValue));

                                            foundOption = true;
                                            break;
                                        }
                                    }
                                    if (!foundOption)
                                    {
                                        optionsArrayList.Add(new DhcpOption(optionCode, value));
                                    }

                                    if (optionCode == DhcpOptionCode.DhcpMessageType)
                                    {
                                        verifyMessageType = (DhcpMessageType)value[0];
                                    }
                                }
                                break;
                        }
                    }

                    optionsBlocksIndex++;
                }
                options = (DhcpOption[])optionsArrayList.ToArray(typeof(DhcpOption));

                // verify that the DHCP message type matches
                bool messageTypeMatches = false;
                for (int iMessageType = 0; iMessageType < messageTypes.Length; iMessageType++)
                {
                    if (messageTypes[iMessageType] == verifyMessageType)
                    {
                        messageTypeMatches = true;
                        break;
                    }
                }

                if (messageTypeMatches)
                    return true; /* message matches the messageTypes filter, with a valid frame; return all data to the caller  */
            }

            // if we did not receive a message before timeout, return false.
            // set default return values
            assignedIPAddress = 0;
            options = null;
            return false;
        }
Esempio n. 9
0
 public DhcpMessageTypeOption(DhcpMessageType type)
     : base(DhcpOptionCode.DhcpMessageType)
 {
     _type = type;
 }
Esempio n. 10
0
 internal DhcpOptionCollection(DhcpMessageType messageType) : base(new Dictionary <DhcpOption, byte[]>())
 {
     SetValue(DhcpOption.DhcpMessageType, (byte)messageType);
 }
 public DhcpMessageTypeOption(DhcpMessageType dhcpMessageType)
 {
     MessageType = dhcpMessageType;
 }
Esempio n. 12
0
 internal DhcpMessage(DhcpOpcode opCode, DhcpMessageType messageType)
 {
     OpCode  = opCode;
     Options = new DhcpOptionCollection(messageType);
 }
Esempio n. 13
0
        private void CompleteRequest(Object state)
        {
            DhcpData messageData = (DhcpData)state;
            EndPoint source      = new IPEndPoint(0, 0);

            this.m_AbortLock.AcquireReaderLock(-1);

            try {
                if (this.m_Abort)
                {
                    return;
                }
                messageData.BufferSize = this.m_DhcpSocket.EndReceiveFrom(messageData.Result, ref source);
                messageData.Source     = (IPEndPoint)source;
            } catch (ArgumentException ex) {
                Trace.TraceInformation("DHCP: " + ex.Message);
                return;
            } finally
            {
                this.m_AbortLock.ReleaseLock();
            }

            DhcpMessage message;

            try
            {
                message = new DhcpMessage(messageData);
            }
            catch (ArgumentException ex)
            {
                TraceException("Error Parsing Dhcp Message", ex);
                return;
            }
            catch (InvalidCastException ex)
            {
                TraceException("Error Parsing Dhcp Message", ex);
                return;
            }
            catch (IndexOutOfRangeException ex)
            {
                TraceException("Error Parsing Dhcp Message", ex);
                return;
            }
            catch (Exception ex)
            {
                TraceException("Error Parsing Dhcp Message", ex);
                throw;
            }

            if (message.Operation == DhcpOperation.BootRequest)
            {
                Byte[] messageTypeData = message.GetOptionData(DhcpOption.DhcpMessageType);

                if (messageTypeData != null && messageTypeData.Length == 1)
                {
                    DhcpMessageType messageType = (DhcpMessageType)messageTypeData[0];

                    switch (messageType)
                    {
                    case DhcpMessageType.Discover:
                        Trace.TraceInformation("{0} Dhcp DISCOVER Message Received.", Thread.CurrentThread.ManagedThreadId);
                        this.DhcpDiscover(message);
                        Trace.TraceInformation("{0} Dhcp DISCOVER Message Processed.", Thread.CurrentThread.ManagedThreadId);
                        break;

                    case DhcpMessageType.Request:
                        Trace.TraceInformation("{0} Dhcp REQUEST Message Received.", Thread.CurrentThread.ManagedThreadId);
                        this.DhcpRequest(message);
                        Trace.TraceInformation("{0} Dhcp REQUEST Message Processed.", Thread.CurrentThread.ManagedThreadId);
                        break;

                    default:
                        Trace.TraceWarning("Unknown Dhcp Message ({0}) Received, Ignoring.", messageType.ToString());
                        break;
                    }
                }
                else
                {
                    Trace.TraceWarning("Unknown Dhcp Data Received, Ignoring.");
                }
            }
        }