agent mac: move from common

Windows agent has been moved from common to core,
so for consistency move mac agent too.

Since agent and agent-enabled client depend on jsoncpp,
also move jsoncpp build scripts.

Signed-off-by: Lev Stipakov <lev@openvpn.net>
This commit is contained in:
Lev Stipakov
2021-05-27 15:37:32 +03:00
committed by David Sommerseth
parent 0ad1bfecc0
commit d31620d0c6
12 changed files with 925 additions and 2 deletions

View File

@@ -19,3 +19,7 @@ if (WIN32)
add_subdirectory(openvpn/ovpnagent/win)
endif ()
if (APPLE)
add_subdirectory(openvpn/ovpnagent/mac)
endif ()

View File

@@ -141,6 +141,12 @@ function (add_json_library target)
target_link_libraries(${target} jsoncpp_lib)
target_compile_definitions(${target} PRIVATE -DHAVE_JSONCPP)
message("Adding jsoncpp to " ${target})
elseif (APPLE)
set(PLAT ${OPENVPN_PLAT})
set(JSONCPP_DIR ${DEP_DIR}/jsoncpp/jsoncpp-${PLAT})
target_include_directories(${target} PRIVATE ${JSONCPP_DIR}/include)
target_compile_definitions(${target} PRIVATE -DHAVE_JSONCPP)
target_link_libraries(${target} ${JSONCPP_DIR}/lib/libjsoncpp.a)
else ()
find_package(PkgConfig REQUIRED)
if (MINGW)

78
deps/jsoncpp/build-jsoncpp vendored Executable file
View File

@@ -0,0 +1,78 @@
#!/usr/bin/env bash
set -e
if [ -z "$O3" ]; then
echo O3 var must point to ovpn3 tree
exit 1
fi
if [ -z "$TARGET" ]; then
echo TARGET var must be defined
exit 1
fi
[ -z "$DL" ] && DL=~/Downloads
# source vars
. $O3/core/vars/vars-${TARGET}
. $O3/core/deps/lib-versions
# source helper functions
. $O3/core/deps/functions.sh
GPP=g++
LD=ld
AR=ar
RANLIB=ranlib
[ "$GPP_CMD" ] && GPP=$GPP_CMD
[ "$LD_CMD" ] && LD=$LD_CMD
[ "$AR_CMD" ] && AR=$AR_CMD
[ "$RANLIB_CMD" ] && RANLIB=$RANLIB_CMD
case $PLATFORM in
android*)
echo PLATFORM android
host="x86_64-apple-darwin"
target=arm
;;
ios*)
echo PLATFORM ios
host="x86_64-apple-darwin"
target=arm
;;
*)
host=""
target=""
;;
esac
if [ "$target" ]; then
targ_opt="--target=$target"
fi
if [ "$host" ]; then
host_opt="--host=$host"
fi
FNAME=jsoncpp-${JSONCPP_VERSION}.tar.gz
URL=https://github.com/open-source-parsers/jsoncpp/archive/refs/tags/${JSONCPP_VERSION}.tar.gz
CSUM=${JSONCPP_CSUM}
download
DIST=$(pwd)/jsoncpp/jsoncpp-$PLATFORM
rm -rf $DIST
mkdir -p $DIST/include
mkdir $DIST/lib
tar xfz $DL/$FNAME
cd jsoncpp-$JSONCPP_VERSION
python amalgamate.py
cd dist
CMD="$GPP -I. $PLATFORM_FLAGS $CXX_COMPILER_FLAGS $OTHER_COMPILER_FLAGS $LIB_OPT_LEVEL $LIB_FPIC -c jsoncpp.cpp"
echo $CMD
$CMD
$AR rc $DIST/lib/libjsoncpp.a jsoncpp.o
$RANLIB $DIST/lib/libjsoncpp.a
cp -a json $DIST/include/
exit 0

2
openvpn/ovpnagent/mac/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
ovpnagent
ovpnagent.dSYM

View File

@@ -0,0 +1,6 @@
add_executable(agent_macos ovpnagent.cpp)
add_core_dependencies(agent_macos)
add_json_library(agent_macos)
# Avoid deprecated warning for using daemon
target_compile_options(agent_macos PRIVATE -Wno-deprecated-declarations)

13
openvpn/ovpnagent/mac/go Executable file
View File

@@ -0,0 +1,13 @@
#!/bin/bash
set -e
pushd $O3/core
if [ "$(uname)" == "Darwin" ]; then
. vars/vars-osx64
. vars/setpath
export GCC_EXTRA="$GCC_EXTRA -Wno-deprecated-declarations" # for daemon()
else
. vars/vars-linux
. vars/setpath
fi
popd
ASIO=1 MTLS=1 NOSSL=1 build ovpnagent

View File

@@ -0,0 +1 @@
http-listen /tmp/agent.sock unix-stream

View File

@@ -0,0 +1,767 @@
// OpenVPN
// Copyright (C) 2012-2017 OpenVPN Technologies, Inc.
// All rights reserved
// OpenVPN agent for Mac
//#define OPENVPN_EXIT_IN 30
//#define OPENVPN_SSL_DEBUG 9 // MbedTLS debugging max level
#include <iostream>
#include <string>
#include <utility>
#include <unistd.h>
// debug settings (production setting in parentheses)
#define OPENVPN_LOG_SSL(x) OPENVPN_LOG(x)
// VERSION version can be passed on build command line
#include <openvpn/common/stringize.hpp>
#ifdef VERSION
#define HTTP_SERVER_VERSION OPENVPN_STRINGIZE(VERSION)
#else
#define HTTP_SERVER_VERSION "0.1.1"
#endif
#ifdef OVPNAGENT_NAME
#define OVPNAGENT_NAME_STRING OPENVPN_STRINGIZE(OVPNAGENT_NAME)
#else
#define OVPNAGENT_NAME_STRING "ovpnagent"
#endif
#include <openvpn/log/logbase.hpp>
#include <openvpn/common/platform.hpp>
#include <openvpn/common/size.hpp>
#include <openvpn/common/exception.hpp>
#include <openvpn/common/rc.hpp>
#include <openvpn/common/runcontext.hpp>
#include <openvpn/common/file.hpp>
#include <openvpn/common/getopt.hpp>
#include <openvpn/common/scoped_fd.hpp>
#include <openvpn/common/daemon.hpp>
#include <openvpn/common/waitbarrier.hpp>
#include <openvpn/common/usergroup.hpp>
#include <openvpn/common/xmitfd.hpp>
#include <openvpn/buffer/bufstr.hpp>
#include <openvpn/buffer/buflist.hpp>
#include <openvpn/init/initprocess.hpp>
#include <openvpn/ssl/sslchoose.hpp>
#include <openvpn/ws/httpserv.hpp>
#include <openvpn/tun/mac/client/tunsetup.hpp>
void log_version()
{
std::cout << "OpenVPN Agent (Mac) " HTTP_SERVER_VERSION " [" SSL_LIB_NAME "]"
#ifdef OPENVPN_DEBUG
<< " built on " __DATE__ " " __TIME__
#endif
<< std::endl;
}
using namespace openvpn;
class MySessionStats : public SessionStats
{
public:
typedef RCPtr<MySessionStats> Ptr;
virtual void error(const size_t err_type, const std::string* text=nullptr) override
{
OPENVPN_LOG(Error::name(err_type));
}
std::string dump() const
{
std::ostringstream os;
os << "OpenVPN Agent Stats" << std::endl;
return os.str();
}
};
struct ThreadCommon
{
ThreadCommon(const char *unix_sock, const char *user, const char *group)
: listen_list(build_listen_list(unix_sock)),
user_group(user, group, true),
stats(new MySessionStats),
event_loop_bar(1)
{
}
static Listen::List build_listen_list(const char *unix_sock)
{
Listen::List ll;
if (unix_sock)
{
Listen::Item li;
li.directive = "http-listen";
li.addr = unix_sock;
li.proto = Protocol(Protocol::UnixStream);
li.n_threads = 1;
ll.push_back(std::move(li));
}
return ll;
}
void show_unused_options() const
{
}
const Listen::List listen_list;
const SetUserGroup user_group;
MySessionStats::Ptr stats;
PThreadBarrier event_loop_bar;
};
class MyListener : public WS::Server::Listener
{
// handles ungraceful exit of client and closes tun
class WatchdogThread : public RC<thread_safe_refcount>
{
private:
typedef RCPtr<WatchdogThread> Ptr;
friend class MyListener;
MyListener *parent;
public:
WatchdogThread(MyListener *parent_arg, openvpn_io::io_context& io_context_arg)
: parent(parent_arg), io_context(io_context_arg) { }
~WatchdogThread()
{
if (th.joinable())
{
OPENVPN_LOG("Reaping watchdog thread");
th.join();
}
}
// starts a thread which blocks until:
// - process with given pid exits
// - there is a data in pipe
void watch(pid_t pid)
{
if (client_pid != -1)
{
OPENVPN_LOG("Watchdog already set for pid " << client_pid << ", won't set for pid " << pid);
return;
}
OPENVPN_LOG("Setting up watchdog for pid " << pid << " exit notification");
// self-pipe trick to be able to interrupt wait when agent exits
if (pipe(fds) == -1)
{
OPENVPN_LOG("pipe() failed: " << strerror(errno));
return;
}
// make write nonblocking
fcntl(fds[1], F_SETFL, O_NONBLOCK);
kq = kqueue();
if (kq == -1)
{
OPENVPN_LOG("kqueue() failed: " << strerror(errno));
close_pipe_fds();
return;
}
// add pid exit and self-pipe read_fd to kevent changelist
struct kevent chlist[2];
EV_SET(&chlist[0], pid, EVFILT_PROC, EV_ADD | EV_RECEIPT, NOTE_EXIT, 0, NULL);
EV_SET(&chlist[1], fds[0], EVFILT_READ, EV_ADD, 0, 0, NULL);
if (kevent(kq, chlist, 2, NULL, 0, NULL) == -1)
{
OPENVPN_LOG("kevent() failed: " << strerror(errno));
close_pipe_fds();
return;
}
// reap thread if previous client didn't exit gracefullt
if (th.joinable())
{
OPENVPN_LOG("Reaping watchdog thread");
th.join();
}
client_pid = pid;
th = std::thread([self=Ptr(this), pid]() {
struct kevent evlist[2];
int nev = kevent(self->kq, 0, 0, evlist, 2, NULL);
if (nev == -1)
{
OPENVPN_LOG("kevent() failed: " << strerror(errno));
self->close_pipe_fds();
return;
}
for (int i = 0; i < nev; ++ i)
{
if (evlist[i].filter == EVFILT_PROC)
{
openvpn_io::post(self->io_context, [self, pid]() {
OPENVPN_LOG("Process " << pid << " has exited, destroy tun");
std::ostringstream os;
self->parent->destroy_tun(os);
});
}
}
self->client_pid = -1;
self->close_pipe_fds();
});
}
void unwatch()
{
OPENVPN_LOG("Stopping watchdog thread");
write(fds[1], "x", 1);
if (th.joinable())
{
OPENVPN_LOG("Reaping watchdog thread");
th.join();
}
}
private:
void close_pipe_fds()
{
close(fds[0]);
close(fds[1]);
}
pid_t client_pid = -1;
openvpn_io::io_context& io_context;
int kq; // kqueue
int fds[2]; // file descriptors for self-pipe trick
std::thread th;
};
public:
typedef RCPtr<MyListener> Ptr;
MyListener(openvpn_io::io_context& io_context,
const WS::Server::Config::Ptr& config,
const Listen::List& listen_list,
const WS::Server::Listener::Client::Factory::Ptr& client_factory)
: WS::Server::Listener(io_context, config, listen_list, client_factory)
{
watchdog.reset(new WatchdogThread(this, io_context));
}
ScopedFD establish_tun(const TunBuilderCapture& tbc,
TunBuilderSetup::Config* config,
Stop* stop,
std::ostream& os)
{
if (!tun)
tun.reset(new TunMac::Setup);
return ScopedFD(tun->establish(tbc, config, stop, os));
}
void destroy_tun(std::ostream& os)
{
if (tun)
{
tun->destroy(os);
tun.reset();
}
remove_cmds_bypass_hosts.execute(os);
remove_cmds_bypass_hosts.clear();
}
void set_watchdog(pid_t pid)
{
watchdog->watch(pid);
}
void unset_watchdog()
{
watchdog->unwatch();
}
void add_bypass_route(const std::string& host, bool ipv6)
{
if (host != bypass_host)
{
bypass_host = host;
std::ostringstream os;
remove_cmds_bypass_hosts.execute(os);
remove_cmds_bypass_hosts.clear();
ActionList add_cmds;
TunMac::Setup::add_bypass_route(host, ipv6, add_cmds, remove_cmds_bypass_hosts);
add_cmds.execute(os);
OPENVPN_LOG(os.str());
}
}
private:
virtual bool allow_client(AsioPolySock::Base& sock) override
{
return true;
}
std::string bypass_host;
ActionList remove_cmds_bypass_hosts;
TunMac::Setup::Ptr tun;
WatchdogThread::Ptr watchdog;
};
class MyClientInstance : public WS::Server::Listener::Client
{
public:
typedef RCPtr<MyClientInstance> Ptr;
MyClientInstance(WS::Server::Listener::Client::Initializer& ci)
: WS::Server::Listener::Client(ci)
{
//OPENVPN_LOG("INSTANCE START");
}
virtual ~MyClientInstance()
{
//OPENVPN_LOG("INSTANCE DESTRUCT");
}
private:
void generate_reply(const Json::Value& jout)
{
out = buf_from_string(jout.toStyledString());
WS::Server::ContentInfo ci;
ci.http_status = HTTP::Status::OK;
ci.type = "application/json";
ci.length = out->size();
ci.keepalive = keepalive_request();
generate_reply_headers(ci);
}
virtual void http_request_received() override
{
// alloc output buffer
std::ostringstream os;
try {
const HTTP::Request& req = request();
OPENVPN_LOG("HTTP request received from " << sock->remote_endpoint_str() << '\n' << req.to_string());
// get content-type
const std::string content_type = req.headers.get_value_trim("content-type");
if (req.method == "POST")
{
// verify correct content-type
if (string::strcasecmp(content_type, "application/json"))
throw Exception("bad content-type");
// parse the json dict
const Json::Value root = json::parse(in.to_string(), "JSON request");
if (!root.isObject())
throw Exception("json parse error: top level json object is not a dictionary");
if (req.uri == "/tun-setup")
{
send_fd.reset();
// get PID
pid_t pid = json::get_int_optional(root, "pid", -1);
if (pid != -1)
parent()->set_watchdog(pid);
// parse JSON data into a TunBuilderCapture object
TunBuilderCapture::Ptr tbc = TunBuilderCapture::from_json(json::get_dict(root, "tun", false));
tbc->validate();
// get config
TunMac::Setup::Config config;
config.from_json(json::get_dict(root, "config", false), "config");
// establish the tun setup object
send_fd = parent()->establish_tun(*tbc, &config, nullptr, os);
// build JSON return dictionary
Json::Value jout(Json::objectValue);
jout["log_txt"] = Json::Value(string::remove_blanks(os.str()));
jout["config"] = config.to_json();
generate_reply(jout);
}
else if (req.uri == "/add-bypass-route")
{
pid_t pid = json::get_int_optional(root, "pid", -1);
if (pid != -1)
parent()->set_watchdog(pid);
bool ipv6 = json::get_bool(root, "ipv6");
std::string host = json::get_string(root, "host");
parent()->add_bypass_route(host, ipv6);
Json::Value jout(Json::objectValue);
generate_reply(jout);
}
}
else if (req.method == "GET" && req.uri == "/tun-destroy")
{
// destroy tun object
parent()->destroy_tun(os);
// build JSON return dictionary
Json::Value jout(Json::objectValue);
jout["log_txt"] = Json::Value(string::remove_blanks(os.str()));
generate_reply(jout);
}
else
{
out = buf_from_string("page not found\n");
WS::Server::ContentInfo ci;
ci.http_status = HTTP::Status::NotFound;
ci.type = "text/plain";
ci.length = out->size();
generate_reply_headers(ci);
}
}
catch (const std::exception& e)
{
out = buf_from_string(string::remove_blanks(os.str() + e.what() + '\n'));
WS::Server::ContentInfo ci;
ci.http_status = HTTP::Status::BadRequest;
ci.type = "text/plain";
ci.length = out->size();
generate_reply_headers(ci);
}
}
virtual void http_content_in(BufferAllocated& buf) override
{
if (buf.defined())
in.emplace_back(new BufferAllocated(std::move(buf)));
}
virtual BufferPtr http_content_out() override
{
BufferPtr ret;
ret.swap(out);
return ret;
}
// Normally true is returned, however return false if we
// are planning to send the tun file descriptor to the client.
virtual bool http_out_eof() override
{
//OPENVPN_LOG("HTTP output EOF send_fd=" << send_fd());
return !send_fd.defined();
}
// After HTTP reply has been transmitted, wait for client to
// send a 't' message. On receipt, reply with a 'T' message
// that bundles the tun file descriptor.
virtual void http_pipeline_peek(BufferAllocated& buf) override
{
//OPENVPN_LOG("HTTP PIPELINE PEEK send_fd=" << send_fd() << " CONTENT=" << buf_to_string(buf));
if (send_fd.defined())
{
if (buf.size() == 1 && buf.front() == 't')
{
const int fd = unix_fd();
if (fd < 0)
OPENVPN_THROW_EXCEPTION("http_pipeline_peek: not a unix socket");
XmitFD::xmit_fd(fd, send_fd(), "T", 5000);
external_stop("FD transmitted");
}
else
OPENVPN_THROW_EXCEPTION("bad FD request message");
}
}
virtual bool http_stop(const int status, const std::string& description) override
{
OPENVPN_LOG("INSTANCE STOP : " << WS::Server::Status::error_str(status) << " : " << description);
// if the shutdown happened due to an unexpected error, the TUN status has
// to be cleaned up to avoid configuration inconsistency.
//
// A problem we have witnessed was that the DNS settings were not being
// reverted when the HTTP connection with the core was interrupted in the
// middle of the establish() call.
if (status != WS::Server::Status::E_SUCCESS &&
status != WS::Server::Status::E_EXTERNAL_STOP)
{
std::ostringstream os;
parent()->destroy_tun(os);
}
// returning true here triggers socket shutdown, which triggers "Socket is not connected" error
return false;
}
MyListener* parent()
{
return static_cast<MyListener*>(get_parent());
}
ScopedFD send_fd;
BufferList in;
BufferPtr out;
};
class MyClientFactory : public WS::Server::Listener::Client::Factory
{
public:
typedef RCPtr<MyClientFactory> Ptr;
virtual WS::Server::Listener::Client::Ptr new_client(WS::Server::Listener::Client::Initializer& ci) override
{
return new MyClientInstance(ci);
}
};
class ServerThread : public ServerThreadBase
{
public:
typedef RCPtr<ServerThread> Ptr;
ServerThread(openvpn_io::io_context& io_context_arg,
ThreadCommon& tc)
: io_context(io_context_arg),
halt(false)
{
Frame::Ptr frame = frame_init_simple(2048);
WS::Server::Config::Ptr config = new WS::Server::Config();
config->http_server_id = OVPNAGENT_NAME_STRING "/" HTTP_SERVER_VERSION;
config->frame = frame;
config->stats = tc.stats;
config->unix_mode = 0777;
MyClientFactory::Ptr factory = new MyClientFactory();
listener.reset(new MyListener(io_context_arg, config, tc.listen_list, factory));
}
void start()
{
if (!halt)
{
listener->start();
}
}
void stop()
{
if (!halt)
{
halt = true;
listener->stop();
listener->unset_watchdog();
}
}
virtual void thread_safe_stop() override
{
if (!halt)
{
openvpn_io::post(io_context, [self=Ptr(this)]()
{
self->stop();
});
}
}
private:
openvpn_io::io_context& io_context;
MyListener::Ptr listener;
bool halt;
};
typedef RunContext<ServerThreadBase, MySessionStats> MyRunContext;
void work(openvpn_io::io_context& io_context,
ThreadCommon& tc,
MyRunContext& runctx,
const unsigned int unit)
{
ServerThread::Ptr serv;
try {
serv.reset(new ServerThread(io_context, tc));
runctx.set_server(unit, serv.get());
serv->start();
// barrier prior to event-loop entry
event_loop_wait_barrier(tc);
// privilege has now been downgraded
// run i/o reactor
io_context.run();
runctx.clear_server(unit);
serv->stop();
}
catch (...)
{
tc.event_loop_bar.error();
if (serv)
{
runctx.clear_server(unit);
serv->stop(); // on exception, stop server
}
io_context.poll(); // execute completion handlers
throw;
}
}
void worker_thread(ThreadCommon& tc,
MyRunContext& runctx,
const unsigned int unit)
{
SignalBlockerDefault signal_blocker;
openvpn_io::io_context io_context(1); // concurrency hint=1
Log::Context log_context(runctx.log_wrapper());
MyRunContext::ThreadContext thread_ctx(runctx);
try {
work(io_context, tc, runctx, unit);
}
catch (const std::exception& e)
{
OPENVPN_LOG("Worker thread exception: " << e.what());
}
}
int ovpnagent(const char *sock_fn,
const char *log_fn,
const bool log_append,
const char *pid_fn,
const char *user,
const char *group)
{
if (log_fn)
daemonize(log_fn, nullptr, log_append, 0);
if (pid_fn)
write_pid(pid_fn);
log_version();
MyRunContext::Ptr runctx(new MyRunContext());
ThreadCommon tc(sock_fn, user, group);
// Give runctx visibility into global stats
// for SIGUSR2 dump.
runctx->set_stats_obj(tc.stats);
// Main worker thread
{
const unsigned int thread_num = 0;
std::thread* thread = new std::thread([&tc, &runctx]() {
worker_thread(tc, *runctx, thread_num);
});
runctx->set_thread(thread_num, thread);
}
// wait for worker to exit
runctx->run();
runctx->join();
// dump final stats
OPENVPN_LOG_NTNL(tc.stats->dump());
// remove pidfile
if (pid_fn)
::unlink(pid_fn);
return 0;
}
OPENVPN_SIMPLE_EXCEPTION(usage);
int main(int argc, char* argv[])
{
static const struct option longopts[] = {
{ "help", no_argument, nullptr, 'h' },
{ "append", no_argument, nullptr, 'a' },
{ "daemon", required_argument, nullptr, 'd' },
{ "pidfile", required_argument, nullptr, 'p' },
{ "user", required_argument, nullptr, 'u' },
{ "group", required_argument, nullptr, 'g' },
{ nullptr, 0, nullptr, 0 }
};
int ret = 0;
bool append = false;
const char *logfile = nullptr;
const char *pidfile = nullptr;
const char *user = nullptr;
const char *group = nullptr;
// process-wide initialization
InitProcess::Init init;
// set global MbedTLS debug level
#if defined(USE_MBEDTLS) && defined(OPENVPN_SSL_DEBUG)
debug_set_threshold(OPENVPN_SSL_DEBUG);
#endif
try {
if (argc < 1)
throw usage();
int ch;
while ((ch = getopt_long(argc, argv, "had:p:u:g:", longopts, nullptr)) != -1)
{
switch (ch)
{
case 'a':
append = true;
break;
case 'd':
logfile = optarg;
break;
case 'p':
pidfile = optarg;
break;
case 'u':
user = optarg;
break;
case 'g':
group = optarg;
break;
default:
throw usage();
}
}
argc -= optind;
argv += optind;
ret = ovpnagent("/var/run/" OVPNAGENT_NAME_STRING ".sock", logfile, append, pidfile, user, group);
}
catch (const usage&)
{
log_version();
std::cout << "usage: ovpnagent [options]" << std::endl;
std::cout << " --daemon <file>, -d : daemonize, log to file" << std::endl;
std::cout << " --append, -a : append to log file" << std::endl;
std::cout << " --pidfile <file>, -p : write pid to file" << std::endl;
std::cout << " --user <user>, -u : set UID to user" << std::endl;
std::cout << " --group <group>, -g : set group" << std::endl;
ret = 2;
}
catch (const std::exception& e)
{
std::cout << "Main thread exception: " << e.what() << std::endl;
ret = 1;
}
return ret;
}

View File

@@ -0,0 +1,9 @@
if [ "$1" = "args" ]; then
echo " JSON=1 -- build with JsonCpp library"
elif [ "$1" = "deps" ]; then
# JsonCpp
if [ "$JSON" = "1" ]; then
CPPFLAGS="$CPPFLAGS $(pkg-config --cflags jsoncpp) -DHAVE_JSONCPP"
EXTRA_SRC_OBJ="$EXTRA_SRC_OBJ $(pkg-config --libs jsoncpp)"
fi
fi

View File

@@ -5,7 +5,7 @@ if [ -z "$O3" ]; then
echo O3 var must point to ovpn3 tree ; exit 1
fi
cd $DEP_DIR
rm -rf asio* boost* lz4* lzo* minicrypto openssl* polarssl* mbedtls* snappy*
rm -rf asio* boost* lz4* lzo* minicrypto openssl* polarssl* mbedtls* snappy* jsoncpp*
echo "******* ASIO"
$O3/core/deps/asio/build-asio
@@ -33,6 +33,9 @@ $O3/core/scripts/mac/build-lz4
echo "******* xxHash"
$O3/core/deps/xxHash/build-xxHash
echo "******* JSONCPP"
$O3/core/scripts/mac/build-jsoncpp
#echo "******* MINICRYPTO"
#$O3/core/scripts/mac/build-minicrypto

28
scripts/mac/build-jsoncpp Executable file
View File

@@ -0,0 +1,28 @@
#!/usr/bin/env bash
set -e
if [ -z "$O3" ]; then
echo O3 var must point to ovpn3 tree
exit 1
fi
if [ -z "$DEP_DIR" ]; then
echo DEP_DIR var must point to ovpn3 dependency tree
exit 1
fi
cd $DEP_DIR
rm -rf jsoncpp
mkdir jsoncpp
if [ "$OSX_ONLY" != "1" ]; then
for target in ios ios-dbg iossim iossim-dbg ; do
echo '***************' TARGET $target
TARGET=$target $O3/core/deps/jsoncpp/build-jsoncpp
done
fi
for target in osx osx-dbg ; do
echo '***************' TARGET $target
TARGET=$target $O3/core/deps/jsoncpp/build-jsoncpp
done
exit 0

View File

@@ -39,7 +39,6 @@ if (${CLI_OVPNDCO})
endif()
if (WIN32)
# for macos, agent-enabled client requires common and is built by scripts there
add_executable(ovpncliagent cli.cpp)
add_core_dependencies(ovpncliagent)
add_json_library(ovpncliagent)
@@ -56,3 +55,10 @@ if (WIN32)
target_include_directories(ovpncli PRIVATE ${OVPN_DCO_WIN_INCLUDE_DIRS})
endif()
endif ()
if (APPLE)
add_executable(ovpncliagent cli.cpp)
add_core_dependencies(ovpncliagent)
add_json_library(ovpncliagent)
target_compile_definitions(ovpncliagent PRIVATE -DOPENVPN_COMMAND_AGENT)
endif ()