Example #1
0
        //Populate v4 options.
        //@param link the link
        //@param configObj the config object or null if none
        protected void PopulateV4Reply(DhcpLink dhcpLink, DhcpV4OptionConfigObject configObj)
        {
            string sname = DhcpServerPolicies.EffectivePolicy(_requestMsg, configObj,
                                                              dhcpLink.GetLink(), Property.V4_HEADER_SNAME);

            if (!String.IsNullOrEmpty(sname))
            {
                _replyMsg.SetsName(sname);
            }

            string filename = DhcpServerPolicies.EffectivePolicy(_requestMsg, configObj,
                                                                 dhcpLink.GetLink(), Property.V4_HEADER_FILENAME);

            if (!String.IsNullOrEmpty(filename))
            {
                _replyMsg.SetFile(filename);
            }

            Dictionary <int, DhcpOption> optionMap =
                _dhcpServerConfig.EffectiveV4AddrOptions(_requestMsg, dhcpLink, configObj);

            if (DhcpServerPolicies.EffectivePolicyAsBoolean(configObj,
                                                            dhcpLink.GetLink(), Property.SEND_REQUESTED_OPTIONS_ONLY))
            {
                optionMap = RequestedOptions(optionMap, _requestMsg);
            }
            _replyMsg.PutAllDhcpOptions(optionMap);

            // copy the relay agent info option from request to reply
            // in order to echo option back to router as required
            if (_requestMsg.HasOption(DhcpConstants.V4OPTION_RELAY_INFO))
            {
                _requestMsg.PutDhcpOption(_requestMsg.GetDhcpOption(DhcpConstants.V4OPTION_RELAY_INFO));
            }
        }
Example #2
0
        /**
         * Build a BindingAddress for the given InetAddress and DhcpLink.
         *
         * @param inetAddr the inet addr
         * @param clientLink the client link
         * @param requestMsg the request msg
         *
         * @return the binding address
         */
        protected override BindingObject BuildBindingObject(IPAddress inetAddr,
                                                            DhcpLink clientLink, DhcpMessage requestMsg)
        {
            V6AddressBindingPool bp =
                (V6AddressBindingPool)FindBindingPool(clientLink.GetLink(), inetAddr, requestMsg);

            if (bp != null)
            {
                bp.SetUsed(inetAddr);   // TODO check if this is necessary
                IaAddress iaAddr = new IaAddress();
                iaAddr.SetIpAddress(inetAddr);
                V6BindingAddress bindingAddr = new V6BindingAddress(iaAddr, bp);
                SetBindingObjectTimes(bindingAddr,
                                      bp.GetPreferredLifetimeMs(), bp.GetPreferredLifetimeMs());
                // TODO store the configured options in the persisted binding?
                // bindingAddr.setDhcpOptions(bp.getDhcpOptions());
                return(bindingAddr);
            }
            else
            {
                log.Error("Failed to create BindingAddress: No BindingPool found for IP=" +
                          inetAddr.ToString());
            }
            // MUST have a BindingPool, otherwise something's broke
            return(null);
        }
        /**
         * Create a Binding given an IdentityAssoc loaded from the database.
         *
         * @param ia the ia
         * @param clientLink the client link
         * @param requestMsg the request msg
         *
         * @return the binding
         */
        protected override Binding BuildBindingFromIa(IdentityAssoc ia, DhcpLink clientLink,
                                                      DhcpMessage requestMsg)
        {
            Binding          binding = new Binding(ia, clientLink);
            List <IaAddress> iaAddrs = ia.GetIaAddresses();

            if ((iaAddrs != null) && iaAddrs.Count > 0)
            {
                List <IaAddress> bindingAddrs = new List <IaAddress>();
                foreach (IaAddress iaAddr in iaAddrs)
                {
                    if (!clientLink.GetSubnet().Contains(iaAddr.GetIpAddress()))
                    {
                        log.Info("Ignoring off-link binding address: " +
                                 iaAddr.GetIpAddress().ToString());
                        continue;
                    }
                    V4BindingAddress bindingAddr   = null;
                    StaticBinding    staticBinding =
                        FindStaticBinding(clientLink.GetLink(), ia.GetDuid(),
                                          ia.GetIatype(), ia.GetIaid(), requestMsg);
                    if (staticBinding != null)
                    {
                        bindingAddr =
                            BuildV4StaticBindingFromIaAddr(iaAddr, staticBinding);
                    }
                    else
                    {
                        bindingAddr =
                            BuildV4BindingAddressFromIaAddr(iaAddr, clientLink.GetLink(), requestMsg);
                    }
                    if (bindingAddr != null)
                    {
                        bindingAddrs.Add(bindingAddr);
                    }
                }
                // replace the collection of IaAddresses with BindingAddresses
                binding.SetIaAddresses(bindingAddrs);
            }
            else
            {
                log.Warn("IA has no addresses, binding is empty.");
            }
            return(binding);
        }
        /**
         * Create a Binding given an IdentityAssoc loaded from the database.
         *
         * @param ia the ia
         * @param clientLink the client link
         * @param requestMsg the request msg
         *
         * @return the binding
         */
        protected override Binding BuildBindingFromIa(IdentityAssoc ia,
                                                      DhcpLink clientLink, DhcpMessage requestMsg)
        {
            Binding          binding = new Binding(ia, clientLink);
            List <IaAddress> iaPrefs = ia.GetIaAddresses();

            if ((iaPrefs != null) && iaPrefs.Count > 0)
            {
                List <IaAddress> bindingPrefixes = new List <IaAddress>();
                foreach (IaAddress iaAddr in iaPrefs)
                {
                    // off-link check needed only for v4?
                    //				if (!clientLink.getSubnet().contains(iaAddr.getIpAddress())) {
                    //					log.info("Ignoring off-link binding address: " +
                    //							iaAddr.getIpAddress().getHostAddress());
                    //					continue;
                    //				}
                    V6BindingPrefix bindingPrefix = null;
                    StaticBinding   staticBinding = FindStaticBinding(clientLink.GetLink(), ia.GetDuid(), ia.GetIatype(), ia.GetIaid(), requestMsg);
                    if (staticBinding != null)
                    {
                        bindingPrefix =
                            BuildV6BindingPrefixFromIaPrefix((IaPrefix)iaAddr, staticBinding);
                    }
                    else
                    {
                        bindingPrefix =
                            BuildBindingAddrFromIaPrefix((IaPrefix)iaAddr, clientLink.GetLink(), requestMsg);
                    }
                    if (bindingPrefix != null)
                    {
                        bindingPrefixes.Add(bindingPrefix);
                    }
                }
                // replace the collection of IaPrefixes with BindingPrefixes
                binding.SetIaAddresses(bindingPrefixes);
            }
            else
            {
                log.Warn("IA has no prefixes, binding is empty.");
            }
            return(binding);
        }
Example #5
0
        /// <summary>
        /// Populate reply msg options.
        /// </summary>
        /// <param name="dhcpLink">the link</param>
        protected void PopulateReplyMsgOptions(DhcpLink dhcpLink)
        {
            Dictionary <int, DhcpOption> optionMap = dhcpServerConfig.EffectiveMsgOptions(this.requestMsg, dhcpLink);

            if (DhcpServerPolicies.EffectivePolicyAsBoolean(dhcpLink.GetLink(), Property.SEND_REQUESTED_OPTIONS_ONLY))
            {
                optionMap = this.RequestedOptions(optionMap, this.requestMsg);
            }

            replyMsg.PutAllDhcpOptions(optionMap);
        }
Example #6
0
        protected void PopulatePrefixOptions(DhcpV6IaPrefixOption iaPrefixOption, DhcpLink dhcpLink, DhcpV6OptionConfigObject configObj)
        {
            Dictionary <int, DhcpOption> optionMap = dhcpServerConfig.EffectivePrefixOptions(this.requestMsg, dhcpLink, configObj);

            if (DhcpServerPolicies.EffectivePolicyAsBoolean(configObj, dhcpLink.GetLink(), Property.SEND_REQUESTED_OPTIONS_ONLY))
            {
                optionMap = this.RequestedOptions(optionMap, this.requestMsg);
            }

            iaPrefixOption.PutAllDhcpOptions(optionMap);
        }
Example #7
0
        public Binding CreateSolicitBinding(DhcpLink clientLink, DhcpV6ClientIdOption clientIdOption, DhcpV6IaNaOption iaNaOption, DhcpMessage requestMsg, byte state, IPAddress clientV4IPAddress)
        {
            byte[] duid = clientIdOption.GetDuid();
            long   iaid = iaNaOption.GetIaId();

            StaticBinding staticBinding = FindStaticBinding(clientLink.GetLink(), duid, IdentityAssoc.NA_TYPE, iaid, requestMsg);

            if (staticBinding != null)
            {
                return(base.CreateStaticBinding(clientLink, duid, IdentityAssoc.NA_TYPE, iaid, staticBinding, requestMsg));
            }
            else
            {
                return(base.CreateBinding(clientLink, duid, IdentityAssoc.NA_TYPE,
                                          iaid, GetInetAddrs(iaNaOption), requestMsg, state, clientV4IPAddress));
            }
        }
        public Binding UpdateBinding(Binding binding, DhcpLink clientLink,
                                     byte[] macAddr, DhcpMessage requestMsg, byte state)
        {
            StaticBinding staticBinding =
                FindStaticBinding(clientLink.GetLink(), macAddr, IdentityAssoc.V4_TYPE, 0, requestMsg);

            if (staticBinding != null)
            {
                return(base.UpdateStaticBinding(binding, clientLink, macAddr, IdentityAssoc.V4_TYPE,
                                                0, staticBinding, requestMsg));
            }
            else
            {
                return(base.UpdateBinding(binding, clientLink, macAddr, IdentityAssoc.V4_TYPE,
                                          0, GetInetAddrs(requestMsg), requestMsg, state, null));
            }
        }
Example #9
0
        /**
         * Create a V6BindingAddress given an IaAddress loaded from the database.
         *
         * @param iaAddr the ia addr
         * @param clientLink the client link
         * @param requestMsg the request msg
         *
         * @return the binding address
         */
        private V6BindingAddress BuildV6BindingAddressFromIaAddr(IaAddress iaAddr,
                                                                 DhcpLink clientLink, DhcpMessage requestMsg)
        {
            IPAddress   inetAddr = iaAddr.GetIpAddress();
            BindingPool bp       = FindBindingPool(clientLink.GetLink(), inetAddr, requestMsg);

            if (bp != null)
            {
                // TODO store the configured options in the persisted binding?
                // ipAddr.setDhcpOptions(bp.getDhcpOptions());
                return(new V6BindingAddress(iaAddr, (V6AddressBindingPool)bp));
            }
            else
            {
                log.Error("Failed to create BindingAddress: No BindingPool found for IP=" +
                          inetAddr.ToString());
            }
            // MUST have a BindingPool, otherwise something's broke
            return(null);
        }
        public Binding CreateDiscoverBinding(DhcpLink clientLink, byte[] macAddr,
                                             DhcpMessage requestMsg, byte state)
        {
            lock (_lock)
            {
                StaticBinding staticBinding =
                    FindStaticBinding(clientLink.GetLink(), macAddr, IdentityAssoc.V4_TYPE, 0, requestMsg);

                if (staticBinding != null)
                {
                    return(base.CreateStaticBinding(clientLink, macAddr, IdentityAssoc.V4_TYPE,
                                                    0, staticBinding, requestMsg));
                }
                else
                {
                    return(base.CreateBinding(clientLink, macAddr, IdentityAssoc.V4_TYPE,
                                              0, GetInetAddrs(requestMsg), requestMsg, state, null));
                }
            }
        }
Example #11
0
        protected void ProcessDdnsUpdates(bool sendUpdates)
        {
            bool doForwardUpdate = true;

            DhcpV4ClientFqdnOption clientFqdnOption = (DhcpV4ClientFqdnOption)_requestMsg.GetDhcpOption(DhcpConstants.V4OPTION_CLIENT_FQDN);
            DhcpV4HostnameOption   hostnameOption   = (DhcpV4HostnameOption)_requestMsg.GetDhcpOption(DhcpConstants.V4OPTION_HOSTNAME);

            if (clientFqdnOption == null && hostnameOption == null)
            {
                //TODO allow name generation?
                log.Debug("No Client FQDN nor hostname option in request.  Skipping DDNS update processing.");
                return;
            }

            string fqdn   = "";
            string domain = DhcpServerPolicies.DffectivePolicy(_clientLink.GetLink(), Property.DDNS_DOMAIN);
            DhcpV4ClientFqdnOption replyFqdnOption = null;

            if (clientFqdnOption != null)
            {
                replyFqdnOption = new DhcpV4ClientFqdnOption();
                replyFqdnOption.SetDomainName(clientFqdnOption.GetDomainName());
                replyFqdnOption.SetUpdateABit(false);
                replyFqdnOption.SetOverrideBit(false);
                replyFqdnOption.SetNoUpdateBit(false);
                replyFqdnOption.SetEncodingBit(clientFqdnOption.GetEncodingBit());
                replyFqdnOption.SetRcode1((short)0xff);     // RFC 4702 says server should set to 255
                replyFqdnOption.SetRcode2((short)0xff);     // RFC 4702 says server should set to 255

                fqdn = clientFqdnOption.GetDomainName();
                if ((fqdn == null) || (fqdn.Length <= 0))
                {
                    log.Error("Client FQDN option domain name is null/empty.  No DDNS udpates performed.");
                    replyFqdnOption.SetNoUpdateBit(true);   // tell client that server did no updates
                    _replyMsg.PutDhcpOption(replyFqdnOption);
                    return;
                }

                string policy = DhcpServerPolicies.EffectivePolicy(_requestMsg, _clientLink.GetLink(), Property.DDNS_UPDATE);
                log.Info("Server configuration for ddns.update policy: " + policy);
                if ((policy == null) || policy.Contains("none"))
                {
                    log.Info("Server configuration for ddns.update policy is null or 'none'." + "  No DDNS updates performed.");
                    replyFqdnOption.SetNoUpdateBit(true);   // tell client that server did no updates
                    _replyMsg.PutDhcpOption(replyFqdnOption);
                    return;
                }

                if (clientFqdnOption.GetNoUpdateBit() && policy.Contains("honorNoUpdate"))
                {
                    log.Info("Client FQDN NoUpdate flag set.  Server configured to honor request." + "  No DDNS updates performed.");
                    replyFqdnOption.SetNoUpdateBit(true);   // tell client that server did no updates
                    _replyMsg.PutDhcpOption(replyFqdnOption);
                    //TODO: RFC 4704 Section 6.1
                    //		...the server SHOULD delete any RRs that it previously added
                    //		via DNS updates for the client.
                    return;
                }

                if (!clientFqdnOption.GetUpdateABit() && policy.Contains("honorNoA"))
                {
                    log.Info("Client FQDN NoA flag set.  Server configured to honor request." + "  No FORWARD DDNS updates performed.");
                    doForwardUpdate = false;
                }
                else
                {
                    replyFqdnOption.SetUpdateABit(true);    // server will do update
                    if (!clientFqdnOption.GetUpdateABit())
                    {
                        replyFqdnOption.SetOverrideBit(true);   // tell client that we overrode request flag
                    }
                }

                if (!String.IsNullOrEmpty(domain))
                {
                    log.Info("Server configuration for domain policy: " + domain);
                    // if there is a configured domain, then replace the domain provide by the client
                    int dot = fqdn.IndexOf('.');
                    if (dot > 0)
                    {
                        fqdn = fqdn.Substring(0, dot + 1) + domain;
                    }
                    else
                    {
                        fqdn = fqdn + "." + domain;
                    }
                    replyFqdnOption.SetDomainName(fqdn);
                }
                // since the client DID send option 81, return it in the reply
                _replyMsg.PutDhcpOption(replyFqdnOption);
            }
            else
            {
                // The client did not send an FQDN option, so we'll try to formulate the FQDN
                // from the hostname option combined with the DDNS_DOMAIN policy setting.
                // A replyFqdnOption is fabricated to be stored with the binding for use
                // with the release/expire binding processing to remove the DDNS entry.
                replyFqdnOption = new DhcpV4ClientFqdnOption();
                fqdn            = hostnameOption.GetString();
                if (!String.IsNullOrEmpty(domain))
                {
                    log.Info("Server configuration for domain policy: " + domain);
                    fqdn = fqdn + "." + domain;
                    // since the client did NOT send option 81, do not put
                    // the fabricated fqdnOption into the reply packet
                    // but set the option so that is can be used below
                    // when storing the fqdnOption to the database, so
                    // that it can be used if/when the lease expires
                    replyFqdnOption.SetDomainName(fqdn);
                    // server will do the A record update, so set the flag
                    // for the option stored in the database, so server will
                    // remove the A record when the lease expires
                    replyFqdnOption.SetUpdateABit(true);
                }
                else
                {
                    log.Error("No DDNS domain configured.  No DDNS udpates performed.");
                    replyFqdnOption.SetNoUpdateBit(true);   // tell client that server did no updates
                    _replyMsg.PutDhcpOption(replyFqdnOption);
                    return;
                }
            }

            if (sendUpdates)
            {
                foreach (Binding binding in _bindings)
                {
                    if (binding.GetState() == Binding.COMMITTED)
                    {
                        HashSet <BindingObject> bindingObjs = binding.GetBindingObjects();
                        if (bindingObjs != null)
                        {
                            foreach (var bindingObj in bindingObjs)
                            {
                                V4BindingAddress bindingAddr  = (V4BindingAddress)bindingObj;
                                DhcpConfigObject configObj    = bindingAddr.GetConfigObj();
                                DdnsCallback     ddnsComplete = new DhcpV4DdnsComplete(bindingAddr, replyFqdnOption);
                                DdnsUpdater      ddns         = new DdnsUpdater(_requestMsg, _clientLink.GetLink(), configObj, bindingAddr.GetIpAddress(), fqdn, _requestMsg.GetChAddr(), configObj.GetValidLifetime(), doForwardUpdate, false, ddnsComplete);
                                ddns.ProcessUpdates();
                            }
                        }
                    }
                }
            }
        }
Example #12
0
        /**
         * Perform the DDNS delete processing when a lease is released or expired.
         *
         * @param ia the IdentityAssoc of the client
         * @param iaAddr the released or expired IaAddress
         */
        protected override void DdnsDelete(IdentityAssoc ia, IaAddress iaAddr)
        {
            DhcpV6ClientFqdnOption clientFqdnOption = null;

            try
            {
                if ((ia != null) && (iaAddr != null))
                {
                    List <DhcpOption> opts = iaAddr.GetDhcpOptions();
                    if (opts != null)
                    {
                        foreach (DhcpOption opt in opts)
                        {
                            if (opt.GetCode() == DhcpConstants.V6OPTION_CLIENT_FQDN)
                            {
                                clientFqdnOption = new DhcpV6ClientFqdnOption();
                                //clientFqdnOption.Decode(ByteBuffer.Wrap(opt.GetValue()));
                                break;
                            }
                        }
                    }
                    if (clientFqdnOption != null)
                    {
                        string fqdn = clientFqdnOption.GetDomainName();
                        if (!String.IsNullOrEmpty(fqdn))
                        {
                            DhcpLink link = serverConfig.FindLinkForAddress(iaAddr.GetIpAddress());
                            if (link != null)
                            {
                                V6BindingAddress bindingAddr   = null;
                                StaticBinding    staticBinding =
                                    FindStaticBinding(link.GetLink(), ia.GetDuid(),
                                                      ia.GetIatype(), ia.GetIaid(), null);
                                if (staticBinding != null)
                                {
                                    bindingAddr =
                                        BuildV6StaticBindingFromIaAddr(iaAddr, staticBinding);
                                }
                                else
                                {
                                    bindingAddr =
                                        BuildV6BindingAddressFromIaAddr(iaAddr, link, null);    // safe to send null requestMsg
                                }
                                if (bindingAddr != null)
                                {
                                    DdnsCallback ddnsComplete =
                                        new DhcpV6DdnsComplete(bindingAddr, clientFqdnOption);

                                    DhcpConfigObject configObj = bindingAddr.GetConfigObj();

                                    DdnsUpdater ddns =
                                        new DdnsUpdater(link.GetLink(), configObj,
                                                        bindingAddr.GetIpAddress(), fqdn, ia.GetDuid(),
                                                        configObj.GetValidLifetime(),
                                                        clientFqdnOption.GetUpdateAaaaBit(), true,
                                                        ddnsComplete);

                                    ddns.ProcessUpdates();
                                }
                                else
                                {
                                    log.Error("Failed to find binding for address: " +
                                              iaAddr.GetIpAddress().ToString());
                                }
                            }
                            else
                            {
                                log.Error("Failed to find link for binding address: " +
                                          iaAddr.GetIpAddress().ToString());
                            }
                        }
                        else
                        {
                            log.Error("FQDN is null or empty.  No DDNS deletes performed.");
                        }
                    }
                    else
                    {
                        log.Warn("No Client FQDN option in current binding.  No DDNS deletes performed.");
                    }
                }
            }
            catch (Exception ex)
            {
                log.Error("Failed to perform DDNS delete");
            }
        }
        /// <summary>
        /// Get list of IP addresses for the given client IA request.
        /// </summary>
        /// <param name="clientLink">link for the client request message</param>
        /// <param name="duid">DUID of the client</param>
        /// <param name="iatype">IA type of the client request</param>
        /// <param name="iaid">IAID of the client request</param>
        /// <param name="requestAddrs">list of requested IP addresses, if any</param>
        /// <param name="requestMsg">client request message</param>
        /// <returns>list of IPAddress</returns>
        protected List <IPAddress> GetInetAddrs(DhcpLink clientLink, byte[] duid, byte iatype, long iaid, List <IPAddress> requestAddrs, DhcpMessage requestMsg, IPAddress clientV4IPAddress)
        {
            List <IPAddress> inetAddrs = new List <IPAddress>();

            if ((requestAddrs != null) && requestAddrs.Count > 0)
            {
                foreach (IPAddress reqAddr in requestAddrs)
                {
                    IPAddress addr = reqAddr;
                    if (!addr.Equals(DhcpConstants.ZEROADDR_V6))
                    {
                        BindingPool bp = FindBindingPool(clientLink.GetLink(), addr, requestMsg);
                        if (bp.IsFree(new BigInteger(addr.GetAddressBytes())) == false)
                        {
                            continue;
                        }
                        if (bp == null)
                        {
                            _log.Warn("No BindingPool found for requested client address: " + addr.ToString());
                            if (iatype == IdentityAssoc.PD_TYPE)
                            {
                                // TAHI tests want NoPrefixAvail in this case
                                _log.Warn("Requested prefix is not available, returning");
                                return(inetAddrs);
                            }
                            // if there is no pool for the requested address, then skip it
                            // because that address is either off-link or no longer valid
                            continue;
                        }
                        _log.Info("Searching existing bindings for requested IP=" + addr.ToString());
                        IdentityAssoc ia = null;
                        try
                        {
                            ia = iaMgr.FindIA(addr);
                            if (ia != null)
                            {
                                // the address is assigned to an IA, which we
                                // don't expect to be this IA, because we would
                                // have found it using findCurrentBinding...
                                // but, perhaps another thread just created it?
                                if (IsMyIa(duid, iatype, iaid, ia))
                                {
                                    _log.Warn("Requested IP=" + addr.ToString() + " is already held by THIS client " + IdentityAssoc.KeyToString(duid, iatype, iaid) + ".  Allowing this requested IP.");
                                }
                                else
                                {
                                    _log.Info("Requested IP=" + addr.ToString() + " is held by ANOTHER client " + IdentityAssoc.KeyToString(duid, iatype, iaid));
                                    // the address is held by another IA, so get a new one
                                    addr = GetNextFreeAddress(clientLink, requestMsg, clientV4IPAddress);
                                }
                            }
                            if (addr != null)
                            {
                                inetAddrs.Add(addr);
                            }
                        }
                        catch
                        {
                            _log.Error("Failure finding IA for address");
                        }
                    }
                }
            }

            if (inetAddrs == null || inetAddrs.Count == 0)
            {
                // the client did not request any valid addresses, so get the next one
                IPAddress inetAddr = GetNextFreeAddress(clientLink, requestMsg, clientV4IPAddress);
                if (inetAddr != null)
                {
                    inetAddrs.Add(inetAddr);
                }
            }
            return(inetAddrs);
        }