diff --git a/src/Cedar/BridgeUnix.c b/src/Cedar/BridgeUnix.c index eca09011..8d3759e0 100644 --- a/src/Cedar/BridgeUnix.c +++ b/src/Cedar/BridgeUnix.c @@ -598,7 +598,7 @@ ETH *OpenEthLinux(char *name, bool local, bool tapmode, char *tapaddr) { #ifndef NO_VLAN // In tap mode - VLAN *v = NewTap(name, tapaddr); + VLAN *v = NewTap(name, tapaddr, true); if (v == NULL) { return NULL; diff --git a/src/Cedar/Client.c b/src/Cedar/Client.c index 705c3117..2a60c80e 100644 --- a/src/Cedar/Client.c +++ b/src/Cedar/Client.c @@ -3854,6 +3854,7 @@ void InRpcClientConfig(CLIENT_CONFIG *c, PACK *p) c->KeepConnectProtocol = PackGetInt(p, "KeepConnectProtocol"); c->KeepConnectInterval = PackGetInt(p, "KeepConnectInterval"); c->AllowRemoteConfig = PackGetInt(p, "AllowRemoteConfig") == 0 ? false : true; + c->NicDownOnDisconnect = PackGetBool(p, "NicDownOnDisconnect"); PackGetStr(p, "KeepConnectHost", c->KeepConnectHost, sizeof(c->KeepConnectHost)); } void OutRpcClientConfig(PACK *p, CLIENT_CONFIG *c) @@ -3869,6 +3870,7 @@ void OutRpcClientConfig(PACK *p, CLIENT_CONFIG *c) PackAddInt(p, "KeepConnectProtocol", c->KeepConnectProtocol); PackAddInt(p, "KeepConnectInterval", c->KeepConnectInterval); PackAddInt(p, "AllowRemoteConfig", c->AllowRemoteConfig); + PackAddBool(p, "NicDownOnDisconnect", c->NicDownOnDisconnect); PackAddStr(p, "KeepConnectHost", c->KeepConnectHost); } @@ -6657,7 +6659,7 @@ bool CtConnect(CLIENT *c, RPC_CLIENT_CONNECT *connect) CLog(c, "LC_CONNECT", connect->AccountName); - r->ClientSession = NewClientSessionEx(c->Cedar, r->ClientOption, r->ClientAuth, pa, r); + r->ClientSession = NewClientSessionEx(c->Cedar, r->ClientOption, r->ClientAuth, pa, r, &c->Config.NicDownOnDisconnect); Notify(r->ClientSession, CLIENT_NOTIFY_ACCOUNT_CHANGED); ret = true; @@ -6674,6 +6676,82 @@ bool CtConnect(CLIENT *c, RPC_CLIENT_CONNECT *connect) return ret; } +// Put all unused TUN interfaces down +// Requires account and VLan lists of the CLIENT argument to be already locked +bool CtVLansDown(CLIENT *c) +{ +#ifndef UNIX_LINUX + return true; +#else + int i; + LIST *tmpVLanList; + UNIX_VLAN t, *r; + bool result = true; + + if (c == NULL) + { + return false; + } + + tmpVLanList = CloneList(c->UnixVLanList); + if (tmpVLanList == NULL) + { + return false; + } + + // Remove from tmpVLanList all VLans corresponding to active sessions + for (i = 0; i < LIST_NUM(c->AccountList); ++i) + { + ACCOUNT *a = LIST_DATA(c->AccountList, i); + if (a->ClientSession == NULL) + { + continue; + } + + Zero(&t, sizeof(t)); + StrCpy(t.Name, sizeof(t.Name), a->ClientOption->DeviceName); + r = Search(tmpVLanList, &t); + Delete(tmpVLanList, r); + } + + // Set down every VLan in tmpVLanList + for (i = 0; i < LIST_NUM(tmpVLanList) && result; ++i) + { + r = LIST_DATA(tmpVLanList, i); + result = UnixVLanSetState(r->Name, false); + // [MP:] Should we report *critical* error on failure? + } + + ReleaseList(tmpVLanList); + return result; +#endif +} + +// Put all TUN interfaces up +// Requires VLan list of the CLIENT argument to be already locked +bool CtVLansUp(CLIENT *c) +{ +#ifndef UNIX_LINUX + return true; +#else + int i; + UNIX_VLAN *r; + + if (c == NULL) + { + return false; + } + + for (i = 0; i < LIST_NUM(c->UnixVLanList); ++i) + { + r = LIST_DATA(c->UnixVLanList, i); + UnixVLanSetState(r->Name, true); + } + + return true; +#endif +} + // Get the account information bool CtGetAccount(CLIENT *c, RPC_CLIENT_GET_ACCOUNT *a) { @@ -6894,6 +6972,20 @@ bool CtSetClientConfig(CLIENT *c, CLIENT_CONFIG *o) } Unlock(k->lock); + // Apply TAP state + LockList(c->AccountList); + LockList(c->UnixVLanList); + if (o->NicDownOnDisconnect) + { + CtVLansDown(c); + } + else + { + CtVLansUp(c); + } + UnlockList(c->UnixVLanList); + UnlockList(c->AccountList); + return true; } @@ -8302,8 +8394,8 @@ bool CtCreateVLan(CLIENT *c, RPC_CLIENT_CREATE_VLAN *create) GenMacAddress(r->MacAddress); StrCpy(r->Name, sizeof(r->Name), create->DeviceName); - // Create a Tap - if (UnixVLanCreate(r->Name, r->MacAddress) == false) + // Create a TUN + if (UnixVLanCreate(r->Name, r->MacAddress, !c->Config.NicDownOnDisconnect) == false) { // Failure Free(r); @@ -9371,6 +9463,7 @@ void CiLoadClientConfig(CLIENT_CONFIG *c, FOLDER *f) c->AllowRemoteConfig = CfgGetBool(f, "AllowRemoteConfig"); c->KeepConnectInterval = MAKESURE(CfgGetInt(f, "KeepConnectInterval"), KEEP_INTERVAL_MIN, KEEP_INTERVAL_MAX); c->NoChangeWcmNetworkSettingOnWindows8 = CfgGetBool(f, "NoChangeWcmNetworkSettingOnWindows8"); + c->NicDownOnDisconnect = CfgGetBool(f, "NicDownOnDisconnect"); } // Read the client authentication data @@ -9699,7 +9792,7 @@ void CiLoadVLan(CLIENT *c, FOLDER *f) Add(c->UnixVLanList, v); #ifdef OS_UNIX - UnixVLanCreate(v->Name, v->MacAddress); + UnixVLanCreate(v->Name, v->MacAddress, !c->Config.NicDownOnDisconnect); #endif // OS_UNIX } @@ -9923,6 +10016,7 @@ void CiWriteClientConfig(FOLDER *cc, CLIENT_CONFIG *config) CfgAddBool(cc, "AllowRemoteConfig", config->AllowRemoteConfig); CfgAddInt(cc, "KeepConnectInterval", config->KeepConnectInterval); CfgAddBool(cc, "NoChangeWcmNetworkSettingOnWindows8", config->NoChangeWcmNetworkSettingOnWindows8); + CfgAddBool(cc, "NicDownOnDisconnect", config->NicDownOnDisconnect); } // Write the client authentication data diff --git a/src/Cedar/Client.h b/src/Cedar/Client.h index 03715ea9..205f1d11 100644 --- a/src/Cedar/Client.h +++ b/src/Cedar/Client.h @@ -195,6 +195,7 @@ struct CLIENT_CONFIG UINT KeepConnectProtocol; // Protocol UINT KeepConnectInterval; // Interval bool NoChangeWcmNetworkSettingOnWindows8; // Don't change the WCM network settings on Windows 8 + bool NicDownOnDisconnect; // Put NIC down on disconnect/connection loss and put it up again after connecting to VPN server }; // Version acquisition diff --git a/src/Cedar/Command.c b/src/Cedar/Command.c index ef0ea6fb..0538b7f3 100644 --- a/src/Cedar/Command.c +++ b/src/Cedar/Command.c @@ -3119,6 +3119,9 @@ void PcMain(PC *pc) {"AccountImport", PcAccountImport}, {"RemoteEnable", PcRemoteEnable}, {"RemoteDisable", PcRemoteDisable}, + {"TUNDownOnDisconnectEnable", PcTunDownOnDisconnectEnable}, + {"TUNDownOnDisconnectDisable", PcTunDownOnDisconnectDisable}, + {"TUNDownOnDisconnectGet", PcTunDownOnDisconnectGet}, {"KeepEnable", PcKeepEnable}, {"KeepDisable", PcKeepDisable}, {"KeepSet", PcKeepSet}, @@ -6641,6 +6644,136 @@ UINT PcRemoteDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param) return ret; } +// Enable turning TUN interface up/down on client connect/disconnect +UINT PcTunDownOnDisconnectEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param) +{ + LIST *o; + PC *pc = (PC *)param; + UINT ret = ERR_NO_ERROR; + CLIENT_CONFIG t; + + // Get the parameter list + o = ParseCommandList(c, cmd_name, str, NULL, 0); + if (o == NULL) + { + return ERR_INVALID_PARAMETER; + } + + // RPC call + Zero(&t, sizeof(t)); + + ret = CcGetClientConfig(pc->RemoteClient, &t); + + if (ret == ERR_NO_ERROR) + { + // Change the settings + t.NicDownOnDisconnect = true; + ret = CcSetClientConfig(pc->RemoteClient, &t); + } + + if (ret == ERR_NO_ERROR) + { + // Success + } + + if (ret != ERR_NO_ERROR) + { + // Error has occurred + CmdPrintError(c, ret); + } + + // Release of the parameter list + FreeParamValueList(o); + + return ret; +} + +// Disable turning TUN interface up/down on client connect/disconnect +UINT PcTunDownOnDisconnectDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param) +{ + LIST *o; + PC *pc = (PC *)param; + UINT ret = ERR_NO_ERROR; + CLIENT_CONFIG t; + + // Get the parameter list + o = ParseCommandList(c, cmd_name, str, NULL, 0); + if (o == NULL) + { + return ERR_INVALID_PARAMETER; + } + + // RPC call + Zero(&t, sizeof(t)); + + ret = CcGetClientConfig(pc->RemoteClient, &t); + + if (ret == ERR_NO_ERROR) + { + // Change the settings + t.NicDownOnDisconnect = false; + ret = CcSetClientConfig(pc->RemoteClient, &t); + } + + if (ret == ERR_NO_ERROR) + { + // Success + } + + if (ret != ERR_NO_ERROR) + { + // Error has occurred + CmdPrintError(c, ret); + } + + // Release of the parameter list + FreeParamValueList(o); + + return ret; +} + +// Get status of turning TUN interface up/down on client connect/disconnect +UINT PcTunDownOnDisconnectGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param) +{ + LIST *o; + PC *pc = (PC *)param; + UINT ret = ERR_NO_ERROR; + CLIENT_CONFIG t; + + o = ParseCommandList(c, cmd_name, str, NULL, 0); + if (o == NULL) + { + return ERR_INVALID_PARAMETER; + } + + // RPC call + Zero(&t, sizeof(t)); + + ret = CcGetClientConfig(pc->RemoteClient, &t); + + if (ret == ERR_NO_ERROR) + { + wchar_t tmp[MAX_SIZE]; + CT *ct = CtNewStandard(); + + CtInsert(ct, _UU("CMD_TUNDownOnDisconnectGet_COLUMN1"), + t.NicDownOnDisconnect ? _UU("SM_ACCESS_ENABLE") : _UU("SM_ACCESS_DISABLE")); + + CtFree(ct, c); + } + + if (ret != ERR_NO_ERROR) + { + // Error has occurred + CmdPrintError(c, ret); + } + + // Release of the parameter list + FreeParamValueList(o); + + return ret; +} + // Enable the maintenance function of the Internet connection UINT PcKeepEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param) { diff --git a/src/Cedar/Command.h b/src/Cedar/Command.h index 6708fc92..f2171541 100644 --- a/src/Cedar/Command.h +++ b/src/Cedar/Command.h @@ -483,6 +483,9 @@ UINT PcAccountExport(CONSOLE *c, char *cmd_name, wchar_t *str, void *param); UINT PcAccountImport(CONSOLE *c, char *cmd_name, wchar_t *str, void *param); UINT PcRemoteEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param); UINT PcRemoteDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param); +UINT PcTunDownOnDisconnectEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param); +UINT PcTunDownOnDisconnectDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param); +UINT PcTunDownOnDisconnectGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param); UINT PcKeepEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param); UINT PcKeepDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param); UINT PcKeepSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param); diff --git a/src/Cedar/Link.c b/src/Cedar/Link.c index d9aaf385..c26307fd 100644 --- a/src/Cedar/Link.c +++ b/src/Cedar/Link.c @@ -612,7 +612,7 @@ void StartLink(LINK *k) pa->Param = (void *)k; LockLink(k); { - k->ClientSession = NewClientSession(k->Cedar, k->Option, k->Auth, pa); + k->ClientSession = NewClientSession(k->Cedar, k->Option, k->Auth, pa, NULL); } UnlockLink(k); } diff --git a/src/Cedar/Protocol.c b/src/Cedar/Protocol.c index bbb5ce8a..a812c58a 100644 --- a/src/Cedar/Protocol.c +++ b/src/Cedar/Protocol.c @@ -5385,6 +5385,14 @@ REDIRECTED: PrintStatus(sess, _UU("STATUS_9")); +#ifdef OS_UNIX + // Set TUN up if session has NicDownOnDisconnect set + if (c->Session->NicDownOnDisconnect != NULL) + { + UnixVLanSetState(c->Session->ClientOption->DeviceName, true); + } +#endif + // Shift the connection to the tunneling mode StartTunnelingMode(c); s = NULL; diff --git a/src/Cedar/Session.c b/src/Cedar/Session.c index 0857a20c..4dc88553 100644 --- a/src/Cedar/Session.c +++ b/src/Cedar/Session.c @@ -1381,6 +1381,13 @@ void CleanupSession(SESSION *s) FreePacketAdapter(s->PacketAdapter); } +#ifdef OS_UNIX + if (s->NicDownOnDisconnect != NULL && *s->NicDownOnDisconnect) + { + UnixVLanSetState(s->ClientOption->DeviceName, false); + } +#endif + if (s->OldTraffic != NULL) { FreeTraffic(s->OldTraffic); @@ -1529,6 +1536,13 @@ void ClientThread(THREAD *t, void *param) CLog(s->Cedar->Client, "LC_CONNECT_ERROR", s->ClientOption->AccountName, GetUniErrorStr(s->Err), s->Err); +#ifdef OS_UNIX + if (s->NicDownOnDisconnect != NULL && *s->NicDownOnDisconnect) + { + UnixVLanSetState(s->ClientOption->DeviceName, false); + } +#endif + if (s->LinkModeClient && s->Link != NULL) { HLog(s->Link->Hub, "LH_CONNECT_ERROR", s->ClientOption->AccountName, @@ -1953,7 +1967,7 @@ SESSION *NewRpcSessionEx2(CEDAR *cedar, CLIENT_OPTION *option, UINT *err, char * } // Create a client session -SESSION *NewClientSessionEx(CEDAR *cedar, CLIENT_OPTION *option, CLIENT_AUTH *auth, PACKET_ADAPTER *pa, ACCOUNT *account) +SESSION *NewClientSessionEx(CEDAR *cedar, CLIENT_OPTION *option, CLIENT_AUTH *auth, PACKET_ADAPTER *pa, ACCOUNT *account, bool *NicDownOnDisconnect) { SESSION *s; THREAD *t; @@ -2081,6 +2095,8 @@ SESSION *NewClientSessionEx(CEDAR *cedar, CLIENT_OPTION *option, CLIENT_AUTH *au s->ClientOption->NumRetry = 0; } + s->NicDownOnDisconnect = NicDownOnDisconnect; + // Create a client thread t = NewThread(ClientThread, (void *)s); WaitThreadInit(t); @@ -2088,9 +2104,9 @@ SESSION *NewClientSessionEx(CEDAR *cedar, CLIENT_OPTION *option, CLIENT_AUTH *au return s; } -SESSION *NewClientSession(CEDAR *cedar, CLIENT_OPTION *option, CLIENT_AUTH *auth, PACKET_ADAPTER *pa) +SESSION *NewClientSession(CEDAR *cedar, CLIENT_OPTION *option, CLIENT_AUTH *auth, PACKET_ADAPTER *pa, bool *NicDownOnDisconnect) { - return NewClientSessionEx(cedar, option, auth, pa, NULL); + return NewClientSessionEx(cedar, option, auth, pa, NULL, NicDownOnDisconnect); } // Get the session from the 32bit session key diff --git a/src/Cedar/Session.h b/src/Cedar/Session.h index 97376981..0d5b5194 100644 --- a/src/Cedar/Session.h +++ b/src/Cedar/Session.h @@ -324,6 +324,8 @@ struct SESSION // Measures for D-Link bug UINT64 LastDLinkSTPPacketSendTick; // Last D-Link STP packet transmission time UCHAR LastDLinkSTPPacketDataHash[MD5_SIZE]; // Last D-Link STP packet hash + + bool *NicDownOnDisconnect; // Pointer to client configuration parameter. NULL for non-clients. }; // Password dialog @@ -399,8 +401,8 @@ struct UI_CHECKCERT // Function prototype -SESSION *NewClientSessionEx(CEDAR *cedar, CLIENT_OPTION *option, CLIENT_AUTH *auth, PACKET_ADAPTER *pa, struct ACCOUNT *account); -SESSION *NewClientSession(CEDAR *cedar, CLIENT_OPTION *option, CLIENT_AUTH *auth, PACKET_ADAPTER *pa); +SESSION *NewClientSessionEx(CEDAR *cedar, CLIENT_OPTION *option, CLIENT_AUTH *auth, PACKET_ADAPTER *pa, struct ACCOUNT *account, bool *NicDownOnDisconnect); +SESSION *NewClientSession(CEDAR *cedar, CLIENT_OPTION *option, CLIENT_AUTH *auth, PACKET_ADAPTER *pa, bool *NicDownOnDisconnect); SESSION *NewRpcSession(CEDAR *cedar, CLIENT_OPTION *option); SESSION *NewRpcSessionEx(CEDAR *cedar, CLIENT_OPTION *option, UINT *err, char *client_str); SESSION *NewRpcSessionEx2(CEDAR *cedar, CLIENT_OPTION *option, UINT *err, char *client_str, void *hWnd); diff --git a/src/Cedar/VLanUnix.c b/src/Cedar/VLanUnix.c index bc37aca8..9de2f629 100644 --- a/src/Cedar/VLanUnix.c +++ b/src/Cedar/VLanUnix.c @@ -360,7 +360,7 @@ void FreeVLan(VLAN *v) } // Create a tap -VLAN *NewTap(char *name, char *mac_address) +VLAN *NewTap(char *name, char *mac_address, bool create_up) { int fd; VLAN *v; @@ -370,7 +370,7 @@ VLAN *NewTap(char *name, char *mac_address) return NULL; } - fd = UnixCreateTapDeviceEx(name, "tap", mac_address); + fd = UnixCreateTapDeviceEx(name, "tap", mac_address, create_up); if (fd == -1) { return NULL; @@ -423,13 +423,25 @@ VLAN *NewVLan(char *instance_name, VLAN_PARAM *param) return v; } +// Generate TUN interface name +void GenerateTunName(char *name, char *prefix, char *tun_name, size_t tun_name_len) +{ + char instance_name_lower[MAX_SIZE]; + + // Generate the device name + StrCpy(instance_name_lower, sizeof(instance_name_lower), name); + Trim(instance_name_lower); + StrLower(instance_name_lower); + Format(tun_name, tun_name_len, "%s_%s", prefix, instance_name_lower); + + tun_name[15] = 0; +} // Create a tap device -int UnixCreateTapDeviceEx(char *name, char *prefix, UCHAR *mac_address) +int UnixCreateTapDeviceEx(char *name, char *prefix, UCHAR *mac_address, bool create_up) { int fd; struct ifreq ifr; char eth_name[MAX_SIZE]; - char instance_name_lower[MAX_SIZE]; struct sockaddr sa; char *tap_name = TAP_FILENAME_1; int s; @@ -442,13 +454,7 @@ int UnixCreateTapDeviceEx(char *name, char *prefix, UCHAR *mac_address) return -1; } - // Generate the device name - StrCpy(instance_name_lower, sizeof(instance_name_lower), name); - Trim(instance_name_lower); - StrLower(instance_name_lower); - Format(eth_name, sizeof(eth_name), "%s_%s", prefix, instance_name_lower); - - eth_name[15] = 0; + GenerateTunName(name, prefix, eth_name, sizeof(eth_name)); // Open the tun / tap #ifndef UNIX_MACOS @@ -531,8 +537,11 @@ int UnixCreateTapDeviceEx(char *name, char *prefix, UCHAR *mac_address) StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), eth_name); ioctl(s, SIOCGIFFLAGS, &ifr); - ifr.ifr_flags |= IFF_UP; - ioctl(s, SIOCSIFFLAGS, &ifr); + if (create_up) + { + ifr.ifr_flags |= IFF_UP; + ioctl(s, SIOCSIFFLAGS, &ifr); + } close(s); } @@ -560,8 +569,11 @@ int UnixCreateTapDeviceEx(char *name, char *prefix, UCHAR *mac_address) StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), macos_eth_name); ioctl(s, SIOCGIFFLAGS, &ifr); - ifr.ifr_flags |= IFF_UP; - ioctl(s, SIOCSIFFLAGS, &ifr); + if (create_up) + { + ifr.ifr_flags |= IFF_UP; + ioctl(s, SIOCSIFFLAGS, &ifr); + } close(s); } @@ -637,9 +649,9 @@ int UnixCreateTapDeviceEx(char *name, char *prefix, UCHAR *mac_address) return fd; } -int UnixCreateTapDevice(char *name, UCHAR *mac_address) +int UnixCreateTapDevice(char *name, UCHAR *mac_address, bool create_up) { - return UnixCreateTapDeviceEx(name, "vpn", mac_address); + return UnixCreateTapDeviceEx(name, "vpn", mac_address, create_up); } // Close the tap device @@ -696,7 +708,7 @@ void UnixVLanInit() } // Create a VLAN -bool UnixVLanCreateEx(char *name, char *prefix, UCHAR *mac_address) +bool UnixVLanCreateEx(char *name, char *prefix, UCHAR *mac_address, bool create_up) { // Validate arguments char tmp[MAX_SIZE]; @@ -727,7 +739,7 @@ bool UnixVLanCreateEx(char *name, char *prefix, UCHAR *mac_address) } // Create a tap device - fd = UnixCreateTapDeviceEx(name, prefix, mac_address); + fd = UnixCreateTapDeviceEx(name, prefix, mac_address, create_up); if (fd == -1) { // Failure to create @@ -745,9 +757,63 @@ bool UnixVLanCreateEx(char *name, char *prefix, UCHAR *mac_address) return true; } -bool UnixVLanCreate(char *name, UCHAR *mac_address) +bool UnixVLanCreate(char *name, UCHAR *mac_address, bool create_up) { - return UnixVLanCreateEx(name, "vpn", mac_address); + return UnixVLanCreateEx(name, "vpn", mac_address, create_up); +} + +// Set a VLAN up/down +bool UnixVLanSetState(char* name, bool state_up) +{ +#ifdef UNIX_LINUX + UNIX_VLAN_LIST *t, tt; + struct ifreq ifr; + int s; + char eth_name[MAX_SIZE]; + + LockList(unix_vlan); + { + int result; + // Find a device with the same name + Zero(&tt, sizeof(tt)); + StrCpy(tt.Name, sizeof(tt.Name), name); + + t = Search(unix_vlan, &tt); + if (t == NULL) + { + // No such device + UnlockList(unix_vlan); + return false; + } + + GenerateTunName(name, "vpn", eth_name, sizeof(eth_name)); + Zero(&ifr, sizeof(ifr)); + StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), eth_name); + + s = socket(AF_INET, SOCK_DGRAM, 0); + if (s == -1) + { + // Failed to create socket + UnlockList(unix_vlan); + return false; + } + + ioctl(s, SIOCGIFFLAGS, &ifr); + if (state_up) + { + ifr.ifr_flags |= IFF_UP; + } + else + { + ifr.ifr_flags &= ~IFF_UP; + } + result = ioctl(s, SIOCSIFFLAGS, &ifr); + close(s); + } + UnlockList(unix_vlan); +#endif // UNIX_LINUX + + return true; } // Enumerate VLANs diff --git a/src/Cedar/VLanUnix.h b/src/Cedar/VLanUnix.h index aafa3824..b628dcd4 100644 --- a/src/Cedar/VLanUnix.h +++ b/src/Cedar/VLanUnix.h @@ -129,7 +129,7 @@ struct VLAN // Function prototype VLAN *NewVLan(char *instance_name, VLAN_PARAM *param); -VLAN *NewTap(char *name, char *mac_address); +VLAN *NewTap(char *name, char *mac_address, bool create_up); void FreeVLan(VLAN *v); CANCEL *VLanGetCancel(VLAN *v); bool VLanGetNextPacket(VLAN *v, void **buf, UINT *size); @@ -154,15 +154,16 @@ struct UNIX_VLAN_LIST int fd; // fd }; -int UnixCreateTapDevice(char *name, UCHAR *mac_address); -int UnixCreateTapDeviceEx(char *name, char *prefix, UCHAR *mac_address); +int UnixCreateTapDevice(char *name, UCHAR *mac_address, bool create_up); +int UnixCreateTapDeviceEx(char *name, char *prefix, UCHAR *mac_address, bool create_up); void UnixCloseTapDevice(int fd); void UnixVLanInit(); void UnixVLanFree(); -bool UnixVLanCreate(char *name, UCHAR *mac_address); -bool UnixVLanCreateEx(char *name, char *prefix, UCHAR *mac_address); +bool UnixVLanCreate(char *name, UCHAR *mac_address, bool create_up); +bool UnixVLanCreateEx(char *name, char *prefix, UCHAR *mac_address, bool create_up); TOKEN_LIST *UnixVLanEnum(); void UnixVLanDelete(char *name); +bool UnixVLanSetState(char* name, bool state_up); int UnixVLanGet(char *name); int UnixCompareVLan(void *p1, void *p2); diff --git a/src/Mayaqua/Memory.c b/src/Mayaqua/Memory.c index e5011c16..3de5c16b 100644 --- a/src/Mayaqua/Memory.c +++ b/src/Mayaqua/Memory.c @@ -1326,6 +1326,20 @@ QUEUE *NewQueueFast() return q; } +// Clone the list +LIST *CloneList(LIST *o) +{ + LIST *n = NewList(o->cmp); + + // Memory reallocation + Free(n->p); + n->p = ToArray(o); + n->num_item = n->num_reserved = LIST_NUM(o); + n->sorted = o->sorted; + + return n; +} + // Copy the list to an array void CopyToArray(LIST *o, void *p) { diff --git a/src/Mayaqua/Memory.h b/src/Mayaqua/Memory.h index 8059efcb..11f9fa2e 100644 --- a/src/Mayaqua/Memory.h +++ b/src/Mayaqua/Memory.h @@ -380,6 +380,7 @@ LIST *NewListFast(COMPARE *cmp); LIST *NewListEx(COMPARE *cmp, bool fast); LIST *NewListEx2(COMPARE *cmp, bool fast, bool fast_malloc); LIST *NewListSingle(void *p); +LIST *CloneList(LIST *o); void CopyToArray(LIST *o, void *p); void *ToArray(LIST *o); void *ToArrayEx(LIST *o, bool fast); diff --git a/src/bin/hamcore/strtable_cn.stb b/src/bin/hamcore/strtable_cn.stb index f223717d..88b23ea0 100644 --- a/src/bin/hamcore/strtable_cn.stb +++ b/src/bin/hamcore/strtable_cn.stb @@ -4686,6 +4686,21 @@ CMD_ServerCipherSet_Args ServerCipherSet [name] CMD_ServerCipherSet_[name] 指定设置加密和数字签名的程序。可以使用的程序一览,可以从 ServerCipherGet 指令中获取。 CMD_ServerCipherSet_PROMPT_NAME 指定的加密程序的名称: +# TUNDownOnDisconnectEnable command +CMD_TUNDownOnDisconnectEnable Enable the Turn TUN Interface Down on Client Disconnect Function. +CMD_TUNDownOnDisconnectEnable_Help This allows you to enable Turn TUN Interface Down on Client Disconnect Function. +CMD_TUNDownOnDisconnectEnable_Args TUNDownOnDisconnectEnable + +# TUNDownOnDisconnectDisable command +CMD_TUNDownOnDisconnectDisable Disable the Turn TUN Interface Down on Client Disconnect Function. +CMD_TUNDownOnDisconnectDisable_Help This allows you to disable Turn TUN Interface Down on Client Disconnect Function. +CMD_TUNDownOnDisconnectDisable_Args TUNDownOnDisconnectDisable + +# TUNDownOnDisconnectGet command +CMD_TUNDownOnDisconnectGet Get status of the Turn TUN Interface Down on Client Disconnect Function. +CMD_TUNDownOnDisconnectGet_Help This allows you to get status of the Turn TUN Interface Down on Client Disconnect Function. +CMD_TUNDownOnDisconnectGet_Args TUNDownOnDisconnectGet +CMD_TUNDownOnDisconnectGet_COLUMN1 Put TUN down on disconnect # KeepEnable 命令 CMD_KeepEnable 启动 Internet 保持连接功能 diff --git a/src/bin/hamcore/strtable_en.stb b/src/bin/hamcore/strtable_en.stb index 4c6693a8..cbd386a4 100644 --- a/src/bin/hamcore/strtable_en.stb +++ b/src/bin/hamcore/strtable_en.stb @@ -4669,6 +4669,21 @@ CMD_ServerCipherSet_Args ServerCipherSet [name] CMD_ServerCipherSet_[name] This specifies the encrypted and electronic signature algorithm to set. You can obtain the list of usable algorithms by using the ServerCipherGet command. CMD_ServerCipherSet_PROMPT_NAME Encrypted Algorithm Name to Specify: +# TUNDownOnDisconnectEnable command +CMD_TUNDownOnDisconnectEnable Enable the Turn TUN Interface Down on Client Disconnect Function. +CMD_TUNDownOnDisconnectEnable_Help This allows you to enable Turn TUN Interface Down on Client Disconnect Function. +CMD_TUNDownOnDisconnectEnable_Args TUNDownOnDisconnectEnable + +# TUNDownOnDisconnectDisable command +CMD_TUNDownOnDisconnectDisable Disable the Turn TUN Interface Down on Client Disconnect Function. +CMD_TUNDownOnDisconnectDisable_Help This allows you to disable Turn TUN Interface Down on Client Disconnect Function. +CMD_TUNDownOnDisconnectDisable_Args TUNDownOnDisconnectDisable + +# TUNDownOnDisconnectGet command +CMD_TUNDownOnDisconnectGet Get status of the Turn TUN Interface Down on Client Disconnect Function. +CMD_TUNDownOnDisconnectGet_Help This allows you to get status of the Turn TUN Interface Down on Client Disconnect Function. +CMD_TUNDownOnDisconnectGet_Args TUNDownOnDisconnectGet +CMD_TUNDownOnDisconnectGet_COLUMN1 Put TUN down on disconnect # KeepEnable command CMD_KeepEnable Enable the Keep Alive Internet Connection Function diff --git a/src/bin/hamcore/strtable_ja.stb b/src/bin/hamcore/strtable_ja.stb index 14ae7109..9b13c5ab 100644 --- a/src/bin/hamcore/strtable_ja.stb +++ b/src/bin/hamcore/strtable_ja.stb @@ -4671,6 +4671,21 @@ CMD_ServerCipherSet_Args ServerCipherSet [name] CMD_ServerCipherSet_[name] 設定するる暗号化および電子署名アルゴリズムを指定します。使用可能なアルゴリズムの一覧は、ServerCipherGet コマンドで取得することができます。 CMD_ServerCipherSet_PROMPT_NAME 指定する暗号化アルゴリズム名: +# TUNDownOnDisconnectEnable command +CMD_TUNDownOnDisconnectEnable Enable the Turn TUN Interface Down on Client Disconnect Function. +CMD_TUNDownOnDisconnectEnable_Help This allows you to enable Turn TUN Interface Down on Client Disconnect Function. +CMD_TUNDownOnDisconnectEnable_Args TUNDownOnDisconnectEnable + +# TUNDownOnDisconnectDisable command +CMD_TUNDownOnDisconnectDisable Disable the Turn TUN Interface Down on Client Disconnect Function. +CMD_TUNDownOnDisconnectDisable_Help This allows you to disable Turn TUN Interface Down on Client Disconnect Function. +CMD_TUNDownOnDisconnectDisable_Args TUNDownOnDisconnectDisable + +# TUNDownOnDisconnectGet command +CMD_TUNDownOnDisconnectGet Get status of the Turn TUN Interface Down on Client Disconnect Function. +CMD_TUNDownOnDisconnectGet_Help This allows you to get status of the Turn TUN Interface Down on Client Disconnect Function. +CMD_TUNDownOnDisconnectGet_Args TUNDownOnDisconnectGet +CMD_TUNDownOnDisconnectGet_COLUMN1 Put TUN down on disconnect # KeepEnable コマンド CMD_KeepEnable インターネット接続の維持機能の有効化 diff --git a/src/bin/hamcore/strtable_ko.stb b/src/bin/hamcore/strtable_ko.stb index 63574e36..406ac1ac 100644 --- a/src/bin/hamcore/strtable_ko.stb +++ b/src/bin/hamcore/strtable_ko.stb @@ -4666,6 +4666,21 @@ CMD_ServerCipherSet_Args ServerCipherSet [name] CMD_ServerCipherSet_ [name] 설정해야 루루 암호화 및 전자 서명 알고리즘을 지정합니다. 사용 가능한 알고리즘 목록은 ServerCipherGet 명령에서 얻을 수 있습니다. CMD_ServerCipherSet_PROMPT_NAME 지정하는 암호화 알고리즘 명: +# TUNDownOnDisconnectEnable command +CMD_TUNDownOnDisconnectEnable Enable the Turn TUN Interface Down on Client Disconnect Function. +CMD_TUNDownOnDisconnectEnable_Help This allows you to enable Turn TUN Interface Down on Client Disconnect Function. +CMD_TUNDownOnDisconnectEnable_Args TUNDownOnDisconnectEnable + +# TUNDownOnDisconnectDisable command +CMD_TUNDownOnDisconnectDisable Disable the Turn TUN Interface Down on Client Disconnect Function. +CMD_TUNDownOnDisconnectDisable_Help This allows you to disable Turn TUN Interface Down on Client Disconnect Function. +CMD_TUNDownOnDisconnectDisable_Args TUNDownOnDisconnectDisable + +# TUNDownOnDisconnectGet command +CMD_TUNDownOnDisconnectGet Get status of the Turn TUN Interface Down on Client Disconnect Function. +CMD_TUNDownOnDisconnectGet_Help This allows you to get status of the Turn TUN Interface Down on Client Disconnect Function. +CMD_TUNDownOnDisconnectGet_Args TUNDownOnDisconnectGet +CMD_TUNDownOnDisconnectGet_COLUMN1 Put TUN down on disconnect # KeepEnable 명령 CMD_KeepEnable 인터넷 연결 유지 기능 활성화 diff --git a/src/bin/hamcore/strtable_tw.stb b/src/bin/hamcore/strtable_tw.stb index 4ca3eec3..78317dcb 100644 --- a/src/bin/hamcore/strtable_tw.stb +++ b/src/bin/hamcore/strtable_tw.stb @@ -4686,6 +4686,21 @@ CMD_ServerCipherSet_Args ServerCipherSet [name] CMD_ServerCipherSet_[name] 指定設置加密和數位簽章的程式。可以使用的程式一覽,可以從 ServerCipherGet 指令中獲取。 CMD_ServerCipherSet_PROMPT_NAME 指定的加密程式的名稱: +# TUNDownOnDisconnectEnable command +CMD_TUNDownOnDisconnectEnable Enable the Turn TUN Interface Down on Client Disconnect Function. +CMD_TUNDownOnDisconnectEnable_Help This allows you to enable Turn TUN Interface Down on Client Disconnect Function. +CMD_TUNDownOnDisconnectEnable_Args TUNDownOnDisconnectEnable + +# TUNDownOnDisconnectDisable command +CMD_TUNDownOnDisconnectDisable Disable the Turn TUN Interface Down on Client Disconnect Function. +CMD_TUNDownOnDisconnectDisable_Help This allows you to disable Turn TUN Interface Down on Client Disconnect Function. +CMD_TUNDownOnDisconnectDisable_Args TUNDownOnDisconnectDisable + +# TUNDownOnDisconnectGet command +CMD_TUNDownOnDisconnectGet Get status of the Turn TUN Interface Down on Client Disconnect Function. +CMD_TUNDownOnDisconnectGet_Help This allows you to get status of the Turn TUN Interface Down on Client Disconnect Function. +CMD_TUNDownOnDisconnectGet_Args TUNDownOnDisconnectGet +CMD_TUNDownOnDisconnectGet_COLUMN1 Put TUN down on disconnect # KeepEnable 命令 CMD_KeepEnable 啟動 Internet 保持連接功能