From 59e1483dbf707b1adcec04f5f450c0b3445ab5f2 Mon Sep 17 00:00:00 2001 From: Joshua Perry Date: Sun, 5 Aug 2018 17:35:57 +0200 Subject: [PATCH] Put TUN down on client disconnect. On startup client creates TUN interface in UP state and kept it UP even if connection to the server was lost. Creating interface in DOWN state, turning it UP on successful (re-)connection to server and DOWN on either disconnect or connection loss would enable DHCP client (say dhclient5) to detect necessity for lease renewal. Added a client configuration parameter to create TUN interface in DOWN state and commands to enable, disable, and query the configuration parameter. Enabling the parameter causes client to put all unused TUN interfaces DOWN, create new TUN interfaces in DOWN state, and turn TUN interfaces corresponding to active sessions DOWN on connection loss or disconnecting from server. Disabling the parameter forces client to turn all TUN interfaces UP and create new TUN interfaces in UP state. Default value is 'Disable'. --- src/Cedar/BridgeUnix.c | 2 +- src/Cedar/Client.c | 102 +++++++++++++++++++++++- src/Cedar/Client.h | 1 + src/Cedar/Command.c | 133 ++++++++++++++++++++++++++++++++ src/Cedar/Command.h | 3 + src/Cedar/Link.c | 2 +- src/Cedar/Protocol.c | 8 ++ src/Cedar/Session.c | 22 +++++- src/Cedar/Session.h | 6 +- src/Cedar/VLanUnix.c | 108 +++++++++++++++++++++----- src/Cedar/VLanUnix.h | 11 +-- src/bin/hamcore/strtable_cn.stb | 15 ++++ src/bin/hamcore/strtable_en.stb | 15 ++++ src/bin/hamcore/strtable_ja.stb | 15 ++++ src/bin/hamcore/strtable_ko.stb | 15 ++++ src/bin/hamcore/strtable_tw.stb | 15 ++++ 16 files changed, 436 insertions(+), 37 deletions(-) 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/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 保持連接功能