示例#1
0
/// Checks if a given client is supported
///
/// @param msg message sent by client
///
/// @return true if supported, false otherwise
bool TSrvCfgMgr::isClntSupported(SPtr<TSrvMsg> msg) {
    int iface=msg->getIface();
    SPtr<TIPv6Addr> clntAddr = msg->getAddr();

    SPtr<TOpt> opt = msg->getOption(OPTION_CLIENTID);
    SPtr<TDUID> duid;
    if (!opt) {
        // malformed message or anonymous inf-request
        duid = new TDUID("", 0); // zero-length DUID
    } else {
        SPtr<TOptDUID> clientId = (Ptr*) opt;
        duid = clientId->getDUID();
    }

    SPtr<TSrvCfgIface> ptrIface;
    firstIface();
    while((ptrIface=getIface())&&(ptrIface->getID()!=iface)) ;

    /** @todo: reject-client and accept-only does not work in stateless mode */
    if (this->stateless())
        return true;

    int classCnt = 0;
    if (ptrIface)
    {
        SPtr<TSrvCfgAddrClass> ptrClass;
        ptrIface->firstAddrClass();
        while(ptrClass=ptrIface->getAddrClass()) {
            if (ptrClass->clntSupported(duid,clntAddr))
                return true;
            classCnt++;
        }

        SPtr<TSrvCfgPD> pd;
        ptrIface->firstPD();
        while ( pd=ptrIface->getPD() ) {
            if (pd->clntSupported(duid, clntAddr, msg))
                return true;
            classCnt++;
        }
    }
    if (!classCnt && ptrIface) {
        Log(Warning) << "There are no address class defined on the " << ptrIface->getFullName()
                     << ". Maybe you are trying to configure clients on cascade relay interface? "
                     << "If that is so, please define separate class on this interface, too." << LogEnd;
    } else if (!classCnt) {
        Log(Warning) << "Interface not found."
                     << "Maybe you are trying to configure clients on cascade relay interface? "
                     << "If that is so, please define separate class on this interface, too." << LogEnd;
    }
    return false;
}
示例#2
0
/*
* Method checks whether client is supported and assigned addresses from any class
*/
bool TSrvCfgMgr::isClntSupported(SPtr<TDUID> duid, SPtr<TIPv6Addr> clntAddr, int iface, SPtr<TSrvMsg> msg)
{
   SPtr<TSrvCfgIface> ptrIface;
   firstIface();
   while((ptrIface=getIface())&&(ptrIface->getID()!=iface)) ;

   /** @todo: reject-client and accept-only does not work in stateless mode */
   if (this->stateless())
	return true;

   int classCnt = 0;
   if (ptrIface)
   {
       SPtr<TSrvCfgAddrClass> ptrClass;
       ptrIface->firstAddrClass();
       while(ptrClass=ptrIface->getAddrClass()) {
           if (ptrClass->clntSupported(duid,clntAddr,msg))
               return true;
	    classCnt++;
	}
   }
   if (!classCnt) {
	Log(Warning) << "There are no address class defined on the " << ptrIface->getFullName()
		     << ". Maybe you are trying to configure clients on cascade relay interface? "
		     << "If that is so, please define separate class on this interface, too." << LogEnd;
   }
   return false;
}
示例#3
0
/** 
 * returns how many addresses can be assigned to this client?
 * factors used:
 * - iface-max-lease
 * - clntSupported()
 * - class-max-lease in each class
 * - assignedCount in each class
 * 
 * @param clntDuid 
 * @param clntAddr 
 * @param iface 
 * 
 * @return return value <= clnt-max-lease <= iface-max-lease
 */
long TSrvCfgMgr::countAvailAddrs(SPtr<TDUID> clntDuid,
				 SPtr<TIPv6Addr> clntAddr,  int iface)
{
    /// @todo: long long long int (128bit) could come in handy
    double avail         = 0; // how many are available?
    double ifaceAssigned = 0; // how many are assigned on this iface?
    SPtr<TSrvCfgIface> ptrIface;
    ptrIface = this->getIfaceByID(iface);
    if (!ptrIface) {
	Log(Error) << "Interface " << iface << " does not exist in SrvCfgMgr." << LogEnd;
	return 0;
    }

    unsigned long ifaceMaxLease = ptrIface->getIfaceMaxLease();

    SPtr<TSrvCfgAddrClass> ptrClass;
    ptrIface->firstAddrClass();
    while (ptrClass = ptrIface->getAddrClass()) {
	if (!ptrClass->clntSupported(clntDuid,clntAddr))
	    continue;
	unsigned long classMaxLease;
	unsigned long classAssigned;
	double tmp;
	classMaxLease = ptrClass->getClassMaxLease();
	classAssigned = ptrClass->getAssignedCount();
	tmp = classMaxLease - classAssigned;
	ifaceAssigned += classAssigned;
	if (tmp>0)
	    avail += tmp;
    }

    if (avail > (ifaceMaxLease-ifaceAssigned))
	avail = ifaceMaxLease-ifaceAssigned;
    return (long)avail;
}
示例#4
0
/// this method finds a temp. address for this client, marks it as used and then
/// creates IAAADDR option containing this option.
///
/// @param clientMsg
///
/// @return IAADDR option with new temporary address (or NULL)
SPtr<TSrvOptIAAddress> TSrvOptTA::assignAddr(SPtr<TSrvMsg> clientMsg) {
    SPtr<TSrvCfgIface> ptrIface;
    ptrIface = SrvCfgMgr().getIfaceByID(this->Iface);
    if (!ptrIface) {
	Log(Error) << "Trying to find free address on non-existent interface (id=%d)\n"
		   << this->Iface << LogEnd;
	return SPtr<TSrvOptIAAddress>(); // NULL
    }

    SPtr<TSrvCfgTA> ta;
    ptrIface->firstTA();

    while ( ta = ptrIface->getTA())
    {
    	if (!ta->clntSupported(ClntDuid, ClntAddr, clientMsg ))
    		continue;
    	break;
    }

    if (!ta)
    {
        Log(Warning) << "Unable to find any suitable (allowed,non-full) TA for this client."
                     << LogEnd;
        return SPtr<TSrvOptIAAddress>(); // NULL
    }
    SPtr<TIPv6Addr> addr;
    int safety=0;

    while (safety < SERVER_MAX_TA_RANDOM_TRIES) {
	addr = ta->getRandomAddr();
	if (SrvAddrMgr().taAddrIsFree(addr)) {
	    if ((this->OrgMessage == REQUEST_MSG)) {
		Log(Debug) << "Temporary address " << addr->getPlain() << " granted." << LogEnd;
		SrvAddrMgr().addTAAddr(this->ClntDuid, this->ClntAddr, this->Iface,
				   IAID_, addr, ta->getPref(), ta->getValid());
		SrvCfgMgr().addTAAddr(this->Iface);
	    } else {
		Log(Debug) << "Temporary address " << addr->getPlain() << " generated (not granted)."
                           << LogEnd;
	    }
	    return new TSrvOptIAAddress(addr, ta->getPref(), ta->getValid(), this->Parent);

	}
	safety++;
    }
    Log(Error) << "Unable to randomly choose address after " << SERVER_MAX_TA_RANDOM_TRIES
               << " tries." << LogEnd;
    return SPtr<TSrvOptIAAddress>(); // NULL
}
示例#5
0
/**
 * @brief returns list of free prefixes for this client
 *
 * return free prefixes for a client. There are several ways that method may work:
 * 1 - client didn't provide any hints:
 *     => one prefix from each pool will be granted
 * 2 - client has provided hint and that is valid (supported and unused):
 *     => requested prefix will be granted
 * 3 - client has provided hint, which belongs to supported pool, but this prefix is used:
 *     => other prefix from that pool will be asigned
 * 4 - client has provided hint, but it is invalid (not beloninging to a supported pool,
 *     multicast or link-local):
 *     => see 1
 *
 * @param clientMsg message received from a client
 * @param cli_hint hint provided by client (or ::)
 *
 * @return - list of prefixes
 */
List(TIPv6Addr) TSrvOptIA_PD::getFreePrefixes(SPtr<TSrvMsg> clientMsg, SPtr<TIPv6Addr> cli_hint) {

    SPtr<TSrvCfgIface> ptrIface;
    SPtr<TIPv6Addr>    prefix;
    SPtr<TSrvCfgPD>    ptrPD;
    bool validHint = true;
    List(TIPv6Addr) lst;

    lst.clear();
    ptrIface = SrvCfgMgr().getIfaceByID(this->Iface);
    if (!ptrIface) {
      Log(Error) << "PD: Trying to find free prefix on non-existent interface (ifindex="
                 << this->Iface << ")." << LogEnd;
      return lst; // empty list
    }

    if (!ptrIface->supportPrefixDelegation()) {
      // this method should not be called anyway
      Log(Error) << "PD: Prefix delegation is not supported on the " << ptrIface->getFullName()
                 << "." << LogEnd;
      return lst; // empty list
    }

    ptrIface->firstPD();
    ptrPD = ptrIface->getPD();
    // should be ==, asigned>total should never happen
    if (ptrPD->getAssignedCount() >= ptrPD->getTotalCount()) {
      Log(Error) << "PD: Unable to grant any prefixes: Already asigned " << ptrPD->getAssignedCount()
                 << " out of " << ptrPD->getTotalCount() << "." << LogEnd;
      return lst; // empty list
    }

    // check if this prefix is ok

    // is it anyaddress (::)?
    SPtr<TIPv6Addr> anyaddr = new TIPv6Addr();
    if (*anyaddr==*cli_hint) {
        Log(Debug) << "PD: Client requested unspecified (" << *cli_hint
                   << ") prefix. Hint ignored." << LogEnd;
        validHint = false;
    }

    // is it multicast address (ff...)?
    if ((*(cli_hint->getAddr()))==0xff) {
        Log(Debug) << "PD: Client requested multicast (" << *cli_hint
                   << ") prefix. Hint ignored." << LogEnd;
        validHint = false;
    }

    // is it link-local address (fe80::...)?
    char linklocal[]={0xfe, 0x80};
    if (!memcmp(cli_hint->getAddr(),linklocal,2)) {
        Log(Debug) << "PD: Client requested link-local (" << *cli_hint
                   << ") prefix. Hint ignored." << LogEnd;
        validHint = false;
    }

    SPtr<TOptVendorData> remoteID;
    TSrvMsg * par = (TSrvMsg*)(Parent);
    if (par) {
        remoteID = par->getRemoteID();
    }

    if ( validHint ) {
        // hint is valid, try to use it
        ptrPD = SrvCfgMgr().getClassByPrefix(this->Iface, cli_hint);

        // if the PD allow the hint, based on DUID, Addr, and Msg from client
        if (ptrPD && ptrPD->clntSupported(ClntDuid, ClntAddr, clientMsg)) {

            // Let's make a copy of the hint (we may need to tweak the hint in a second)
            SPtr<TIPv6Addr> hint(new TIPv6Addr(cli_hint->getAddr()));

            // Now zero the remaining part
            hint->truncate(0, ptrPD->getPD_Length());
            
            // Is this hint reserved for someone else?
            if (!ptrIface->checkReservedPrefix(hint, ClntDuid, remoteID, ClntAddr))
            {
                // Nope, not reserved.

                // case 2: address belongs to supported class, and is free
                if ( SrvAddrMgr().prefixIsFree(hint) ) {
                    Log(Debug) << "PD: Requested prefix (" << *hint << ") is free, great!" << LogEnd;
                    this->PDLength = ptrPD->getPD_Length();
                    this->Prefered = ptrPD->getPrefered(this->Prefered);
                    this->Valid    = ptrPD->getValid(this->Valid);
                    T1_       = ptrPD->getT1(T1_);
                    T2_       = ptrPD->getT2(T2_);
                    lst.append(hint);
                    return lst;
                } else {

                    // case 3: hint is used, but we can assign another prefix from the same pool
                    do {
                        prefix=ptrPD->getRandomPrefix();
                    } while (!SrvAddrMgr().prefixIsFree(prefix));
                    lst.append(prefix);

                    this->PDLength = ptrPD->getPD_Length();
                    this->Prefered = ptrPD->getPrefered(this->Prefered);
                    this->Valid    = ptrPD->getValid(this->Valid);
                    T1_       = ptrPD->getT1(T1_);
                    T2_       = ptrPD->getT2(T2_);
                    return lst;
                } // if hint is used
            } // if this hint is reserved for someone?
        } // if client is supported at all
    } // if this is a valid hint

    // case 1: no hint provided, assign one prefix from each pool
    // case 4: provided hint does not belong to supported class or is useless (multicast,link-local, ::)
    ptrIface->firstPD();

    while ( ptrPD = ptrIface->getPD())
    {
        if (!ptrPD->clntSupported(ClntDuid, ClntAddr, clientMsg ))
                continue;
        break;
    }

    if (!ptrPD)
    {
        Log(Warning) << "Unable to find any PD for this client." << LogEnd;
        return lst;  // return empty list
    }

    int attempts = SERVER_MAX_PD_RANDOM_TRIES;
    while (attempts--) {
        List(TIPv6Addr) lst;
        lst = ptrPD->getRandomList();
        lst.first();
        bool allFree = true;
        while (prefix = lst.get()) {
            if (!SrvAddrMgr().prefixIsFree(prefix) || SrvCfgMgr().prefixReserved(prefix)) {
                allFree = false;
            }
        }
        if (allFree) {
            this->PDLength = ptrPD->getPD_Length();
            this->Prefered = ptrPD->getPrefered(this->Prefered);
            this->Valid    = ptrPD->getValid(this->Valid);
            T1_       = ptrPD->getT1(T1_);
            T2_       = ptrPD->getT2(T2_);
            return lst;
        }
    };

    // failed to find available prefixes after 100 attempts. Return empty list
    return List(TIPv6Addr)();
}