otError ThreadNetif::Down(void) { VerifyOrExit(mIsUp); #if OPENTHREAD_ENABLE_DTLS mDtls.Stop(); #endif #if OPENTHREAD_ENABLE_DNS_CLIENT mDnsClient.Stop(); #endif #if OPENTHREAD_ENABLE_SNTP_CLIENT mSntpClient.Stop(); #endif mCoap.Stop(); mMleRouter.Disable(); RemoveAllExternalUnicastAddresses(); UnsubscribeAllExternalMulticastAddresses(); UnsubscribeAllRoutersMulticast(); UnsubscribeAllNodesMulticast(); mIsUp = false; GetIp6().RemoveNetif(*this); mMeshForwarder.Stop(); #if OPENTHREAD_ENABLE_CHANNEL_MONITOR GetInstance().GetChannelMonitor().Stop(); #endif GetNotifier().Signal(OT_CHANGED_THREAD_NETIF_STATE); exit: return OT_ERROR_NONE; }
otError Netif::SubscribeAllRoutersMulticast(void) { otError error = OT_ERROR_NONE; if (mMulticastAddresses == &kLinkLocalAllNodesMulticastAddress) { mMulticastAddresses = static_cast<NetifMulticastAddress *>( const_cast<otNetifMulticastAddress *>(&kLinkLocalAllRoutersMulticastAddress)); } else { for (NetifMulticastAddress *cur = mMulticastAddresses; cur; cur = cur->GetNext()) { if (cur == &kLinkLocalAllRoutersMulticastAddress) { ExitNow(error = OT_ERROR_ALREADY); } if (cur->mNext == &kLinkLocalAllNodesMulticastAddress) { cur->mNext = &kLinkLocalAllRoutersMulticastAddress; break; } } } GetNotifier().SetFlags(OT_CHANGED_IP6_MULTICAST_SUBSRCRIBED); exit: return error; }
otError Netif::UnsubscribeMulticast(const NetifMulticastAddress &aAddress) { otError error = OT_ERROR_NONE; if (mMulticastAddresses == &aAddress) { mMulticastAddresses = mMulticastAddresses->GetNext(); ExitNow(); } else if (mMulticastAddresses != NULL) { for (NetifMulticastAddress *cur = mMulticastAddresses; cur->GetNext(); cur = cur->GetNext()) { if (cur->mNext == &aAddress) { cur->mNext = aAddress.mNext; ExitNow(); } } } ExitNow(error = OT_ERROR_NOT_FOUND); exit: if (error != OT_ERROR_NOT_FOUND) { GetNotifier().SetFlags(OT_CHANGED_IP6_MULTICAST_UNSUBSRCRIBED); } return error; }
otError Netif::SubscribeExternalMulticast(const Address &aAddress) { otError error = OT_ERROR_NONE; NetifMulticastAddress *entry; size_t num = sizeof(mExtMulticastAddresses) / sizeof(mExtMulticastAddresses[0]); if (IsMulticastSubscribed(aAddress)) { ExitNow(error = OT_ERROR_ALREADY); } // Find an available entry in the `mExtMulticastAddresses` array. for (entry = &mExtMulticastAddresses[0]; num > 0; num--, entry++) { // In an unused/available entry, `mNext` points back to the entry itself. if (entry->mNext == entry) { break; } } VerifyOrExit(num > 0, error = OT_ERROR_NO_BUFS); // Copy the address into the available entry and add it to linked-list. entry->mAddress = aAddress; entry->mNext = mMulticastAddresses; mMulticastAddresses = entry; GetNotifier().SetFlags(OT_CHANGED_IP6_MULTICAST_SUBSRCRIBED); exit: return error; }
otError Netif::RemoveUnicastAddress(const NetifUnicastAddress &aAddress) { otError error = OT_ERROR_NONE; if (mUnicastAddresses == &aAddress) { mUnicastAddresses = mUnicastAddresses->GetNext(); ExitNow(); } else if (mUnicastAddresses != NULL) { for (NetifUnicastAddress *cur = mUnicastAddresses; cur->GetNext(); cur = cur->GetNext()) { if (cur->mNext == &aAddress) { cur->mNext = aAddress.mNext; ExitNow(); } } } ExitNow(error = OT_ERROR_NOT_FOUND); exit: if (error != OT_ERROR_NOT_FOUND) { GetNotifier().SetFlags(aAddress.mRloc ? OT_CHANGED_THREAD_RLOC_REMOVED : OT_CHANGED_IP6_ADDRESS_REMOVED); } return error; }
otError Netif::UnsubscribeAllRoutersMulticast(void) { otError error = OT_ERROR_NONE; if (mMulticastAddresses == &kLinkLocalAllRoutersMulticastAddress) { mMulticastAddresses = static_cast<NetifMulticastAddress *>( const_cast<otNetifMulticastAddress *>(&kLinkLocalAllNodesMulticastAddress)); ExitNow(); } for (NetifMulticastAddress *cur = mMulticastAddresses; cur; cur = cur->GetNext()) { if (cur->mNext == &kLinkLocalAllRoutersMulticastAddress) { cur->mNext = &kLinkLocalAllNodesMulticastAddress; ExitNow(); } } error = OT_ERROR_NOT_FOUND; exit: if (error != OT_ERROR_NOT_FOUND) { GetNotifier().SetFlags(OT_CHANGED_IP6_MULTICAST_UNSUBSRCRIBED); } return error; }
otError ThreadNetif::Up(void) { VerifyOrExit(!mIsUp); // Enable the MAC just in case it was disabled while the Interface was down. mMac.SetEnabled(true); #if OPENTHREAD_ENABLE_CHANNEL_MONITOR GetInstance().GetChannelMonitor().Start(); #endif mMeshForwarder.Start(); GetIp6().AddNetif(*this); mIsUp = true; SubscribeAllNodesMulticast(); mMleRouter.Enable(); mCoap.Start(kCoapUdpPort); #if OPENTHREAD_ENABLE_DNS_CLIENT mDnsClient.Start(); #endif #if OPENTHREAD_ENABLE_SNTP_CLIENT mSntpClient.Start(); #endif GetNotifier().Signal(OT_CHANGED_THREAD_NETIF_STATE); exit: return OT_ERROR_NONE; }
otError Joiner::Start(const char * aPSKd, const char * aProvisioningUrl, const char * aVendorName, const char * aVendorModel, const char * aVendorSwVersion, const char * aVendorData, otJoinerCallback aCallback, void * aContext) { ThreadNetif & netif = GetNetif(); otError error; Mac::ExtAddress joinerId; Crc16 ccitt(Crc16::kCcitt); Crc16 ansi(Crc16::kAnsi); VerifyOrExit(mState == OT_JOINER_STATE_IDLE, error = OT_ERROR_BUSY); GetNotifier().Signal(OT_CHANGED_JOINER_STATE); // use extended address based on factory-assigned IEEE EUI-64 GetJoinerId(joinerId); netif.GetMac().SetExtAddress(joinerId); netif.GetMle().UpdateLinkLocalAddress(); for (size_t i = 0; i < sizeof(joinerId); i++) { ccitt.Update(joinerId.m8[i]); ansi.Update(joinerId.m8[i]); } mCcitt = ccitt.Get(); mAnsi = ansi.Get(); error = netif.GetCoapSecure().Start(OPENTHREAD_CONFIG_JOINER_UDP_PORT); SuccessOrExit(error); error = netif.GetCoapSecure().SetPsk(reinterpret_cast<const uint8_t *>(aPSKd), static_cast<uint8_t>(strlen(aPSKd))); SuccessOrExit(error); error = netif.GetCoapSecure().GetDtls().mProvisioningUrl.SetProvisioningUrl(aProvisioningUrl); SuccessOrExit(error); memset(mJoinerRouters, 0, sizeof(mJoinerRouters)); SuccessOrExit(error = netif.GetMle().Discover(0, netif.GetMac().GetPanId(), true, false, HandleDiscoverResult, this)); mVendorName = aVendorName; mVendorModel = aVendorModel; mVendorSwVersion = aVendorSwVersion; mVendorData = aVendorData; mCallback = aCallback; mContext = aContext; mState = OT_JOINER_STATE_DISCOVER; exit: return error; }
otError Netif::AddExternalUnicastAddress(const NetifUnicastAddress &aAddress) { otError error = OT_ERROR_NONE; NetifUnicastAddress *entry; size_t num = sizeof(mExtUnicastAddresses) / sizeof(mExtUnicastAddresses[0]); VerifyOrExit(!aAddress.GetAddress().IsLinkLocal(), error = OT_ERROR_INVALID_ARGS); for (entry = mUnicastAddresses; entry; entry = entry->GetNext()) { if (entry->GetAddress() == aAddress.GetAddress()) { VerifyOrExit((entry >= &mExtUnicastAddresses[0]) && (entry < &mExtUnicastAddresses[num]), error = OT_ERROR_INVALID_ARGS); entry->mPrefixLength = aAddress.mPrefixLength; entry->mPreferred = aAddress.mPreferred; entry->mValid = aAddress.mValid; ExitNow(); } } // Find an available entry in the `mExtUnicastAddresses` array. for (entry = &mExtUnicastAddresses[0]; num > 0; num--, entry++) { // In an unused/available entry, `mNext` points back to the entry itself. if (entry->mNext == entry) { break; } } VerifyOrExit(num > 0, error = OT_ERROR_NO_BUFS); // Copy the new address into the available entry and insert it in linked-list. *entry = aAddress; entry->mNext = mUnicastAddresses; mUnicastAddresses = entry; GetNotifier().SetFlags(OT_CHANGED_IP6_ADDRESS_ADDED); exit: return error; }
otError Netif::SubscribeMulticast(NetifMulticastAddress &aAddress) { otError error = OT_ERROR_NONE; for (NetifMulticastAddress *cur = mMulticastAddresses; cur; cur = cur->GetNext()) { if (cur == &aAddress) { ExitNow(error = OT_ERROR_ALREADY); } } aAddress.mNext = mMulticastAddresses; mMulticastAddresses = &aAddress; GetNotifier().SetFlags(OT_CHANGED_IP6_MULTICAST_SUBSRCRIBED); exit: return error; }
otError Netif::AddUnicastAddress(NetifUnicastAddress &aAddress) { otError error = OT_ERROR_NONE; for (NetifUnicastAddress *cur = mUnicastAddresses; cur; cur = cur->GetNext()) { if (cur == &aAddress) { ExitNow(error = OT_ERROR_ALREADY); } } aAddress.mNext = mUnicastAddresses; mUnicastAddresses = &aAddress; GetNotifier().SetFlags(aAddress.mRloc ? OT_CHANGED_THREAD_RLOC_ADDED : OT_CHANGED_IP6_ADDRESS_ADDED); exit: return error; }
void Joiner::Complete(otError aError) { ThreadNetif &netif = GetNetif(); mState = OT_JOINER_STATE_IDLE; otError error = OT_ERROR_NOT_FOUND; GetNotifier().Signal(OT_CHANGED_JOINER_STATE); netif.GetCoapSecure().Disconnect(); if (aError != OT_ERROR_NONE && aError != OT_ERROR_NOT_FOUND) { error = TryNextJoin(); } if (error == OT_ERROR_NOT_FOUND && mCallback) { netif.GetCoapSecure().Stop(); otJoinerCallback callback = mCallback; mCallback = NULL; callback(aError, mContext); } }
otError Netif::RemoveExternalUnicastAddress(const Address &aAddress) { otError error = OT_ERROR_NONE; NetifUnicastAddress *entry; NetifUnicastAddress *last = NULL; size_t num = sizeof(mExtUnicastAddresses) / sizeof(mExtUnicastAddresses[0]); for (entry = mUnicastAddresses; entry; entry = entry->GetNext()) { if (entry->GetAddress() == aAddress) { VerifyOrExit((entry >= &mExtUnicastAddresses[0]) && (entry < &mExtUnicastAddresses[num]), error = OT_ERROR_INVALID_ARGS); if (last) { last->mNext = entry->mNext; } else { mUnicastAddresses = entry->GetNext(); } break; } last = entry; } VerifyOrExit(entry != NULL, error = OT_ERROR_NOT_FOUND); // To mark the address entry as unused/available, set the `mNext` pointer back to the entry itself. entry->mNext = entry; GetNotifier().SetFlags(OT_CHANGED_IP6_ADDRESS_REMOVED); exit: return error; }
template <> Notifier &Instance::Get(void) { return GetNotifier(); }
bool Win32Vif::InitTap(const char* vifName, const ProtoAddress& vifAddr, unsigned int maskLen) { HKEY key; ULONG status; char adapterid[1024]; char tapname[1024]; long len; /// Open Registry and get a list of network adapters status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, NETWORK_CONNECTIONS_KEY, 0, KEY_READ, &key); if (status != ERROR_SUCCESS) { PLOG(PL_ERROR,"Win32Vif::InitTap() Error opening registry key:%s\n",NETWORK_CONNECTIONS_KEY); return false; } /* find the adapter with TAPSUFFIX */ for (int enum_index = 0; ; enum_index++) { len = sizeof(adapterid); if (RegEnumKeyEx(key, enum_index, adapterid, (LPDWORD)&len, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) { RegCloseKey(key); PLOG(PL_ERROR,"Win32Vif::InitTap() error: Couldn't find TAP-Win32 adapter.\n"); return false; } sprintf(tapname, USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid); // Get the tap handle tap_handle = CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0); if (tap_handle != INVALID_HANDLE_VALUE) { break; } } RegCloseKey(key); PLOG(PL_INFO,"win32Vif::InitTap() found tap adapter %s\n",tapname); if (!ConfigureTap(adapterid,vifName,vifAddr,maskLen)) return false; if (NULL == (input_handle = CreateEvent(NULL,TRUE,FALSE,NULL))) { input_handle = INVALID_HANDLE_VALUE; PLOG(PL_ERROR,"Win32Vif::InitTap() CreateEvent(input_handle) error: %s\n", ::GetErrorString()); Close(); // ljt?? return false; } if (NULL == (output_handle = CreateEvent(NULL,TRUE,FALSE,NULL))) { output_handle = INVALID_HANDLE_VALUE; PLOG(PL_ERROR,"Win32Vif::InitTap() CreateEvent(output_handle) error: %s\n",::GetErrorString()); Close(); // ljt?? return false; } memset(&read_overlapped,0,sizeof(read_overlapped)); read_overlapped.hEvent = input_handle; memset(&write_overlapped,0,sizeof(write_overlapped)); write_overlapped.hEvent = output_handle; StartInputNotification(); // Start overlapped notifications if (NULL != GetNotifier()) { // Initiate overlapped I/O ... DWORD bytesRead; if (0 != ReadFile(tap_handle, read_buffer, BUFFER_MAX, &bytesRead, &read_overlapped)) { input_ready = true; read_count = bytesRead; } else { switch(GetLastError()) { case ERROR_IO_PENDING: read_count = 0; input_ready = false; break; //case ERROR_BROKEN_PIPE: default: PLOG(PL_ERROR,"Win32Vif::InitTap() ReadFile() error: %s\n", ::GetErrorString()); Close(); return false; } } } if (!UpdateNotification()) { PLOG(PL_ERROR, "Win32Vif::InitTap() error updating notification\n"); Close(); return false; } return true; } // end Win32Vif::InitTap()
bool Win32Vif::Write(const char* buffer, unsigned int numBytes) { // ljt is this quite right?? DWORD bytesWritten = 0; OVERLAPPED overlappedPtr; // set up overlapped structure fields overlappedPtr.Offset = 0; overlappedPtr.OffsetHigh = 0; overlappedPtr.hEvent = NULL; const char* bufPtr = buffer; if (NULL != GetNotifier()) { if (!output_ready) { if (FALSE != GetOverlappedResult(tap_handle,&write_overlapped,&bytesWritten,FALSE)) { output_ready = true; overlappedPtr = write_overlapped; bufPtr = write_buffer; if (numBytes > BUFFER_MAX) numBytes = BUFFER_MAX; memcpy(write_buffer,buffer,numBytes); } else { if (GetDebugLevel() >= 2) PLOG(PL_ERROR,"Win32Vif::Write() GetOverlappedResult() error: %s\n",::GetErrorString()); return false; } } } if (0 != WriteFile(tap_handle,bufPtr,numBytes,&bytesWritten,(LPOVERLAPPED)&overlappedPtr)) { numBytes = bytesWritten; if (0 == numBytes) { output_ready = false; } return true; } else { numBytes = 0; switch (GetLastError()) { case ERROR_IO_PENDING: return true; case ERROR_BROKEN_PIPE: OnNotify(NOTIFY_NONE); break; default: PLOG(PL_ERROR,"Win32Vif::Write() WriteFile() error(%d): %s\n",GetLastError(),::GetErrorString()); break; } return false; } return true; } // end Win32Vif::Write()
bool Win32Vif::Read(char* buffer, unsigned int& numBytes) { DWORD bytesRead = 0; unsigned int len = 0; if (NULL != GetNotifier()) { if (!input_ready) { // We had a pending overlapped read operation if (FALSE != GetOverlappedResult(tap_handle,&read_overlapped,&bytesRead,FALSE)) { numBytes = read_count = bytesRead; memcpy(buffer,read_buffer,bytesRead); input_ready = true; } else { numBytes = 0; switch (GetLastError()) { case ERROR_BROKEN_PIPE: OnNotify(NOTIFY_NONE); return false; default: PLOG(PL_ERROR,"Win32Vif::Read() GetOverlappedResult() error (%d): %s\n",GetLastError(), ::GetErrorString()); return false; } } } } // Do we have any data in our "read_buffer"? if (read_count > 0) { memcpy (buffer,read_buffer,read_count); numBytes = read_count; read_count = 0; return true; } // Read more as needed, triggering overlapped I/O memset(&read_overlapped,0,sizeof(read_overlapped)); read_overlapped.hEvent = input_handle; memset(&write_overlapped,0,sizeof(write_overlapped)); write_overlapped.hEvent = output_handle; // ljt need me? bytesRead = 0; len = BUFFER_MAX; if (0 != ReadFile(tap_handle,read_buffer,len,&bytesRead,&read_overlapped)) { memcpy(buffer,read_buffer,bytesRead); numBytes = bytesRead; input_ready = true; } else { switch(GetLastError()) { case ERROR_IO_PENDING: read_count = 0; input_ready = false; break; case ERROR_BROKEN_PIPE: if (0 == bytesRead) { OnNotify(NOTIFY_NONE); return false; } break; default: PLOG(PL_ERROR,"Win32Vif::Read() error: %s\n", ::GetErrorString()); if (0 == bytesRead) return false; break; } } numBytes = bytesRead; return true; } // end Win32Vif::Read()