mirror of
https://github.com/ZeroTier/ZeroTierOne
synced 2025-08-22 14:23:59 -07:00
add network event script support
Based on PR #1669 of @joseph-henry Co-authored-by: Joseph Henry Signed-off-by: Oskari Rauta <oskari.rauta@gmail.com>
This commit is contained in:
parent
e0a3291235
commit
da0ed006e8
5 changed files with 96 additions and 22 deletions
16
one.cpp
16
one.cpp
|
@ -1996,6 +1996,7 @@ static void printHelp(const char *cn,FILE *out)
|
|||
|
||||
#ifdef __UNIX_LIKE__
|
||||
fprintf(out," -d - Fork and run as daemon (Unix-ish OSes)" ZT_EOL_S);
|
||||
fprintf(out," -s<path> - path to script to execute on network events" ZT_EOL_S);
|
||||
#endif // __UNIX_LIKE__
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
|
@ -2012,13 +2013,13 @@ static void printHelp(const char *cn,FILE *out)
|
|||
class _OneServiceRunner
|
||||
{
|
||||
public:
|
||||
_OneServiceRunner(const char *pn,const std::string &hd,unsigned int p) : progname(pn),returnValue(0),port(p),homeDir(hd) {}
|
||||
_OneServiceRunner(const char *pn,const std::string &hd,unsigned int p, std::string &sp) : progname(pn),returnValue(0),port(p),homeDir(hd),scriptPath(sp) {}
|
||||
void threadMain()
|
||||
throw()
|
||||
{
|
||||
try {
|
||||
for(;;) {
|
||||
zt1Service = OneService::newInstance(homeDir.c_str(),port);
|
||||
zt1Service = OneService::newInstance(homeDir.c_str(),port,scriptPath.c_str());
|
||||
switch(zt1Service->run()) {
|
||||
case OneService::ONE_STILL_RUNNING: // shouldn't happen, run() won't return until done
|
||||
case OneService::ONE_NORMAL_TERMINATION:
|
||||
|
@ -2053,6 +2054,7 @@ public:
|
|||
unsigned int returnValue;
|
||||
unsigned int port;
|
||||
const std::string &homeDir;
|
||||
const std::string &scriptPath;
|
||||
};
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
|
@ -2082,6 +2084,7 @@ int main(int argc,char **argv)
|
|||
signal(SIGTERM,&_sighandlerQuit);
|
||||
signal(SIGQUIT,&_sighandlerQuit);
|
||||
signal(SIGINT,&_sighandlerQuit);
|
||||
signal(SIGCHLD, SIG_IGN);
|
||||
|
||||
/* Ensure that there are no inherited file descriptors open from a previous
|
||||
* incarnation. This is a hack to ensure that GitHub issue #61 or variants
|
||||
|
@ -2115,7 +2118,7 @@ int main(int argc,char **argv)
|
|||
if ((strstr(argv[0],"zerotier-cli"))||(strstr(argv[0],"ZEROTIER-CLI")))
|
||||
return cli(argc,argv);
|
||||
|
||||
std::string homeDir;
|
||||
std::string homeDir, scriptPath;
|
||||
unsigned int port = ZT_DEFAULT_PORT;
|
||||
bool skipRootCheck = false;
|
||||
|
||||
|
@ -2135,6 +2138,11 @@ int main(int argc,char **argv)
|
|||
case 'd': // Run in background as daemon
|
||||
runAsDaemon = true;
|
||||
break;
|
||||
case 's': // script to run on network events
|
||||
if (argv[i][2]) {
|
||||
scriptPath = argv[i] + 2;
|
||||
} else printHelp(argv[0],stdout);
|
||||
break;
|
||||
#endif // __UNIX_LIKE__
|
||||
|
||||
case 'U':
|
||||
|
@ -2306,7 +2314,7 @@ int main(int argc,char **argv)
|
|||
}
|
||||
#endif // __UNIX_LIKE__
|
||||
|
||||
_OneServiceRunner thr(argv[0],homeDir,port);
|
||||
_OneServiceRunner thr(argv[0],homeDir,port,scriptPath);
|
||||
thr.threadMain();
|
||||
//Thread::join(Thread::start(&thr));
|
||||
|
||||
|
|
|
@ -11,34 +11,34 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../node/Constants.hpp"
|
||||
#include "../node/Utils.hpp"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef __UNIX_LIKE__
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
#include <dirent.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
#include <shlobj.h>
|
||||
#include <netioapi.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <netioapi.h>
|
||||
#include <shlobj.h>
|
||||
#include <wincrypt.h>
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "OSUtils.hpp"
|
||||
|
@ -551,6 +551,53 @@ std::string OSUtils::jsonBinFromHex(const nlohmann::json &jv)
|
|||
return std::string();
|
||||
}
|
||||
|
||||
void OSUtils::_hookCmd(const char* scriptPath, const uint64_t nwid, const char *homePath, ZT_VirtualNetworkConfigOperation op)
|
||||
{
|
||||
if (! scriptPath || ! strlen(scriptPath) || nwid == 0) {
|
||||
#ifdef ZT_TRACE
|
||||
fprintf(stderr, "no script path specified\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
long p = (long)fork();
|
||||
|
||||
if (p > 0) {
|
||||
#ifdef ZT_TRACE
|
||||
fprintf(stderr, "Running network event hook script (%s)\n", scriptPath);
|
||||
#endif
|
||||
//int exitcode = -1;
|
||||
//::waitpid(p, &exitcode, 0);
|
||||
}
|
||||
else if (p == 0) {
|
||||
::close(STDOUT_FILENO);
|
||||
::close(STDERR_FILENO);
|
||||
char cmdBuf[128] = { 0 };
|
||||
OSUtils::ztsnprintf(cmdBuf, sizeof(cmdBuf), "%s", scriptPath);
|
||||
char nwidStr[17] = { 0 };
|
||||
OSUtils::ztsnprintf(nwidStr, sizeof(nwidStr), "%.16llx", nwid);
|
||||
std::string cmd;
|
||||
switch (op) {
|
||||
case ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP:
|
||||
cmd = std::string(cmdBuf) + " network_up " + std::string(nwidStr) + " " + std::string(homePath) + "";
|
||||
//::execl("/bin/sh", "sh", cmdBuf, "network_up", nwidStr, homePath, "&", (const char*)0);
|
||||
break;
|
||||
case ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE:
|
||||
cmd = std::string(cmdBuf) + " network_update " + std::string(nwidStr) + " " + std::string(homePath) + "";
|
||||
//::execl("/bin/sh", "sh", cmdBuf, "network_update", nwidStr, homePath, "&", (const char*)0);
|
||||
break;
|
||||
case ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DOWN: // Same as _DESTROY
|
||||
cmd = std::string(cmdBuf) + " network_down " + std::string(nwidStr) + " " + std::string(homePath) + "";
|
||||
//::execl("/bin/sh", "sh", cmdBuf, "network_down", nwidStr, homePath, "&", (const char*)0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// Using system instead of execl, because execl blocks connections through cli
|
||||
if (!cmd.empty()) ::system(cmd.c_str());
|
||||
::_exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OMIT_JSON_SUPPORT
|
||||
|
||||
// Used to convert HTTP header names to ASCII lower case
|
||||
|
|
|
@ -269,6 +269,16 @@ public:
|
|||
*/
|
||||
static std::string platformDefaultHomePath();
|
||||
|
||||
/**
|
||||
* Executes a system script specified by user
|
||||
*
|
||||
* @param scriptPath The full path to the script that should be run on each network event
|
||||
* @param nwid The Network ID of the network in question
|
||||
* @param homePath full patch to homepath containing connections settings and data
|
||||
* @param op The operation performed up on the network
|
||||
*/
|
||||
static void _hookCmd(const char *scriptPath, const uint64_t nwid, const char *homePath, ZT_VirtualNetworkConfigOperation op);
|
||||
|
||||
#ifndef OMIT_JSON_SUPPORT
|
||||
static nlohmann::json jsonParse(const std::string &buf);
|
||||
static std::string jsonDump(const nlohmann::json &j,int indentation = 1);
|
||||
|
|
|
@ -704,8 +704,11 @@ public:
|
|||
// begin member variables --------------------------------------------------
|
||||
|
||||
const std::string _homePath;
|
||||
|
||||
std::string _authToken;
|
||||
std::string _controllerDbPath;
|
||||
std::string _eventHookScriptPath;
|
||||
|
||||
const std::string _networksPath;
|
||||
const std::string _moonsPath;
|
||||
|
||||
|
@ -804,9 +807,10 @@ public:
|
|||
|
||||
// end member variables ----------------------------------------------------
|
||||
|
||||
OneServiceImpl(const char *hp,unsigned int port) :
|
||||
OneServiceImpl(const char *hp,unsigned int port,const char *sp) :
|
||||
_homePath((hp) ? hp : ".")
|
||||
,_controllerDbPath(_homePath + ZT_PATH_SEPARATOR_S "controller.d")
|
||||
,_eventHookScriptPath(sp)
|
||||
,_networksPath(_homePath + ZT_PATH_SEPARATOR_S "networks.d")
|
||||
,_moonsPath(_homePath + ZT_PATH_SEPARATOR_S "moons.d")
|
||||
,_controller((EmbeddedNetworkController *)0)
|
||||
|
@ -2160,6 +2164,10 @@ public:
|
|||
}
|
||||
#endif
|
||||
|
||||
if (_eventHookScriptPath.empty()) {
|
||||
_eventHookScriptPath = std::string(OSUtils::jsonString(settings["eventHookScriptPath"],""));
|
||||
}
|
||||
|
||||
json &ignoreIfs = settings["interfacePrefixBlacklist"];
|
||||
if (ignoreIfs.is_array()) {
|
||||
for(unsigned long i=0;i<ignoreIfs.size();++i) {
|
||||
|
@ -2796,6 +2804,7 @@ public:
|
|||
}
|
||||
break;
|
||||
}
|
||||
OSUtils::_hookCmd(_eventHookScriptPath.c_str(), nwid, _homePath.c_str(), op);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3555,7 +3564,7 @@ std::string OneService::platformDefaultHomePath()
|
|||
return OSUtils::platformDefaultHomePath();
|
||||
}
|
||||
|
||||
OneService *OneService::newInstance(const char *hp,unsigned int port) { return new OneServiceImpl(hp,port); }
|
||||
OneService *OneService::newInstance(const char *hp,unsigned int port,const char *sp) { return new OneServiceImpl(hp,port,sp); }
|
||||
OneService::~OneService() {}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -111,7 +111,7 @@ public:
|
|||
* @param hp Home path
|
||||
* @param port TCP and UDP port for packets and HTTP control (if 0, pick random port)
|
||||
*/
|
||||
static OneService *newInstance(const char *hp,unsigned int port);
|
||||
static OneService *newInstance(const char *hp,unsigned int port, const char *sp);
|
||||
|
||||
virtual ~OneService();
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue