// Release the stack void FreeNativeStack(NATIVE_STACK *a) { // Validate arguments if (a == NULL) { return; } if (a->Ipc != NULL && IsZero(&a->CurrentDhcpOptionList, sizeof(a->CurrentDhcpOptionList)) == false) { IP dhcp_server; UINTToIP(&dhcp_server, a->CurrentDhcpOptionList.ServerAddress); IPCDhcpFreeIP(a->Ipc, &dhcp_server); SleepThread(200); } a->Halt = true; Cancel(a->Cancel); Disconnect(a->Sock1); Disconnect(a->Sock2); WaitThread(a->MainThread, INFINITE); ReleaseThread(a->MainThread); CloseEth(a->Eth); FreeIPC(a->Ipc); NsStopIpTablesTracking(a); ReleaseCancel(a->Cancel); ReleaseSock(a->Sock1); ReleaseSock(a->Sock2); ReleaseCedar(a->Cedar); Free(a); }
void CleanupEtherIPServer(ETHERIP_SERVER *s) { UINT i; // Validate arguments if (s == NULL) { return; } EtherIPLog(s, "LE_STOP"); if (s->IpcConnectThread != NULL) { ReleaseThread(s->IpcConnectThread); } if (s->Ipc != NULL) { FreeIPC(s->Ipc); } for (i = 0;i < LIST_NUM(s->SendPacketList);i++) { BLOCK *b = LIST_DATA(s->SendPacketList, i); FreeBlock(b); } ReleaseList(s->SendPacketList); ReleaseSockEvent(s->SockEvent); ReleaseCedar(s->Cedar); DeleteLock(s->Lock); Free(s); }
// Processing of the interrupt void EtherIPProcInterrupts(ETHERIP_SERVER *s) { // Validate arguments if (s == NULL) { return; } // If EtherIP settings have been changed, and the change may effect to this connection, disconnect if (s->Ipc != NULL) { if (s->Ike->IPsec->EtherIPIdListSettingVerNo != s->LastEtherIPSettingVerNo) { ETHERIP_ID id; bool ok = true; s->LastEtherIPSettingVerNo = s->Ike->IPsec->EtherIPIdListSettingVerNo; if (SearchEtherIPId(s->IPsec, &id, s->ClientId) == false && SearchEtherIPId(s->IPsec, &id, "*") == false) { ok = false; } else { if (StrCmpi(s->CurrentEtherIPIdSetting.HubName, id.HubName) != 0 || StrCmpi(s->CurrentEtherIPIdSetting.UserName, id.UserName) != 0 || StrCmp(s->CurrentEtherIPIdSetting.Password, id.Password) != 0) { ok = false; } } if (ok == false) { // Disconnect immediately since setting of EtherIP seems to have been changed FreeIPC(s->Ipc); s->Ipc = NULL; EtherIPLog(s, "LE_RECONNECT"); } } } // Connect if IPC connection is not completed Lock(s->Lock); { if (s->Ipc == NULL) { if (s->IpcConnectThread == NULL) { if ((s->LastConnectFailedTick == 0) || ((s->LastConnectFailedTick + (UINT64)ETHERIP_VPN_CONNECT_RETRY_INTERVAL) <= s->Now)) { Lock(s->IPsec->LockSettings); { Copy(&s->CurrentIPSecServiceSetting, &s->IPsec->Services, sizeof(IPSEC_SERVICES)); } Unlock(s->IPsec->LockSettings); s->IpcConnectThread = NewThread(EtherIPIpcConnectThread, s); AddThreadToThreadList(s->Ike->ThreadList, s->IpcConnectThread); AddRef(s->Ref); } } } } Unlock(s->Lock); if (s->Ipc != NULL) { // Set to get hit the SockEvent when a packet arrives via the IPC IPCSetSockEventWhenRecvL2Packet(s->Ipc, s->SockEvent); // IPC interrupt processing IPCProcessInterrupts(s->Ipc); // Receive the MAC frame which arrived via the IPC while (true) { BLOCK *b = IPCRecvL2(s->Ipc); UCHAR *dst; UINT dst_size; if (b == NULL) { break; } if (b->Size >= 14) { BLOCK *block; // Store the arrived MAC frame by adding an EtherIP header to the reception packet queue if (s->L2TPv3 == false) { dst_size = b->Size + 2; dst = Malloc(dst_size); dst[0] = 0x30; dst[1] = 0x00; Copy(dst + 2, b->Buf, b->Size); } else { dst = Clone(b->Buf, b->Size); dst_size = b->Size; } block = NewBlock(dst, dst_size, 0); Add(s->SendPacketList, block); } FreeBlock(b); } if (IsIPCConnected(s->Ipc) == false) { // IPC connection is disconnected FreeIPC(s->Ipc); s->Ipc = NULL; } } }