예제 #1
0
파일: arp.cs 프로젝트: jncronin/tysos
        public RPCResult <bool> PacketReceived(byte[] packet, int dev_no, int payload_offset,
                                               int payload_len, p_addr src)
        {
            ushort htype = net.ReadWord(packet, payload_offset);
            ushort ptype = net.ReadWord(packet, payload_offset + 2);
            byte   hlen  = packet[payload_offset + 4];
            byte   plen  = packet[payload_offset + 5];
            ushort oper  = net.ReadWord(packet, payload_offset + 6);

            if (htype != 1)
            {
                System.Diagnostics.Debugger.Log(0, null, "Packet with unknown HTYPE: " +
                                                htype.ToString("X4"));
                return(false);
            }
            if (hlen != 6)
            {
                System.Diagnostics.Debugger.Log(0, null, "Invalid HLEN: " +
                                                hlen.ToString());
                return(false);
            }

            HWAddr sha = net.ReadHWAddr(packet, payload_offset + 8);
            HWAddr tha = net.ReadHWAddr(packet, payload_offset + 8 + hlen + plen);

            var nd = net.devs[dev_no];

            // Reject those packets sent by ourselves (don't reply to our own
            //  announce packets)
            if (sha.Equals(nd.HWAddr))
            {
                return(false);
            }

            switch (ptype)
            {
            case 0x0800:
                // IPv4
            {
                if (plen != 4)
                {
                    System.Diagnostics.Debugger.Log(0, null, "Invalid HLEN: " +
                                                    hlen.ToString());
                    return(false);
                }

                IPv4Address spa = net.ReadIPv4Addr(packet, payload_offset + 14);
                IPv4Address tpa = net.ReadIPv4Addr(packet, payload_offset + 24);

                System.Diagnostics.Debugger.Log(0, null, "Received IPv4 packet: oper: " +
                                                oper.ToString() + ", SHA: " + sha.ToString() +
                                                ", SPA: " + spa.ToString() +
                                                ", THA: " + tha.ToString() +
                                                ", TPA: " + tpa.ToString());

                if (oper == 1)
                {
                    /* Is it a request for our own IP address? */
                    //var addr = net.devs[dev_no].a as IPv4Address
                    if (net.devs[dev_no].a.Equals(tpa))
                    {
                        System.Diagnostics.Debugger.Log(0, null, "Received ARP request for our IP");

                        // build a response packet.  We are usually directly above
                        //  the link layer in the stack, so only need to reserve space
                        //  for ethernet headers (if we are not big enough, the
                        //  ethernet layer will do this for us anyway, but it involves
                        //  a memcpy and so is less efficient)

                        byte[] ret           = new byte[100];
                        int    packet_offset = 32;
                        int    packet_len    = 0;

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

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


                        /*net.InvokeAsync("TransmitPacket",
                         *  new object[] { ret, dev_no, packet_offset, packet_len, sha },
                         *  net.sig_packet);*/
                        net.TransmitEthernetPacket(ret, dev_no, packet_offset,
                                                   packet_len, sha, 0x0806);
                    }
                    else if (tpa.Equals(spa) && tha.Equals(HWAddr.Zero))
                    {
                        // This is a gratuitous request (announce) packet
                        // Interpret it as a response
                        oper = 2;
                    }
                }
                if (oper == 2)
                {
                    /* This is a reply to a previous request, or an announcement */

                    // Cache the current response
                    System.Diagnostics.Debugger.Log(0, null, "Cacheing " +
                                                    spa.ToString() + " to " + sha.ToString());
                    GetProtocolDictionary(dev_no, 0x0800)[spa] = sha;

                    // Fulfil pending requests
                    var pending_list = GetPendingRequestList(dev_no, 0x0800,
                                                             spa);
                    while (pending_list.Count > 0)
                    {
                        var e = pending_list[pending_list.Count - 1];
                        System.Diagnostics.Debugger.Log(0, null, "Handling pending request");
                        ((RPCResult <HWAddr>)e.result).Result = sha;
                        e.result.Set();
                        pending_list.RemoveAt(pending_list.Count - 1);
                    }

                    // Remove the pointer to the pending list so it is collected
                    pending_reqs[dev_no][0x0800].Remove(spa);
                }
            }
            break;

            default:
                System.Diagnostics.Debugger.Log(0, null, "Packet with unknown PTYPE: " +
                                                htype.ToString("X4"));
                return(false);
            }

            return(true);
        }
예제 #2
0
        public RPCResult <bool> PacketReceived(byte[] packet, int dev_no, int payload_offset,
                                               int payload_len, p_addr src)
        {
            /* Parse the provided packet */

            // check version
            uint ver = (uint)(packet[payload_offset] >> 4) & 0xfU;

            if (ver != 4)
            {
                System.Diagnostics.Debugger.Log(0, null, "Packet dropped as version incorrect: " +
                                                ver.ToString());
                return(false);
            }

            // get header length (in bytes)
            int hlen = (int)((packet[payload_offset] & 0xfU) * 4);

            // checksum
            uint csum = calc_checksum(packet, payload_offset, hlen);

            if (csum != 0)
            {
                StringBuilder sb = new StringBuilder();
                sb.Append("Packet dropped as checksum incorrect: ");
                sb.Append(csum.ToString());
                sb.Append(".  Packet header length: ");
                sb.Append(hlen.ToString());
                sb.Append(", words: ");
                for (int i = 0; i < hlen; i += 2)
                {
                    if (i != 0)
                    {
                        sb.Append(" ");
                    }
                    sb.Append(net.ReadWord(packet, payload_offset + i).ToString("X4"));
                }
                System.Diagnostics.Debugger.Log(0, null, sb.ToString());
                return(false);
            }

            // get packet length (excluding header)
            int plen = net.ReadWord(packet, payload_offset + 2) - hlen;

            // get fragment offset and flags field
            ushort frag_off_flags = net.ReadWord(packet, payload_offset + 6);
            uint   flags          = (uint)(frag_off_flags >> 13) & 0x3U;

            // don't handle fragmented packets yet
            if (flags != 0)
            {
                System.Diagnostics.Debugger.Log(0, null, "Packet dropped as fragmented");
                return(false);
            }

            // get protocol
            byte prot = packet[payload_offset + 9];

            // get source and dest IPs
            IPv4Address spa = net.ReadIPv4Addr(packet, payload_offset + 12);
            IPv4Address dpa = net.ReadIPv4Addr(packet, payload_offset + 16);

            System.Diagnostics.Debugger.Log(0, null, "Received packet from " +
                                            spa.ToString() + " to " + dpa.ToString() + ", protocol 0x" +
                                            prot.ToString("X2"));

            // Do we accept the destination address?
            bool found = false;

            foreach (var addr in net.addrs)
            {
                // check octet by octet so we also catch broadcast addresses
                IPv4Address tpa = addr.Key as IPv4Address;
                if (tpa != null)
                {
                    bool pass = true;
                    for (int i = 0; i < 4; i++)
                    {
                        uint mask       = 0xffU << ((3 - i) * 8);
                        uint dpa_masked = dpa.addr & mask;
                        if (dpa_masked != mask && dpa_masked != (tpa.addr & mask))
                        {
                            pass = false;
                            break;
                        }
                    }
                    if (pass)
                    {
                        found = true;
                        break;
                    }
                }
            }

            if (found)
            {
                IPacketHandler prot_handler;
                if (packet_handlers.TryGetValue(prot, out prot_handler))
                {
                    prot_handler.PacketReceived(packet, dev_no, payload_offset + hlen, plen, spa);
                }
            }

            return(true);
        }