TClntMsgInfRequest::TClntMsgInfRequest(SPtr<TClntCfgIface> iface)
    :TClntMsg(iface->getID(), 0, INFORMATION_REQUEST_MSG) {

    IRT = INF_TIMEOUT;
    MRT = INF_MAX_RT;
    MRC = 0;
    MRD = 0;
    RT= 0 ;
    
    Iface=iface->getID();
    IsDone=false;

    if (!ClntCfgMgr().anonInfRequest()) {
        Options.push_back(new TOptDUID(OPTION_CLIENTID, ClntCfgMgr().getDUID(), this));
    } else {
        Log(Info) << "Sending anonymous INF-REQUEST (ClientID not included)." << LogEnd;
    }

    // Append the options we want to configure
    appendRequestedOptions();

    // If there is no ORO (or it is empty), skip the message.
    SPtr<TClntOptOptionRequest> oro = (Ptr*) getOption(OPTION_ORO);
    if (!oro || !oro->count()) {
        IsDone = true;
        return;
    }

    appendAuthenticationOption();
    appendElapsedOption();
    send();
}
bool TClntIfaceMgr::fqdnAdd(SPtr<TClntIfaceIface> iface, string fqdn)
{
    SPtr<TIPv6Addr> DNSAddr;
    SPtr<TIPv6Addr> addr;

    SPtr<TClntCfgIface> cfgIface;
    cfgIface = ClntCfgMgr().getIface(iface->getID());
    if (!cfgIface) {
        Log(Error) << "Unable to find interface with ifindex=" << iface->getID() << "." << LogEnd;
        return false;
    }

    // For the moment, we just take the first DNS entry.
    List(TIPv6Addr) DNSSrvLst = iface->getDNSServerLst();
    if (!DNSSrvLst.count()) {
        Log(Error) << "Unable to find DNS Server. FQDN add failed." << LogEnd;
        return false;
    }
    DNSSrvLst.first();
    DNSAddr = DNSSrvLst.get();

    // And the first IP address
    SPtr<TAddrIA> ptrAddrIA;
    ClntAddrMgr().firstIA();
    ptrAddrIA = ClntAddrMgr().getIA();

    if (ptrAddrIA->countAddr() > 0) {
        ptrAddrIA->firstAddr();
        addr = ptrAddrIA->getAddr()->get();

        Log(Notice) << "FQDN: About to perform DNS Update: DNS server=" << *DNSAddr
                    << ", IP=" << *addr << " and FQDN=" << fqdn << LogEnd;

        // remember DNS Address (used during address release)
        ptrAddrIA->setFQDNDnsServer(DNSAddr);

        TCfgMgr::DNSUpdateProtocol proto = ClntCfgMgr().getDDNSProtocol();
        DNSUpdate::DnsUpdateProtocol proto2 = DNSUpdate::DNSUPDATE_TCP;
        if (proto == TCfgMgr::DNSUPDATE_UDP)
            proto2 = DNSUpdate::DNSUPDATE_UDP;
        if (proto == TCfgMgr::DNSUPDATE_ANY)
            proto2 = DNSUpdate::DNSUPDATE_ANY;
        unsigned int timeout = ClntCfgMgr().getDDNSTimeout();

#ifndef MOD_CLNT_DISABLE_DNSUPDATE
        /* add AAAA record */
        DNSUpdate *act = new DNSUpdate(DNSAddr->getPlain(), "", fqdn, addr->getPlain(),
                                       DNSUPDATE_AAAA, proto2);
        int result = act->run(timeout);
        act->showResult(result);
        delete act;
#else
        Log(Error) << "This version is compiled without DNS Update support." << LogEnd;
        return false;
#endif
    }
    return true;
}
bool TClntIfaceMgr::doDuties() {
    SPtr<TClntIfaceIface> iface;
    SPtr<TClntCfgIface> cfgIface;

    this->firstIface();
    while (iface = (Ptr*)this->getIface()) {
              cfgIface = ClntCfgMgr().getIface(iface->getID());
              if (cfgIface) {
            // Log(Debug) << "FQDN State: " << cfgIface->getFQDNState() << " on " << iface->getFullName() << LogEnd;
            if (cfgIface->getFQDNState() == STATE_INPROCESS) {
                            // Here we check if all parameters are set, and do the DNS update if possible
                            List(TIPv6Addr) DNSSrvLst = iface->getDNSServerLst();
                            string fqdn = iface->getFQDN();
                            if (ClntAddrMgr().countIA() > 0 && DNSSrvLst.count() > 0 && fqdn.size() > 0) {

                                Log(Warning) << "Sleeping 3 seconds before performing DNS Update." << LogEnd;
                                /** @todo: sleep cannot be performed here. What if client has to perform other
                                   action during those 3 seconds? */
#ifdef WIN32
                            Sleep(3);
#else
                            sleep(3);
#endif
                            this->fqdnAdd(iface, fqdn);
                        }
                  }
              }
    }
    ClntAddrMgr().dump();
    this->dump();
    return true;
}
void TClntMsgInfRequest::answer(SPtr<TClntMsg> msg)
{

    copyAAASPI(msg);

    TClntMsg::answer(msg);

#if 0
    //which option have we requested from server
    SPtr<TClntOptOptionRequest> ptrORO;
    ptrORO = (Ptr*)getOption(OPTION_ORO);
    
    SPtr<TOpt> option;
    msg->firstOption();
    while(option = msg->getOption())
    {
        //if option did what it was supposed to do ???
	if (!option->doDuties()) {
	    // Log(Debug) << "Setting option " << option->getOptType() << " failed." << LogEnd;
	    continue;
	}
	if ( ptrORO && (ptrORO->isOption(option->getOptType())) )
	    ptrORO->delOption(option->getOptType());
	SPtr<TOpt> requestOpt;
	this->firstOption();
	while ( requestOpt = this->getOption()) 
	{
	    if (requestOpt->getOptType()==option->getOptType()) {
		delOption(requestOpt->getOptType());
		break;
	    }
	}//while
    }
    
    ptrORO->delOption(OPTION_INFORMATION_REFRESH_TIME);
    if (ptrORO && ptrORO->count())
    {
	if (ClntCfgMgr().insistMode()){ 
	    Log(Notice) << "Insist-mode enabled. Not all options were assigned (";
	    for (int i=0; i<ptrORO->count(); i++)
                Log(Cont) << ptrORO->getReqOpt(i) << " ";
	    Log(Cont) << "). Sending new INFORMATION-REQUEST." << LogEnd;
	    ClntTransMgr().sendInfRequest(Options,Iface);
	} else {
	    Log(Notice) << "Insist-mode disabled. Not all options were assigned (";
	    for (int i=0; i<ptrORO->count(); i++)
                Log(Cont) << ptrORO->getReqOpt(i) << " ";
	    Log(Cont) << "). They will remain unconfigured." << LogEnd;
	    IsDone = true;
	}
    } else {
        Log(Debug) << "All requested options were assigned." << LogEnd;
        IsDone=true;
    }
    return;

#endif
}
bool TClntIfaceMgr::fqdnDel(SPtr<TClntIfaceIface> iface, SPtr<TAddrIA> ia, string fqdn)
{
    SPtr<TIPv6Addr> dns = ia->getFQDNDnsServer();

    // let's do deleting update
    SPtr<TIPv6Addr> clntAddr;
    ia->firstAddr();
    SPtr<TAddrAddr> tmpAddr = ia->getAddr();
    if (!tmpAddr) {
        Log(Error) << "FQDN: Unable to delete FQDN: IA (IAID=" << ia->getIAID()
                   << ") does not have any addresses." << LogEnd;
        return false;
    }
    SPtr<TIPv6Addr> myAddr = tmpAddr->get();

    SPtr<TClntCfgIface> ptrIface = ClntCfgMgr().getIface(iface->getID());

    TCfgMgr::DNSUpdateProtocol proto = ClntCfgMgr().getDDNSProtocol();
    DNSUpdate::DnsUpdateProtocol proto2 = DNSUpdate::DNSUPDATE_TCP;
    if (proto == TCfgMgr::DNSUPDATE_UDP)
        proto2 = DNSUpdate::DNSUPDATE_UDP;
    if (proto == TCfgMgr::DNSUPDATE_ANY)
        proto2 = DNSUpdate::DNSUPDATE_ANY;
    unsigned int timeout = ClntCfgMgr().getDDNSTimeout();

    Log(Debug) << "FQDN: Cleaning up DNS AAAA record in server " << *dns << ", for IP=" << *myAddr
               << " and FQDN=" << fqdn << LogEnd;
#ifndef MOD_CLNT_DISABLE_DNSUPDATE
    DNSUpdate *act = new DNSUpdate(dns->getPlain(), "", fqdn, myAddr->getPlain(),
                                   DNSUPDATE_AAAA_CLEANUP, proto2);
    int result = act->run(timeout);
    act->showResult(result);
    delete act;

#else
    Log(Error) << "This Dibbler version is compiled without DNS Update support." << LogEnd;
#endif

    return false;
}
TClntMsgInfRequest::TClntMsgInfRequest(SPtr<TClntCfgIface> iface)
    :TClntMsg(iface->getID(), 0, INFORMATION_REQUEST_MSG) {

    IRT = INF_TIMEOUT;
    MRT = INF_MAX_RT;
    MRC = 0;
    MRD = 0;
    RT= 0 ;
    
    Iface=iface->getID();
    IsDone=false;

    if (!ClntCfgMgr().anonInfRequest()) {
        Options.push_back(new TOptDUID(OPTION_CLIENTID, ClntCfgMgr().getDUID(), this));
    } else {
        Log(Info) << "Sending anonymous INF-REQUEST (ClientID not included)." << LogEnd;
    }

    this->appendRequestedOptions();

    appendAuthenticationOption();
    appendElapsedOption();
    send();
}
bool TClntOptLifetime::doDuties()
{
    string reason = "trying to set Lifetime timer.";
    int ifindex = this->Parent->getIface();

    if (!DUID) {
        Log(Error) << "Unable to find proper DUID while " << reason << LogEnd;
        return false;
    }

    SPtr<TClntIfaceIface> iface = (Ptr*)ClntIfaceMgr().getIfaceByID(ifindex);
    if (!iface) {
        Log(Error) << "Unable to find interface ifindex=" << ifindex
            << reason << LogEnd;
        return false;
    }

    SPtr<TClntCfgIface> cfgIface = ClntCfgMgr().getIface(ifindex);
    return iface->setLifetime(DUID, Parent->getAddr(), Value);
}
bool TClntOptNTPServers::doDuties() {
    string reason = "trying to set NTP server(s).";
    int ifindex = this->Parent->getIface();

        if (!this->DUID) {
        Log(Error) << "Unable to find proper DUID while " << reason << LogEnd;
        return false;
    }

    SPtr<TClntIfaceIface> iface = (Ptr*)ClntIfaceMgr().getIfaceByID(ifindex);
    if (!iface) {
        Log(Error) << "Unable to find interface ifindex=" << ifindex
            << reason << LogEnd;
        return false;
    }

    SPtr<TClntCfgIface> cfgIface = ClntCfgMgr().getIface(ifindex);
    cfgIface->setNTPServerState(STATE_CONFIGURED);

    return iface->setNTPServerLst(DUID, Parent->getAddr(), AddrLst);
}
void TClntOptIA_PD::setState(EState state)
{
    SPtr<TClntCfgIface> cfgIface = ClntCfgMgr().getIface(this->Iface);

    SPtr<TClntCfgPD> cfgPD = cfgIface->getPD(getIAID());
    if (!cfgPD) {
	Log(Error) << "Unable to find PD with iaid=" << getIAID() << " on the "
		   << cfgIface->getFullName() << " interface (CfgMgr)." << LogEnd;
	return;
    }
    cfgPD->setState(state);

    SPtr<TAddrIA> addrPD = ClntAddrMgr().getPD(getIAID());
    if (!addrPD) {
	/* Log(Error) << "Unable to find PD with iaid=" << getIAID() << " on the "
	   << cfgIface->getFullName() << " interface (AddrMgr)." << LogEnd; */
	/* Don't complain about it. It is normal that IA is being deleted when there
	   are no more prefixes in it */
	return;
    }
    addrPD->setState(state);
}
bool TClntOptIA_PD::modifyPrefixes(TClntIfaceMgr::PrefixModifyMode mode)
{
    bool status = false;
    EState state = STATE_NOTCONFIGURED;
    SPtr<TClntOptIAPrefix> prefix;
    string action;
    switch(mode) {
      case TClntIfaceMgr::PREFIX_MODIFY_ADD:
        action = "addition";
        state = STATE_CONFIGURED;
        break;
      case TClntIfaceMgr::PREFIX_MODIFY_UPDATE:
        action = "update";
        state = STATE_CONFIGURED;
        break;
      case TClntIfaceMgr::PREFIX_MODIFY_DEL:
        action = "delete";
        state = STATE_NOTCONFIGURED;
        break;
    }
    
    if ( (mode==TClntIfaceMgr::PREFIX_MODIFY_ADD) || (mode==TClntIfaceMgr::PREFIX_MODIFY_UPDATE) ) {
      if ( (T1==0) && (T2==0) ) {
        firstPrefix();
        if (prefix = getPrefix()) {
          T1 = prefix->getPref()/2;
          T2 = (int)((prefix->getPref())*0.7);
          Log(Notice) << "Server set T1 and T2 to 0. Choosing default (50%, 70% * prefered-lifetime): T1=" << T1 
                      << ", T2=" << T2 << LogEnd;
        }
      }
    }

    this->firstPrefix();
    while (prefix = this->getPrefix() ) {
	switch (mode) {
    case TClntIfaceMgr::PREFIX_MODIFY_ADD:
	    ClntAddrMgr().addPrefix(this->DUID, this->Prefix, this->Iface, this->IAID, this->T1, this->T2,
                           prefix->getPrefix(), prefix->getPref(), prefix->getValid(), prefix->getPrefixLength(), false);
	    status = ClntIfaceMgr().addPrefix(this->Iface, prefix->getPrefix(), prefix->getPrefixLength(),
                                     prefix->getPref(), prefix->getValid());
        Log(Debug) << "RENEW will be sent (T1) after " << T1 << ", REBIND (T2) after " << T2 << " seconds." << LogEnd;
	    action = "addition";
	    break;
	case TClntIfaceMgr::PREFIX_MODIFY_UPDATE:
	    ClntAddrMgr().updatePrefix(this->DUID, this->Prefix, this->Iface, this->IAID, this->T1, this->T2,
				  prefix->getPrefix(), prefix->getPref(), prefix->getValid(), prefix->getPrefixLength(), false);
	    status = ClntIfaceMgr().updatePrefix(this->Iface, prefix->getPrefix(), prefix->getPrefixLength(),
					    prefix->getPref(), prefix->getValid());
        Log(Debug) << "RENEW will be sent (T1) after " << T1 << ", REBIND (T2) after " << T2 << " seconds." << LogEnd;
	    action = "update";
	    break;
	case TClntIfaceMgr::PREFIX_MODIFY_DEL:
	    ClntAddrMgr().delPrefix(ClntCfgMgr().getDUID(), this->IAID, prefix->getPrefix(), false);
	    status = ClntIfaceMgr().delPrefix(this->Iface, prefix->getPrefix(), prefix->getPrefixLength() );
	    action = "delete";
	    break;
	}
	
	if (!status) {
	    string tmp = error_message();
	    Log(Error) << "Prefix error encountered during prefix " << action << " operation: " << tmp << LogEnd;
            // Let's pretend it was configured and renew it
	    // setState(STATE_FAILED);
	    //return true;
	}
    }

    setState(state);
    return true;
}
/// @brief check if received message should be accepted.
///
/// The following conditions are checked:
/// - is server on the black-list?
/// - are all requested options present?
/// - is there requested IA option?
/// - is there requested TA option?
///
/// @param msg server's REPLY
///
/// @return true if REPLY is rejected
bool TClntMsgSolicit::shallRejectAnswer(SPtr<TClntMsg> msg)
{
    bool somethingAssigned = false;

    // this == solicit or request
    // msg  == reply
    SPtr<TOptDUID> srvDUID = (Ptr*) msg->getOption(OPTION_SERVERID);
    if (!srvDUID) {
        Log(Notice) << "No server identifier provided. Message ignored." << LogEnd;
        return true;
    }
    
    //is this server rejected?
    SPtr<TClntCfgIface> iface = ClntCfgMgr().getIface(this->Iface);
    if (!iface) {
        Log(Error) << "Unable to find iface=" << this->Iface << "." << LogEnd;
        return true;
    }
    if (iface->isServerRejected(msg->getAddr(), srvDUID->getDUID())) {
	Log(Notice) << "Server was rejected (duid=" << srvDUID->getDUID() << ")." << LogEnd;
        return true;
    }

    // have we asked for IA?
    bool iaOk = true;
    if (this->getOption(OPTION_IA_NA))
    {
        /// @todo Check if proper IAIDs are returned, also if all IA were answered (if requested
        ///       several IAs were requested)
        /// @todo Check all IA_NAs, not just first one
        SPtr<TClntOptIA_NA> ia = (Ptr*)msg->getOption(OPTION_IA_NA);
        if (!ia)  {
            Log(Notice) << "IA_NA option requested, but not present in this message. Ignored." << LogEnd;
            iaOk = false;
        } else {
            if (!ia->getOption(OPTION_IAADDR)) {
                Log(Notice) << "IA_NA option returned, but without any addresses. Ignored." << LogEnd;
                iaOk = false;
            }
            SPtr<TClntOptStatusCode> st = (Ptr*)ia->getOption(OPTION_STATUS_CODE);
            if (st && st->getCode()!= STATUSCODE_SUCCESS) {
                Log(Notice) << "IA_NA has status code!=SUCCESS: " << st->getCode()
                            << "(" << st->getText() << "). Ignored." << LogEnd;
                iaOk = false;
            }
        }
        if (iaOk)
            somethingAssigned = true;
    }

    // have we asked for TA?
    bool taOk = true;
    if (this->getOption(OPTION_IA_TA)) {
        SPtr<TClntOptTA> ta = (Ptr*)msg->getOption(OPTION_IA_TA);
        if (!ta) {
            Log(Notice) << "TA option requested, but not present in this message. Ignored." << LogEnd;
            taOk = false;
        } else {
            if (!ta->getOption(OPTION_IAADDR)) {
                Log(Notice) << "TA option received, but without IAADDR" << LogEnd;
                taOk = false;
            }

            SPtr<TClntOptStatusCode> st = (Ptr*)ta->getOption(OPTION_STATUS_CODE);
            if (st && st->getCode()!= STATUSCODE_SUCCESS) {
                Log(Notice) << "IA_TA has status code!=SUCCESS: " << st->getCode()
                            << "(" << st->getText() << "). Ignored." << LogEnd;
                taOk = false;
            }
        }
        if (taOk)
            somethingAssigned = true;
    }

    // have we asked for PD?
    bool pdOk = true;
    if (getOption(OPTION_IA_PD)) {
        SPtr<TClntOptIA_PD> pd = (Ptr*) msg->getOption(OPTION_IA_PD);
        if (!pd) {
            Log(Notice) << "PD option requested, but not returned in this message. Ignored." << LogEnd;
            pdOk = false;
        } else {

	    if (!pd->getOption(OPTION_IAPREFIX)) {
		Log(Notice) << "Received PD without any prefixes." << LogEnd;
		pdOk = false;
	    }

            /// @todo: We should check all iaprefix instances, not just one.
            /// We should accept the PD if there's at least one valid prefix.
            if (!pd->getOption(OPTION_IAPREFIX)->isValid()) {
                Log(Warning) << "IA_Prefix option is not valid." << LogEnd;
                pdOk = false;
            }

	    SPtr<TClntOptStatusCode> st = (Ptr*)pd->getOption(OPTION_STATUS_CODE);
	    if (st && st->getCode()!= STATUSCODE_SUCCESS) {
		Log(Notice) << "IA_NA has status code!=SUCCESS: " << st->getCode()
			    << "(" << st->getText() << "). Ignored." << LogEnd;
		pdOk = false;
	    }
        }
        if (pdOk)
            somethingAssigned = true;
    }

    if (!somethingAssigned)
        return true; // this advertise does not offers us anything

    if (!ClntCfgMgr().insistMode())
        return false; // accept this advertise

    // insist-mode enabled. We MUST get everything we wanted or we reject this answer
    if (iaOk && taOk && pdOk)
        return false;
    else
        return true;
}
bool TClntOptIA_NA::doDuties() {

    // find this IA in addrMgr...
    SPtr<TAddrIA> ptrIA=ClntAddrMgr().getIA(this->getIAID());
    if (!ptrIA) {
        // unknown IAID, ignore it
        Log(Warning) << "Received message contains unknown IA (IAID="
                     << this->getIAID() << "). We didn't order it. Weird... ignoring it." << LogEnd;
        return true;
    }

    // IAID found, set up new received options.
    SPtr<TAddrAddr> ptrAddrAddr;
    SPtr<TOptIAAddress> ptrOptAddr;

    SPtr<TIfaceIface> ptrIface;
    ptrIface = ClntIfaceMgr().getIfaceByID(Iface_);
    if (!ptrIface)
    {
        Log(Error) << "Interface with ifindex=" << Iface_ << " not found." << LogEnd;
        return true;
    }

    // for each address in IA option...
    this->firstAddr();
    while (ptrOptAddr = this->getAddr() ) {
        ptrAddrAddr = ptrIA->getAddr( ptrOptAddr->getAddr() );

        // no such address in DB ??
        if (!ptrAddrAddr) {
            if (ptrOptAddr->getValid()) {

                int prefixLen = ptrIface->getPrefixLength();
                if (ptrOptAddr->getOption(OPTION_ADDRPARAMS)) {
                    Log(Debug) << "Experimental addr-params found." << LogEnd;
                    SPtr<TOptAddrParams> optAddrParams =
                        SPtr_cast<TOptAddrParams>(ptrOptAddr->getOption(OPTION_ADDRPARAMS));
                    prefixLen = optAddrParams->getPrefix();
                }

                // add this address in addrDB...
                ptrIA->addAddr(ptrOptAddr->getAddr(), ptrOptAddr->getPref(),
                               ptrOptAddr->getValid(), prefixLen);
                ptrIA->setDUID(this->DUID);

                // ... and in IfaceMgr -
                ptrIface->addAddr(ptrOptAddr->getAddr(), ptrOptAddr->getPref(),
                                  ptrOptAddr->getValid(), prefixLen);
            }
            else {
                Log(Warning) << "Server send new addr with valid lifetime 0." << LogEnd;
            }
        } else {
            // we have this addr in DB
            if ( ptrOptAddr->getValid() == 0 ) {
                // valid=0, release this address
                // delete address from addrDB
                ptrIA->delAddr(ptrOptAddr->getAddr());
                // delete address from IfaceMgr
                ptrIface->delAddr(ptrOptAddr->getAddr(), ptrIface->getPrefixLength());
                break; // analyze next option OPTION_IA_NA
            }

            // set up new options in IfaceMgr
            SPtr<TIfaceIface> ptrIface = ClntIfaceMgr().getIfaceByID(Iface_);
            if (ptrIface)
                ptrIface->updateAddr(ptrOptAddr->getAddr(),
                        ptrOptAddr->getPref(),
                        ptrOptAddr->getValid());
            // set up new options in addrDB
            ptrAddrAddr->setPref(ptrOptAddr->getPref());
            ptrAddrAddr->setValid(ptrOptAddr->getValid());
            ptrAddrAddr->setTimestamp();
        }
    }
    SPtr<TClntCfgIA> ptrCfgIA;
    ptrCfgIA=ClntCfgMgr().getIA(ptrIA->getIAID());

    if (getT1() && getT2()) {
        ptrIA->setT1( this->getT1() );
        ptrIA->setT2( this->getT2() );
        Log(Debug) << "RENEW(IA_NA) will be sent (T1) after " << ptrIA->getT1()
                   << ", REBIND (T2) after " << ptrIA->getT2() << " seconds." << LogEnd;
    } else {
        this->firstAddr();
        ptrOptAddr = this->getAddr();
        if (ptrOptAddr) {
            ptrIA->setT1( ptrOptAddr->getPref()/2);
            ptrIA->setT2( (int)((ptrOptAddr->getPref())*0.7) );
            Log(Notice) << "Server set T1 and T2 to 0. Choosing default (50%, "
                        << "70% * prefered-lifetime): T1=" << ptrIA->getT1()
                        << ", T2=" << ptrIA->getT2() << LogEnd;
        }
    }

    ptrIA->setTimestamp();
    ptrIA->setState(STATE_CONFIGURED);
    ptrCfgIA->setState(STATE_CONFIGURED);
    return true;
}
Beispiel #13
0
 */bool TClntOptTA::doDuties()
{
    // find this TA in addrMgr...
    SPtr<TAddrIA> ta = ClntAddrMgr().getTA(this->getIAID());

    if (!ta) {
	Log(Debug) << "Creating TA (iaid=" << this->getIAID() << ") in the addrDB." << LogEnd;
        ta = new TAddrIA(this->Iface, TAddrIA::TYPE_TA, 0 /*if unicast, then this->Addr*/, 
		         this->DUID, DHCPV6_INFINITY, 
		         DHCPV6_INFINITY, this->getIAID());
        ClntAddrMgr().addTA(ta);
    }

    // IAID found, set up new received options.
    SPtr<TAddrAddr> addr;
    SPtr<TClntOptIAAddress> optAddr;

    SPtr<TIfaceIface> ptrIface;
    ptrIface = ClntIfaceMgr().getIfaceByID(this->Iface);
    if (!ptrIface) 
    {
	Log(Error) << "Interface " << this->Iface << " not found." << LogEnd;
	return true;
    }

    // for each address in IA option...
    this->firstAddr();
    while (optAddr = this->getAddr() ) {
        addr = ta->getAddr( optAddr->getAddr() );
        
        if (!addr) { // - no such address in DB -
            if (!optAddr->getValid()) {
                Log(Warning) << "Server send new addr with valid=0." << LogEnd;
		continue;
	    }
	    // add this address in addrDB...
	    ta->addAddr(optAddr->getAddr(), optAddr->getPref(), optAddr->getValid());
	    ta->setDUID(this->DUID);
	    // ... and in IfaceMgr - 
	    ptrIface->addAddr(optAddr->getAddr(), optAddr->getPref(), optAddr->getValid(), ptrIface->getPrefixLength());
	    Log(Notice) << "Temp. address " << *optAddr->getAddr() << " has been added to "
			<< ptrIface->getName() << "/" << ptrIface->getID() 
			<< " interface." << LogEnd;

        } else { // - we have this addr in DB -

            if ( optAddr->getValid() == 0 ) {
                // valid=0, release this address and delete address from addrDB
                ta->delAddr(optAddr->getAddr());
                // delete address from IfaceMgr
                ptrIface->delAddr(optAddr->getAddr(), ptrIface->getPrefixLength());
                continue; // analyze next option OPTION_IA
            }

            // set up new options in IfaceMgr
	    ptrIface->updateAddr(optAddr->getAddr(), optAddr->getPref(), optAddr->getValid());
            // set up new options in addrDB
            addr->setPref(optAddr->getPref());
            addr->setValid(optAddr->getValid());
            addr->setTimestamp();
        }
    }

    // mark this TA as configured
    SPtr<TClntCfgTA> cfgTA;
    SPtr<TClntCfgIface> cfgIface;
    if (! (cfgIface = ClntCfgMgr().getIface(this->Iface)) ) {
        Log(Error) << "Unable to find TA class in the CfgMgr, on the " << this->Iface << " interface." << LogEnd;
        return true;
    }
    cfgIface->firstTA();
    cfgTA = cfgIface->getTA();
    cfgTA->setState(STATE_CONFIGURED);

    ta->setState(STATE_CONFIGURED);
    return true;
} 
SPtr<TClntMsg> TClntIfaceMgr::select(unsigned int timeout)
{
    int bufsize=4096;
    static char buf[4096];
    SPtr<TIPv6Addr> peer(new TIPv6Addr());
    int sockid;
    int msgtype;
    int ifaceid;

    sockid = TIfaceMgr::select(timeout, buf, bufsize, peer);

    if (sockid>0) {
        if (bufsize<4) {
            if (buf[0]!=CONTROL_MSG) {
                Log(Warning) << "Received message is too short (" << bufsize
                             << ") bytes." << LogEnd;
            } else {
                Log(Warning) << "Control message received." << LogEnd;
            }
            return 0; // NULL
        }
        msgtype = buf[0];
        SPtr<TClntMsg> ptr;
        SPtr<TIfaceIface> ptrIface;
        ptrIface = this->getIfaceBySocket(sockid);
        ifaceid = ptrIface->getID();
        Log(Debug) << "Received " << bufsize << " bytes on interface " << ptrIface->getName() << "/"
                   << ptrIface->getID() << " (socket=" << sockid << ", addr=" << *peer << "."
                   << ")." << LogEnd;

        switch (msgtype) {
        case ADVERTISE_MSG:
            ptr = new TClntMsgAdvertise(ifaceid,peer,buf,bufsize);
#ifndef MOD_DISABLE_AUTH
            if (!ptr->validateAuthInfo(buf, bufsize, ClntCfgMgr().getAuthAcceptMethods())) {
                    Log(Error) << "Message dropped, authentication validation failed." << LogEnd;
                    return 0;
            }
#endif
            return ptr;
        case SOLICIT_MSG:
        case REQUEST_MSG:
        case CONFIRM_MSG:
        case RENEW_MSG:
        case REBIND_MSG:
        case RELEASE_MSG:
        case DECLINE_MSG:
        case INFORMATION_REQUEST_MSG:
            Log(Warning) << "Illegal message type " << msgtype << " received." << LogEnd;
            return 0; // NULL
        case REPLY_MSG:
            ptr = new TClntMsgReply(ifaceid, peer, buf, bufsize);
#ifndef MOD_DISABLE_AUTH
            if (!ptr->validateAuthInfo(buf, bufsize, ClntCfgMgr().getAuthAcceptMethods())) {
                    Log(Error) << "Message dropped, authentication validation failed." << LogEnd;
                    return 0;
            }
#endif
            return ptr;

        case RECONFIGURE_MSG:
            Log(Warning) << "Reconfigure Message is currently not supported." << LogEnd;
            return 0; // NULL
        case RELAY_FORW_MSG: // those two msgs should not be visible for client
        case RELAY_REPL_MSG:
        default:
            Log(Warning) << "Message type " << msgtype << " is not supposed to "
                         << "be received by client. Check your relay/server configuration." << LogEnd;
            return 0;
        }
    } else {
        return 0;
    }
}
bool TClntIfaceMgr::modifyPrefix(int iface, SPtr<TIPv6Addr> prefix, int prefixLen,
                                 unsigned int pref, unsigned int valid,
                                 PrefixModifyMode mode)
{
    SPtr<TClntIfaceIface> ptrIface = (Ptr*)getIfaceByID(iface);
    if (!ptrIface) {
        Log(Error) << "Unable to find interface with ifindex=" << iface
                   << ", prefix add/modify operation failed." << LogEnd;
        return false;
    }

    string action;
    int conf = 0; // number of successfully configured prefixes
    int status = -1;

    switch (mode) {
    case PREFIX_MODIFY_ADD:
            action = "Adding";
            break;
    case PREFIX_MODIFY_UPDATE:
            action = "Updating";
            break;
    case PREFIX_MODIFY_DEL:
            action = "Deleting";
            break;
    }

    // option: split this prefix and add it to all interfaces
    Log(Notice) << "PD: " << action << " prefix " << prefix->getPlain() << "/" << (int)prefixLen
                << " to all interfaces (prefix will be split to /"
                << int(prefixLen+8) << " prefixes if necessary)." << LogEnd;

    if (prefixLen>120) {
        Log(Error) << "PD: Unable to perform prefix operation: prefix /" << prefixLen
                   << " can't be split. At least /120 prefix is required." << LogEnd;
        return false;
    }

    // get a list of interfaces that we will assign prefixes to
    TIfaceIfaceLst ifaceLst;
    vector<string> ifaceNames = ClntCfgMgr().getDownlinkPrefixIfaces();
    for (vector<string>::const_iterator name = ifaceNames.begin(); name != ifaceNames.end(); ++name) {
        SPtr<TIfaceIface> x = getIfaceByName(*name);
        if (x)
            ifaceLst.push_back(x);
        else
            Log(Warning) << "Interface " << *name << " specified in downlink-prefix-ifaces is missing." << LogEnd;
    }

    if (ifaceLst.size() == 0) {
        SPtr<TIfaceIface> x;
        firstIface();
        while ( x = (Ptr*)getIface() ) {
            if (x->getID() == ptrIface->getID()) {
                Log(Debug) << "PD: Interface " << x->getFullName()
                           << " is the interface, where prefix has been obtained, skipping." << LogEnd;
                continue;
            }

            // for each interface present in the system...
            if (!x->flagUp()) {
                Log(Debug) << "PD: Interface " << x->getFullName() << " is down, ignoring." << LogEnd;
            continue;
            }
            if (!x->flagRunning()) {
                Log(Debug) << "PD: Interface " << x->getFullName()
                           << " has flag RUNNING not set, ignoring." << LogEnd;
                continue;
            }
            if (!x->flagMulticast()) {
                Log(Debug) << "PD: Interface " << x->getFullName()
                           << " is not multicast capable, ignoring." << LogEnd;
                continue;
            }
            if ( !(x->getMacLen() > 5) ) {
                Log(Debug) << "PD: Interface " << x->getFullName()
                           << " has MAC address length " << x->getMacLen()
                           << " (6 or more required), ignoring." << LogEnd;
                continue;
            }
            x->firstLLAddress();
            if (!x->getLLAddress()) {
                Log(Debug) << "PD: Interface " << x->getFullName()
                           << " has no link-local address, ignoring. (Disconnected? Not associated? No-link?)" << LogEnd;
                continue;
            }

            ifaceLst.push_back(x);
        }
    }

    Log(Info) << "PD: Using " << ifaceLst.size() << " suitable interface(s):";
    TIfaceIfaceLst::const_iterator i;
    for (TIfaceIfaceLst::const_iterator i=ifaceLst.begin(); i!=ifaceLst.end(); ++i) {
        Log(Cont) << (*i)->getName() << " ";
    }
    Log(Cont) << LogEnd;

    if (ifaceLst.size() == 0) {
        Log(Warning) << "Suitable interfaces not found. Delegated prefix not split." << LogEnd;
        return true;
    }

    for (TIfaceIfaceLst::const_iterator i=ifaceLst.begin(); i!=ifaceLst.end(); ++i) {

        char buf[16];
        int subprefixLen;
        memmove(buf, prefix->getAddr(), 16);

        if (ifaceLst.size() == 1) {
            // just one interface - use delegated prefix as is
            subprefixLen = prefixLen;
        } else if (ifaceLst.size()<256) {
            subprefixLen = prefixLen + 8;
            int offset = prefixLen/8;
            if (prefixLen%8 == 0) {
                // that's easy, just put ID in the next octet
                buf[offset] = (*i)->getID();
            } else {
                // here's fun
                uint16_t existing = readUint16(buf+offset);
                uint16_t bitmask = 0xff00;
                uint16_t infixmask = ((uint8_t)(*i)->getID()) << 8;
                bitmask = bitmask >> (prefixLen%8);
                infixmask = infixmask >> (prefixLen%8);

                // clear out if there is anything there, i.e. server assigned prefix
                // with garbage in host section
                existing = existing & (~bitmask);
                existing = existing | (bitmask & infixmask);
                writeUint16(buf+offset, existing);
            }

        } else {
Beispiel #16
0
  :TClntMsg(iface, addr, RELEASE_MSG)
{
    SPtr<TDUID> srvDUID;
    
    IRT=REL_TIMEOUT;
    MRT=0;
    MRC=REL_MAX_RC;
    MRD=0;
    RT=0;

    // obtain IA, TA or PD, so server DUID can be obtained
    SPtr<TAddrIA> x = 0;
    if (iaLst.count()) {
        iaLst.first();
        x=iaLst.get();
    }
    if (!x)
        x = ta;
    if (!x) {
        pdLst.first();
        x = pdLst.get();
    }
    if (!x) {
        Log(Error) << "Unable to send RELEASE. No IA, TA or PD provided." << LogEnd;
        this->IsDone = true;
        return;
    }
    if (!x->getDUID()) {
        Log(Error) << "Unable to send RELEASE. Unable to find DUID. " << LogEnd;
        this->IsDone = true;
        return;
    }
    srvDUID = x->getDUID();

    Options.push_back(new TOptDUID(OPTION_SERVERID, srvDUID,this));
    Options.push_back(new TOptDUID(OPTION_CLIENTID, ClntCfgMgr().getDUID(),this));

#if 0
    if (ClntCfgMgr().getNotifyScripts()) {
	// release workaround (add removed IAs)
        /// @todo: WTF? Why are those IAs removed?
        iaLst.first();
        SPtr<TAddrIA> ia;
	while (ia = iaLst.get()) 
	{
	    ClntAddrMgr().addIA(ia);
	}
	
	
	iaLst.first();
	while (ia = iaLst.get())
	{
	    ClntAddrMgr().delIA(ia->getIAID());
	}
    }
#endif

    // --- RELEASE IA ---
    iaLst.first();
    while(x=iaLst.get()) {
        Options.push_back(new TClntOptIA_NA(x,this));
        SPtr<TAddrAddr> ptrAddr;
        SPtr<TClntIfaceIface> ptrIface;
        ptrIface = (Ptr*)ClntIfaceMgr().getIfaceByID(x->getIface());
        x->firstAddr();
        while (ptrAddr = x->getAddr()) {
            ptrIface->delAddr(ptrAddr->get(), ptrAddr->getPrefix());
        }

	// --- DNS Update ---
	SPtr<TIPv6Addr> dns = x->getFQDNDnsServer();
	if (dns) {
	    string fqdn = ptrIface->getFQDN();
	    ClntIfaceMgr().fqdnDel(ptrIface, x, fqdn);
	}
	// --- DNS Update ---
    }
    
    // --- RELEASE TA ---
    if (ta)
	Options.push_back(new TClntOptTA(ta, this));

    // --- RELEASE PD ---

    SPtr<TAddrIA> pd = 0;
    
    pdLst.first();
    while(pd=pdLst.get()) {
        SPtr<TClntOptIA_PD> pdOpt = new TClntOptIA_PD(pd,this);
        Options.push_back( (Ptr*)pdOpt );
        pdOpt->setContext(srvDUID, addr, this);
        pdOpt->delPrefixes();

        ClntAddrMgr().delPD(pd->getIAID() );
    }

    appendElapsedOption();
    appendAuthenticationOption();

    IsDone = false;
    send();
}
bool TClntMsgReply::check() {
    bool anonInfReq = ClntCfgMgr().anonInfRequest();
    return TClntMsg::check(!anonInfReq /* clientID mandatory */, true /* serverID mandatory */ );
}