Пример #1
0
        public RPCResult <bool> PacketReceived(byte[] packet, int dev_no, int payload_offset,
                                               int payload_len, p_addr src)
        {
            /* Parse the provided packet */

            byte type = packet[payload_offset];
            byte code = packet[payload_offset + 1];
            uint csum = ipv4.calc_checksum(packet, payload_offset, payload_len);

            if (csum != 0)
            {
                System.Diagnostics.Debugger.Log(0, null, "Received ICMP message with " +
                                                "invalid checksum " + csum.ToString("X4"));
                return(false);
            }
            ushort ident = net.ReadWord(packet, payload_offset + 4);
            ushort seq   = net.ReadWord(packet, payload_offset + 6);

            System.Diagnostics.Debugger.Log(0, null, "ICMP message received from " +
                                            src.ToString() + ": type: " + type.ToString() + ", code: " +
                                            code.ToString() + ", ident: " + ident.ToString() + ", seq: " +
                                            seq.ToString());

            return(true);
        }
Пример #2
0
        public void TransmitEthernetPacket(byte[] packet, int dev_no, int payload_offset,
                                           int payload_len, p_addr dest, ushort etype)
        {
            /* Build an ethernet packet from the higher level packet passed to us.
             *
             *  First, decide if we have enough space in the original buffer to
             *  build the packet around.  We need 14 bytes before the packet and
             *  optionally 4 bytes after if the device doesn't add FCS.
             *
             *  TODO: add support also for padding here */

            var nd = devs[dev_no];

            bool need_new_buf = false;
            int  header_len   = 14;

            if (payload_offset < header_len)
            {
                need_new_buf = true;
            }
            int crc_len = 0;

            if (nd.dev_appends_crc_on_tx == false)
            {
                crc_len = 4;
            }
            if (packet.Length < payload_offset + payload_len + crc_len)
            {
                need_new_buf = true;
            }

            if (need_new_buf)
            {
                byte[] new_buf = new byte[header_len + crc_len + payload_len];
                for (int i = 0; i < payload_len; i++)
                {
                    new_buf[header_len + i] = packet[payload_offset + i];
                }
                payload_offset = header_len;
                packet         = new_buf;
            }

            // Add in the header
            payload_offset -= header_len;
            payload_len    += header_len;

            // dest
            var d = dest as HWAddr;

            if (d == null)
            {
                System.Diagnostics.Debugger.Log(0, null, "TransmitEthernetPacket: "
                                                + "dest is not a hardware address: " + dest.ToString());
                return;
            }
            for (int i = 0; i < 6; i++)
            {
                packet[payload_offset + i] = d.MAC[i];
            }

            // src
            for (int i = 0; i < 6; i++)
            {
                packet[payload_offset + 6 + i] = nd.HWAddr.MAC[i];
            }

            // ethertype
            packet[payload_offset + 12] = (byte)((etype >> 8) & 0xff);
            packet[payload_offset + 13] = (byte)(etype & 0xff);

            // TODO: pad if required
            if (nd.dev_pads_on_tx == false && payload_len + crc_len < 64)
            {
                System.Diagnostics.Debugger.Log(0, null, "TransmitEthernetPacket: "
                                                + "packet too short and device does not automatically pad");
                return;
            }

            // TODO: add FCS if required
            if (nd.dev_appends_crc_on_tx == false)
            {
                System.Diagnostics.Debugger.Log(0, null, "TransmitEthernetPacket: "
                                                + "device does not automatically add FCS");
                return;
            }

            // Send packet
            nd.s.TransmitPacket(packet, dev_no, payload_offset, payload_len, dest);
        }
Пример #3
0
        public RPCResult <HWAddr> ResolveAddress(int dev_no, p_addr addr)
        {
            /* Get the appropriate dictionary */
            var prot_dict = GetProtocolDictionary(dev_no, addr.EtherType);

            /* If the cache contains the value we need, then we can use it
             *  directly, otherwise we need to send a request for it */
            HWAddr ret;

            if (prot_dict.TryGetValue(addr, out ret) == true)
            {
                System.Diagnostics.Debugger.Log(0, null, "Resolving " +
                                                addr.ToString() + " from cache to " + ret.ToString());
                return(ret);
            }

            /* We need to send a ARP request out to the network, then respond to
             *  the reply.  Unfortunately, messages sent to the arp subsystem are
             *  processed sequentially, therefore the reply will never be processed
             *  until the current function exits.  To get around this, we tell the
             *  Invoke mechanism not to return from the synchronous call until
             *  we have that response */
            var e = CurrentMessage;

            e.EventSetsOnReturn = false;

            /* Send the request */
            switch (addr.EtherType)
            {
            case 0x0800:
                /* IPv4 */
                HWAddr      sha           = net.devs[dev_no].HWAddr;
                IPv4Address spa           = net.devs[dev_no].addresses[0x0800] as IPv4Address;
                IPv4Address tpa           = addr as IPv4Address;
                byte[]      pkt           = new byte[100];
                int         packet_offset = 32;
                int         packet_len    = 0;

                pkt[packet_offset + packet_len++] = 0x00;           // HTYPE
                pkt[packet_offset + packet_len++] = 0x01;
                pkt[packet_offset + packet_len++] = 0x08;           // PTYPE
                pkt[packet_offset + packet_len++] = 0x00;
                pkt[packet_offset + packet_len++] = 0x06;           // HLEN
                pkt[packet_offset + packet_len++] = 0x04;           // PLEN
                pkt[packet_offset + packet_len++] = 0x00;           // OPER
                pkt[packet_offset + packet_len++] = 0x01;

                // SHA
                for (int i = 0; i < 6; i++)
                {
                    pkt[packet_offset + packet_len++] = sha.MAC[i];
                }
                // SPA
                for (int i = 0; i < 4; i++)
                {
                    pkt[packet_offset + packet_len++] = spa.Octets[i];
                }
                // THA
                for (int i = 0; i < 6; i++)
                {
                    pkt[packet_offset + packet_len++] = 0;
                }
                // TPA
                for (int i = 0; i < 4; i++)
                {
                    pkt[packet_offset + packet_len++] = tpa.Octets[i];
                }

                net.TransmitEthernetPacket(pkt, dev_no, packet_offset,
                                           packet_len, HWAddr.Multicast, 0x0806);

                break;
            }

            // Store this request
            GetPendingRequestList(dev_no, addr.EtherType, addr).Add(e);

            // Return null for now until we actually get a result
            return(null);
        }