Пример #1
0
        public RPCResult <bool> PacketReceived(byte[] packet, int dev_no, int payload_offset,
                                               int payload_len, p_addr devsrc)
        {
            HWAddr dest = ReadHWAddr(packet, payload_offset);
            HWAddr src  = ReadHWAddr(packet, payload_offset + 6);

            /* Whole packet is 6 bytes dest MAC, 6 bytes source MAC,
             *  optional 4 bytes VLAN packet, 2 bytes ethertype,
             *  payload, 4 bytes frame check sequence (FCS) */
            payload_len    -= 18;
            payload_offset += 14;

            if (packet[14] == 0x81 && packet[15] == 0x00)
            {
                /* This is a VLAN tagged packet
                 *  We don't do anything special (yet) */
                payload_len    -= 4;
                payload_offset += 4;
            }

            ushort ethertype = (ushort)(((uint)packet[payload_offset - 2] << 8) |
                                        packet[payload_offset - 1]);

            System.Diagnostics.Debugger.Log(0, null, "Received packet of size " +
                                            packet.Length.ToString() + ", ethertype: " + ethertype.ToString("X4") +
                                            " from device " + dev_no.ToString());

            if (packet_handlers.ContainsKey(ethertype))
            {
                packet_handlers[ethertype].PacketReceived(packet, dev_no, payload_offset, payload_len, src);
            }

            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 */

            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);
        }
Пример #3
0
        List <RPCMessage> GetPendingRequestList(int dev_no, ushort etype,
                                                p_addr addr)
        {
            /* Get the address->hwaddr dictionary, creating the various layers
             *  as we go */
            Dictionary <ushort, Dictionary <p_addr, List <RPCMessage> > > nd_dict;

            if (pending_reqs.TryGetValue(dev_no, out nd_dict) == false)
            {
                nd_dict = new Dictionary <ushort, Dictionary <p_addr, List <RPCMessage> > >(
                    new tysos.Program.MyGenericEqualityComparer <ushort>());
                pending_reqs[dev_no] = nd_dict;
            }

            Dictionary <p_addr, List <RPCMessage> > prot_dict;

            if (nd_dict.TryGetValue(etype, out prot_dict) == false)
            {
                prot_dict = new Dictionary <p_addr, List <RPCMessage> >(
                    new tysos.Program.MyGenericEqualityComparer <p_addr>());
                nd_dict[etype] = prot_dict;
            }

            List <RPCMessage> ret;

            if (prot_dict.TryGetValue(addr, out ret) == false)
            {
                ret             = new List <RPCMessage>();
                prot_dict[addr] = ret;
            }

            return(ret);
        }
Пример #4
0
        public override bool Equals(p_addr other)
        {
            IPv4Address o = other as IPv4Address;

            if (o == null)
            {
                return(false);
            }
            return(addr == o.addr);
        }
Пример #5
0
        public override bool Equals(p_addr other)
        {
            HWAddr o = other as HWAddr;

            if (o == null)
            {
                return(false);
            }
            for (int i = 0; i < 6; i++)
            {
                if (mac[i] != o.mac[i])
                {
                    return(false);
                }
            }
            return(true);
        }
Пример #6
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);
        }
Пример #7
0
        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);
        }
Пример #8
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);
        }
Пример #9
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);
        }