/// <summary>
        /// Handles RIPv1 updates
        /// </summary>
        /// <param name="udpFrame"></param>
        /// <param name="ipFrame"></param>
        /// <returns>Bool indicating if something changed</returns>
        private bool HandleRIPV1(UDP.UDPFrame udpFrame, IP.IPFrame ipFrame)
        {
            RIPFrame fRIPFrame;
            bool     bChanged = false;

            if (ipFrame.SourceAddress.Equals(IPAddress.Broadcast)) // Check Addr
            {
                if (udpFrame.DestinationPort == iRIPPort)          // Check Port
                {
                    fRIPFrame = new RIPFrame(udpFrame.EncapsulatedFrame.FrameBytes);
                    if (fRIPFrame.Version == 1)
                    {
                        foreach (RIPUpdate ru in fRIPFrame.GetUpdates())
                        {
                            if (ru.AddressFamilyIdentifier == RIPEntryAddressFamily.IPv4)
                            {
                                bChanged |= UpdateEntry(ipFrame.SourceAddress, ru.Address, IPAddressAnalysis.GetClassfullSubnetMask(ru.Address), (int)ru.Metric);
                            }
                        }
                    }
                }
            }

            return(bChanged);
        }
Beispiel #2
0
        /// <summary>
        /// Applies all known rules sequentially to the given frame, until a rule matches
        /// </summary>
        /// <param name="fInputFrame">The frame to analyze</param>
        protected override void HandleTraffic(Frame fInputFrame)
        {
            IP.IPFrame             ipv4Frame = GetIPv4Frame(fInputFrame);
            UDP.UDPFrame           udpFrame  = GetUDPFrame(fInputFrame);
            TCP.TCPFrame           tcpFrame  = GetTCPFrame(fInputFrame);
            Ethernet.EthernetFrame ethFrame  = GetEthernetFrame(fInputFrame);

            lock (tsrRules)
            {
                foreach (TrafficSplitterRule tsr in tsrRules)
                {
                    if (tsr.IsMatch(fInputFrame, ethFrame, ipv4Frame, udpFrame, tcpFrame))
                    {
                        if (tsr.Action == TrafficSplitterActions.SendToA)
                        {
                            NotifyA(fInputFrame);
                            return;
                        }
                        else if (tsr.Action == TrafficSplitterActions.SendToB)
                        {
                            NotifyB(fInputFrame);
                            return;
                        }
                        else if (tsr.Action == TrafficSplitterActions.Drop)
                        {
                            //Drop
                            PushDroppedFrame(fInputFrame);
                            return;
                        }
                    }
                }
            }

            NotifyA(fInputFrame);
        }
        /// <summary>
        /// Checks the incoming traffic for RIP updates.
        /// </summary>
        /// <param name="fInputFrame">The frame to handle.</param>
        protected override void HandleTraffic(Frame fInputFrame)
        {
            IRouter rtRouterToManage    = this.RouterToManage;
            TrafficDescriptionFrame tdf = (TrafficDescriptionFrame)GetFrameByType(fInputFrame, FrameTypes.TrafficDescriptionFrame);

            if (!bShutdownPending)
            {
                UDP.UDPFrame udpFrame = GetUDPFrame(fInputFrame);
                IP.IPFrame   ipFrame  = GetIPv4Frame(fInputFrame);

                if (udpFrame != null && ipFrame != null && rtRouterToManage != null && udpFrame.EncapsulatedFrame != null)
                {
                    if (iVersion == 1)
                    {
                        if (HandleRIPV1(udpFrame, ipFrame))
                        {
                            DistributeUpdate(tdf.SourceInterface);
                        }
                    }
                    else if (iVersion == 2)
                    {
                        if (HandleRIPV2(udpFrame, ipFrame))
                        {
                            DistributeUpdate(tdf.SourceInterface);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Tries to extract a DHCP frame from this frame and forwards it to the HandleDHCPFrame method
        /// </summary>
        /// <param name="fInputFrame">The frame to handle</param>
        protected override void HandleTraffic(Frame fInputFrame)
        {
            if (bShuttingDown)
            {
                return; //Shutdown pending.
            }
            UDP.UDPFrame            udpFrame = GetUDPFrame(fInputFrame);
            TrafficDescriptionFrame tdf      = (TrafficDescriptionFrame)GetFrameByType(fInputFrame, FrameTypes.TrafficDescriptionFrame);

            IP.IPFrame     ipFrame   = GetIPFrame(fInputFrame);
            DHCP.DHCPFrame dhcpFrame = (DHCP.DHCPFrame)GetFrameByType(fInputFrame, FrameTypes.DHCP);

            if (dhcpFrame != null && ipFrame != null && udpFrame != null && tdf != null)
            {
                HandleDHCPFrame(dhcpFrame, udpFrame, ipFrame, tdf, fInputFrame);
            }
        }
        /// <summary>
        /// Handles RIPv2 Frames
        /// </summary>
        /// <param name="udpFrame"></param>
        /// <param name="ipFrame"></param>
        /// <returns>Bool indicating if something changed</returns>
        private bool HandleRIPV2(UDP.UDPFrame udpFrame, IP.IPFrame ipFrame)
        {
            RIPFrame fRIPFrame;
            bool     bChanged = false;

            if (ipFrame.SourceAddress.Equals(IPAddress.Broadcast))
            {
                HandleRIPV1(udpFrame, ipFrame);                          // RIPv1? Fallback!
            }
            else if (ipFrame.DestinationAddress.Equals(ipaRIPv2Address)) // Check Addr
            {
                if (udpFrame.DestinationPort == iRIPPort)                //Check Port
                {
                    fRIPFrame = new RIPFrame(udpFrame.EncapsulatedFrame.FrameBytes);

                    if (fRIPFrame.Version == 2)
                    {
                        foreach (RIPUpdate ru in fRIPFrame.GetUpdates())
                        {
                            if (ru.AddressFamilyIdentifier == RIPEntryAddressFamily.IPv4)
                            {
                                if (!IsHoldDown(ru.Address))
                                {
                                    bChanged |= UpdateEntry(ipFrame.SourceAddress, ru.Address, ru.Ripv2SubnetMask, (int)ru.Metric);
                                }
                            }
                        }
                    }
                    else
                    {
                        bChanged |= HandleRIPV1(udpFrame, ipFrame);
                    }
                }
            }

            return(bChanged);
        }
Beispiel #6
0
        /// <summary>
        /// Handles a DHCP frame and sends responses and requests or leases addresses according to its contents
        /// </summary>
        /// <param name="dhcFrame">The DHCP frame to handle</param>
        /// <param name="udpFrame">The UDP frame</param>
        /// <param name="ipv4Frame">The IPv4 frame</param>
        /// <param name="tdf">The traffic description frame</param>
        /// <param name="fInputFrame">The original input frame</param>
        protected override void HandleDHCPFrame(DHCPFrame dhcFrame, UDP.UDPFrame udpFrame, IP.IPFrame ipv4Frame, TrafficDescriptionFrame tdf, Frame fInputFrame)
        {
            base.HandleDHCPFrame(dhcFrame, udpFrame, ipv4Frame, tdf, fInputFrame);

            EthernetFrame ethFrame = GetEthernetFrame(fInputFrame);

            bool bIsOffer = false;
            bool bIsACK   = false;

            foreach (DHCPTLVItem tlvItem in dhcFrame.GetDHCPTLVItems())
            {
                if (tlvItem.DHCPOptionType == DHCPOptions.DHCPMessageType)
                {
                    if (dhcFrame.MessageType == DHCPType.BootReply && (DHCPMessageType)tlvItem.Data[0] == DHCPMessageType.Offer && lOpenClientTransactions.Contains(dhcFrame.TransactionID))
                    {
                        bIsOffer = true;
                        break;
                    }
                    if (dhcFrame.MessageType == DHCPType.BootReply && (DHCPMessageType)tlvItem.Data[0] == DHCPMessageType.ACK && lOpenClientTransactions.Contains(dhcFrame.TransactionID))
                    {
                        bIsACK = true;
                        break;
                    }
                }
            }

            if (bIsOffer)
            {
                #region Client Process offer
                IPAddress ipaServer = ipv4Frame.SourceAddress;
                IPAddress myAddress = dhcFrame.OfferedAddress;

                DHCPFrame newDHCPFrame = new DHCPFrame();
                newDHCPFrame.ClientAddress       = IPAddress.Any;
                newDHCPFrame.ClientMac           = dhcFrame.ClientMac;
                newDHCPFrame.Hardwarelen         = 6;
                newDHCPFrame.HardwareType        = eExNetworkLibrary.HardwareAddressType.Ethernet;
                newDHCPFrame.Hops                = 0;
                newDHCPFrame.MessageType         = DHCPType.BootRequest;
                newDHCPFrame.OfferedAddress      = IPAddress.Any;
                newDHCPFrame.RelayAddress        = IPAddress.Any;
                newDHCPFrame.RequestedFile       = "";
                newDHCPFrame.RequestedServerName = "";
                newDHCPFrame.Secs                = dhcFrame.Secs + 1;
                newDHCPFrame.ServerAddress       = IPAddress.Any;
                newDHCPFrame.ValidIPFlag         = true;
                newDHCPFrame.TransactionID       = dhcFrame.TransactionID;

                DHCPTLVItem tlvItem = new DHCPTLVItem();
                tlvItem.DHCPOptionType = DHCPOptions.DHCPMessageType;
                tlvItem.Data           = new byte[] { (byte)DHCPMessageType.Request };

                newDHCPFrame.AddDHCPTLVItem(tlvItem);

                tlvItem = new DHCPTLVItem();
                tlvItem.DHCPOptionType = DHCPOptions.ClientID;
                byte[] bIDData = new byte[7];
                bIDData[0] = (byte)HardwareAddressType.Ethernet;
                dhcFrame.ClientMac.AddressBytes.CopyTo(bIDData, 1);
                tlvItem.Data = bIDData;

                newDHCPFrame.AddDHCPTLVItem(tlvItem);

                tlvItem = new DHCPTLVItem();
                tlvItem.DHCPOptionType = DHCPOptions.AddressRequest;
                tlvItem.Data           = myAddress.GetAddressBytes();

                newDHCPFrame.AddDHCPTLVItem(tlvItem);

                tlvItem = new DHCPTLVItem();
                tlvItem.DHCPOptionType = DHCPOptions.Hostname;
                tlvItem.Data           = Encoding.ASCII.GetBytes(strHostnameToSpoof + iIPIDCounter);

                newDHCPFrame.AddDHCPTLVItem(tlvItem);

                tlvItem = new DHCPTLVItem();
                tlvItem.DHCPOptionType = DHCPOptions.DHCPServerID;
                tlvItem.Data           = ipaServer.GetAddressBytes();

                newDHCPFrame.AddDHCPTLVItem(tlvItem);

                UDP.UDPFrame newUDPFrame = new eExNetworkLibrary.UDP.UDPFrame();
                newUDPFrame.DestinationPort   = iDHCPOutPort;
                newUDPFrame.SourcePort        = iDHCPInPort;
                newUDPFrame.EncapsulatedFrame = newDHCPFrame;

                IP.IPv4Frame newIPv4Frame = new eExNetworkLibrary.IP.IPv4Frame();
                newIPv4Frame.Version            = 4;
                newIPv4Frame.DestinationAddress = IPAddress.Broadcast;
                newIPv4Frame.SourceAddress      = IPAddress.Any;
                newIPv4Frame.Protocol           = eExNetworkLibrary.IP.IPProtocol.UDP;
                newIPv4Frame.EncapsulatedFrame  = newUDPFrame;
                newIPv4Frame.Identification     = (uint)IncrementIPIDCounter();
                newIPv4Frame.TimeToLive         = 128;

                ethFrame                   = new eExNetworkLibrary.Ethernet.EthernetFrame();
                ethFrame.Destination       = new MACAddress(new byte[] { 255, 255, 255, 255, 255, 255 });
                ethFrame.Source            = dhcFrame.ClientMac;
                ethFrame.EtherType         = eExNetworkLibrary.EtherType.IPv4;
                ethFrame.EncapsulatedFrame = newIPv4Frame;

                TrafficDescriptionFrame tdFrame = new TrafficDescriptionFrame(null, DateTime.Now);
                tdFrame.EncapsulatedFrame = ethFrame;

                if (tdf != null && tdf.SourceInterface != null)
                {
                    tdf.SourceInterface.Send(tdFrame);
                }
                #endregion
            }
            else if (bIsACK)
            {
                #region Client Process ACK
                if (tdf != null && tdf.SourceInterface != null)
                {
                    IPInterface  ipiSource = tdf.SourceInterface;
                    DHCPPool     dhPool    = GetPoolForInterface(ipiSource);
                    DHCPPoolItem dpiItem   = new DHCPPoolItem();
                    dpiItem.Address = dhcFrame.OfferedAddress;
                    if (dhPool.GetItemForAddress(dpiItem.Address) == null)
                    {
                        if (bRedirectGateway)
                        {
                            if (ipaGateway == null)
                            {
                                dpiItem.Gateway = ipiSource.IpAddresses[0];
                            }
                            else
                            {
                                dpiItem.Gateway = ipaGateway;
                            }
                        }
                        else
                        {
                            IPAddress ipGateway = IPAddress.Any;
                            foreach (DHCPTLVItem tlvItem in dhcFrame.GetDHCPTLVItems())
                            {
                                if (tlvItem.DHCPOptionType == DHCPOptions.Router)
                                {
                                    ipGateway = new IPAddress(tlvItem.Data);
                                    break;
                                }
                            }
                            dpiItem.DNSServer = ipGateway;
                        }
                        if (bRedirectDNSServer)
                        {
                            if (ipaDNSServer == null)
                            {
                                dpiItem.DNSServer = ipiSource.IpAddresses[0];
                            }
                            else
                            {
                                dpiItem.DNSServer = ipaDNSServer;
                            }
                        }
                        else
                        {
                            IPAddress ipDNS = IPAddress.Any;
                            foreach (DHCPTLVItem tlvItem in dhcFrame.GetDHCPTLVItems())
                            {
                                if (tlvItem.DHCPOptionType == DHCPOptions.DomainNameServer)
                                {
                                    ipDNS = new IPAddress(tlvItem.Data);
                                    break;
                                }
                            }
                            dpiItem.DNSServer = ipDNS;
                        }

                        IPAddress ipServer = null;
                        foreach (DHCPTLVItem tlvItem in dhcFrame.GetDHCPTLVItems())
                        {
                            if (tlvItem.DHCPOptionType == DHCPOptions.DHCPServerID)
                            {
                                ipServer = new IPAddress(tlvItem.Data);
                                break;
                            }
                        }

                        dpiItem.DHCPServer = ipServer;

                        dpiItem.Netmask       = ipiSource.Subnetmasks[0];
                        dpiItem.DHCPServerMAC = ethFrame.Source;
                        AddPoolItem(dpiItem, dhPool, ipiSource);
                        dictPoolItemSpoofedMAC.Add(dpiItem, dhcFrame.ClientMac);
                        if (dictIPSpoofedMACs.ContainsKey(dpiItem.Address))
                        {
                            dictIPSpoofedMACs.Remove(dpiItem.Address);
                        }
                        dictIPSpoofedMACs.Add(dpiItem.Address, dhcFrame.ClientMac);
                        lServers.Add(ipv4Frame.SourceAddress);
                        InvokeAddressStolen(new DHCPServerEventArgs(dhPool, dpiItem, ipiSource));
                    }
                }
                lOpenClientTransactions.Remove(dhcFrame.TransactionID);
                #endregion
            }
        }
        /// <summary>
        /// Forces this instance to distribute traffic immidiately, with exluding the specified interface from forwarding operations.
        /// </summary>
        /// <param name="ipiExcludeInterface">The interface to exclude from forwarding operations or null, if no interface should be excluded.</param>
        public void DistributeUpdate(IPInterface ipiExcludeInterface)
        {
            IRouter rtRouter = this.RouterToManage;

            if (rtRouter != null)
            {
                RIPFrame rf = new RIPFrame();
                rf.Version = (uint)this.iVersion;
                rf.Command = RipCommand.RIPResponse;

                RoutingEntry[] arre = rtRouter.RoutingTable.GetRoutes();

                foreach (RoutingEntry re in arre)
                {
                    if (re.Owner == RoutingEntryOwner.RIP || re.Owner == RoutingEntryOwner.Interface)
                    {
                        if (this.iVersion == 1)
                        {
                            rf.AddUpdate(new RIPUpdate(RIPEntryAddressFamily.IPv4, new byte[2], new Subnetmask(), IPAddress.Any, re.Destination, (uint)((re.Metric + 1) > 16 ? 16 : (re.Metric + 1))));
                        }
                        else if (this.iVersion == 2)
                        {
                            rf.AddUpdate(new RIPUpdate(RIPEntryAddressFamily.IPv4, new byte[2], re.Subnetmask, IPAddress.Any, re.Destination, (uint)((re.Metric + 1) > 16 ? 16 : (re.Metric + 1))));
                        }
                    }
                    else if ((re.Owner == RoutingEntryOwner.UserStatic || re.Owner == RoutingEntryOwner.System) && this.bRedistributeStatic)
                    {
                        if (this.iVersion == 1)
                        {
                            rf.AddUpdate(new RIPUpdate(RIPEntryAddressFamily.IPv4, new byte[2], new Subnetmask(), IPAddress.Any, re.Destination, 1));
                        }
                        else if (this.iVersion == 2)
                        {
                            rf.AddUpdate(new RIPUpdate(RIPEntryAddressFamily.IPv4, new byte[2], re.Subnetmask, IPAddress.Any, re.Destination, 1));
                        }
                    }
                }

                UDP.UDPFrame uf = new UDP.UDPFrame();
                uf.DestinationPort   = iRIPPort;
                uf.SourcePort        = iRIPPort;
                uf.EncapsulatedFrame = rf;

                foreach (IPInterface ipi in lInterfaces)
                {
                    if (ipi != ipiExcludeInterface && ipi.IpAddresses.Length > 0 && !ipiPassiveInterfaces.Contains(ipi))
                    {
                        IP.IPv4Frame ipf = new IP.IPv4Frame();
                        ipf.SourceAddress = ipi.IpAddresses[0];
                        if (iVersion == 2)
                        {
                            ipf.DestinationAddress = ipaRIPv2Address;
                        }
                        else if (iVersion == 1)
                        {
                            ipf.DestinationAddress = IPAddress.Broadcast;
                        }
                        ipf.Protocol          = eExNetworkLibrary.IP.IPProtocol.UDP;
                        ipf.Version           = 4;
                        ipf.EncapsulatedFrame = uf;

                        TrafficDescriptionFrame tdf = new TrafficDescriptionFrame(null, DateTime.Now);
                        tdf.EncapsulatedFrame = ipf;

                        ipi.Send(tdf, IPAddress.Broadcast);
                    }
                }
            }
        }
Beispiel #8
0
        /// <summary>
        /// Checkes whether this rule matches a given frame.
        /// </summary>
        /// <param name="frame">The original frame</param>
        /// <param name="ethFrame">The Ethernet part of the frame</param>
        /// <param name="ipv4Frame">The IPv4 part of the frame</param>
        /// <param name="udpFrame">The UDP part of the frame</param>
        /// <param name="tcpFrame">The TCP part of the frame</param>
        /// <returns>A bool indicating whether this rule matches a given frame.</returns>
        public virtual bool IsMatch(Frame frame, Ethernet.EthernetFrame ethFrame, IP.IPFrame ipFrame, UDP.UDPFrame udpFrame, TCP.TCPFrame tcpFrame)
        {
            lock (lChildRules)
            {
                if (lChildRules.Count == 0)
                {
                    return(true); //Nothing to validate
                }
                foreach (TrafficSplitterRule tsrRule in lChildRules)
                {
                    if (tsrRule.IsMatch(frame, ethFrame, ipFrame, udpFrame, tcpFrame))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Beispiel #9
0
        private void HandleFromInternal(Frame fInputFrame, int iSourcePort, int iDestinationPort, IP.IPFrame ipFrame, TCP.TCPFrame tcpFrame, UDP.UDPFrame udpFrame)
        {
            NATEntry neEntry = GetTranslationEntry(ipFrame.SourceAddress, ipFrame.DestinationAddress, iSourcePort, iDestinationPort, ipFrame.Protocol);

            if (neEntry == null)
            {
                neEntry = CreateTranslationEntry(ipFrame.SourceAddress, ipFrame.DestinationAddress, iSourcePort, iDestinationPort, ipFrame.Protocol);
            }

            ipFrame.SourceAddress = neEntry.TranslatedSourceAddress;
            if (tcpFrame != null)
            {
                tcpFrame.SourcePort = neEntry.TranslatedSourcePort;
                tcpFrame.Checksum   = tcpFrame.CalculateChecksum(ipFrame.GetPseudoHeader());

                CheckForTCPFinish(tcpFrame, neEntry);
            }
            else if (udpFrame != null)
            {
                udpFrame.SourcePort = neEntry.TranslatedSourcePort;
                udpFrame.Checksum   = udpFrame.CalculateChecksum(ipFrame.GetPseudoHeader());
            }

            NotifyNextExternal(ipFrame);
        }
Beispiel #10
0
        private void HandleFromExternal(Frame fInputFrame, int iSourcePort, int iDestinationPort, IP.IPFrame ipFrame, TCP.TCPFrame tcpFrame, UDP.UDPFrame udpFrame)
        {
            NATEntry neEntry = GetReTranslationEntry(ipFrame.DestinationAddress, ipFrame.SourceAddress, iDestinationPort, iSourcePort, ipFrame.Protocol);

            if (neEntry != null)
            {
                ipFrame.DestinationAddress = neEntry.OriginalSourceAddress;
                if (tcpFrame != null)
                {
                    tcpFrame.DestinationPort = neEntry.OriginalSourcePort;
                    tcpFrame.Checksum        = tcpFrame.CalculateChecksum(ipFrame.GetPseudoHeader());

                    CheckForTCPFinish(tcpFrame, neEntry);
                }
                else if (udpFrame != null)
                {
                    udpFrame.DestinationPort = neEntry.OriginalSourcePort;
                    udpFrame.Checksum        = udpFrame.CalculateChecksum(ipFrame.GetPseudoHeader());
                }

                NotifyNextInternal(ipFrame);
            }
            else
            {
                PushDroppedFrame(fInputFrame);
                if (bThrowOnNonNATFrame)
                {
                    throw new Exception("The external frame was discarded because there was no corresponding translation entry in the database. (Source: " + ipFrame.SourceAddress + "/" + iSourcePort + ", Destination: " + ipFrame.DestinationAddress + "/" + iDestinationPort + ", Protocol: " + ipFrame.Protocol.ToString());
                }
            }
        }
Beispiel #11
0
        /// <summary>
        /// Extracts a IP frame and does some NAT
        /// </summary>
        /// <param name="fInputFrame">The frame to handle</param>
        protected override void HandleTraffic(Frame fInputFrame)
        {
            int iSourcePort      = 0;
            int iDestinationPort = 0;

            if (fInputFrame.FrameType != NATDescriptionFrame.DefaultFrameType)
            {
                throw new Exception("A frame without a NATDescription was received by the NAT handler. This must not happen and indicates a serious internal error.");
            }

            NATDescriptionFrame ndDescription = (NATDescriptionFrame)fInputFrame;

            fInputFrame = ndDescription.EncapsulatedFrame;

            IP.IPFrame   ipFrame  = GetIPv4Frame(fInputFrame);
            TCP.TCPFrame tcpFrame = GetTCPFrame(fInputFrame);
            UDP.UDPFrame udpFrame = null;

            if (tcpFrame != null)
            {
                iSourcePort      = tcpFrame.SourcePort;
                iDestinationPort = tcpFrame.DestinationPort;
            }
            else
            {
                udpFrame = GetUDPFrame(fInputFrame);
                if (udpFrame != null)
                {
                    iSourcePort      = udpFrame.SourcePort;
                    iDestinationPort = udpFrame.DestinationPort;
                }
            }

            if (ipFrame != null)
            {
                if (ndDescription.Source == NATDescriptionFrame.NATFrameSource.Internal)
                {
                    //In to out
                    if (IsInternalRange(ipFrame.SourceAddress))
                    {
                        HandleFromInternal(fInputFrame, iSourcePort, iDestinationPort, ipFrame, tcpFrame, udpFrame);
                    }
                    else
                    {
                        NotifyNextExternal(fInputFrame);
                    }
                }
                else if (ndDescription.Source == NATDescriptionFrame.NATFrameSource.External)
                {
                    //Out to in
                    if (IsExternalRange(ipFrame.DestinationAddress))
                    {
                        HandleFromExternal(fInputFrame, iSourcePort, iDestinationPort, ipFrame, tcpFrame, udpFrame);
                    }
                    else
                    {
                        NotifyNextInternal(fInputFrame);
                    }
                }
            }
        }