add initial jni stuff for lokinet android. i fucking hate android so god damn much.

pull/155/head
Jeff Becker 6 years ago
parent b323665140
commit 7e4d74cbfc
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05

@ -50,7 +50,9 @@ endif(WIN32)
if(DEBIAN)
add_definitions(-DDEBIAN)
else()
set(CRYPTO_FLAGS -march=native)
if( NOT ANDROID)
set(CRYPTO_FLAGS -march=native)
endif()
endif()
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)

@ -165,6 +165,7 @@ android-gradle: android-gradle-prepare
cd $(ANDROID_DIR) && JAVA_HOME=$(JAVA_HOME) $(GRADLE) clean assemble
android: android-gradle
cp -f $(ANDROID_DIR)/build/outputs/apk/*.apk $(REPO)
windows-configure: clean
mkdir -p '$(BUILD_ROOT)'

@ -13,7 +13,8 @@
<uses-permission android:name="android.permission.INTERNET" /> <!-- normal perm, per https://developer.android.com/guide/topics/permissions/normal-permissions.html -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- normal perm -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- normal perm -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application
android:allowBackup="true"
@ -26,9 +27,9 @@
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
<activity
android:name=".PermsAskerActivity"
android:name=".LokiNetActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@ -36,22 +37,14 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".LokiNetActivity"
android:label="@string/app_name" />
<service
android:name=".ForegroundService"
android:enabled="true" />
<activity
android:name=".PermsExplanationActivity"
android:label="@string/title_activity_perms_asker_prompt"
android:parentActivityName=".PermsAskerActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="network.loki.lokinet.PermsAskerActivity" />
</activity>
<service android:name=".LokinetService"
android:enabled="true"
android:exported="true"
android:permission="android.permission.BIND_VPN_SERVICE">
<intent-filter>
<action android:name="android.net.VpnService"/>
</intent-filter>
</service>
</application>
</manifest>

@ -34,6 +34,7 @@ android {
cmake {
targets "lokinetandroid"
arguments "-DANDROID=ON", "-DANDROID_STL=c++_static"
cppFlags "-fexceptions"
}
}
packagingOptions{

@ -22,6 +22,6 @@
android:id="@+id/button_request_write_ext_storage_perms"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Retry requesting the SD card write permissions"
android:text="Retry requesting VPN"
android:visibility="gone"/>
</LinearLayout>

@ -15,7 +15,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/horizontal_page_margin"
android:text="SD card write access is required to write the keys and other files on an SD card."
android:text="VPN permissions are required for lokinet usage."
/>
<Button

@ -12,4 +12,8 @@
<string name="stopped">lokinet has stopped</string>
<string name="remaining">remaining</string>
<string name="title_activity_perms_asker_prompt">Prompt</string>
<string name="bootstrap_ok">got bootstrap node info</string>
<string name="bootstrap_fail">failed to bootstrap</string>
<string name="netdb_create_fail">failed to create netdb directory</string>
<string name="vpn_setup_fail">failed to set up vpn tunnel</string>
</resources>

@ -35,6 +35,8 @@ public class LokiNetActivity extends Activity {
private TextView textView;
private static final String DefaultBootstrapURL = "https://i2p.rocks/bootstrap.signed";
private AsyncBootstrap bootstrapper;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@ -65,14 +67,18 @@ public class LokiNetActivity extends Activity {
}
}
public void startLokinet() {
public void startLokinet()
{
if(bootstrapper != null)
return;
bootstrapper = new AsyncBootstrap();
bootstrapper.execute(DefaultBootstrapURL);
}
public void runLokinetService()
{
bindService(new Intent(LokiNetActivity.this,
ForegroundService.class), mConnection, Context.BIND_AUTO_CREATE);
startService(new Intent(LokiNetActivity.this,
LokinetService.class));
}
@Override
@ -81,29 +87,41 @@ public class LokiNetActivity extends Activity {
textView = null;
}
public File getRootDir()
{
return getFilesDir();
}
private class AsyncBootstrap extends AsyncTask<String, String, String>
{
public String doInBackground(String ... urls) {
try
{
File bootstrapFile = new File(getCacheDir(), "bootstrap.signed");
File bootstrapFile = new File(getRootDir(), "bootstrap.signed");
URL bootstrapURL = new URL(urls[0]);
InputStream instream = bootstrapURL.openStream();
writeFile(bootstrapFile, instream);
instream.close();
return "downloaded";
return getString(R.string.bootstrap_ok);
}
catch(Exception thrown)
{
return thrown.getLocalizedMessage();
return getString(R.string.bootstrap_fail) + ": " + throwableToString(thrown);
}
}
public void onPostExecute(String val) {
final File configFile = new File(getCacheDir(), "daemon.ini");
runLokinetService();
textView.setText(val);
if(val.equals(getString(R.string.bootstrap_ok)))
runLokinetService();
bootstrapDone();
}
}
private void bootstrapDone()
{
bootstrapper = null;
}
private CharSequence throwableToString(Throwable tr) {
StringWriter sw = new StringWriter(8192);
PrintWriter pw = new PrintWriter(sw);
@ -112,33 +130,6 @@ public class LokiNetActivity extends Activity {
return sw.toString();
}
private ForegroundService boundService;
// private LocalService mBoundService;
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
// This is called when the connection with the service has been
// established, giving us the service object we can use to
// interact with the service. Because we have bound to a explicit
// service that we know is running in our own process, we can
// cast its IBinder to a concrete class and directly access it.
boundService = ((ForegroundService.LocalBinder)service).getService();
textView.setText(R.id.loaded);
// Tell the user about this for our demo.
// Toast.makeText(Binding.this, R.string.local_service_connected,
// Toast.LENGTH_SHORT).show();
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
// Because it is running in our same process, we should never
// see this happen.
// mBoundService = null;
// Toast.makeText(Binding.this, R.string.local_service_disconnected,
// Toast.LENGTH_SHORT).show();
}
};
@Override
@ -160,7 +151,6 @@ public class LokiNetActivity extends Activity {
startLokinet();
return true;
case R.id.action_stop:
Lokinet_JNI.stopLokinet();
return true;
}

@ -17,11 +17,23 @@ public class Lokinet_JNI {
*/
public static native void stopLokinet();
/** get interface address we want */
public static native String getIfAddr();
/** get interface address range we want */
public static native int getIfRange();
/**
* change network status
*/
public static native void onNetworkStateChanged(boolean isConnected);
/**
* set vpn network interface fd
* @param fd the file descriptor of the vpn interface
*/
public static native void setVPNFileDescriptor(int fd);
/**
* load jni libraries
*/

@ -15,21 +15,22 @@ import java.lang.reflect.Method;
//android.permission.WRITE_EXTERNAL_STORAGE
public class PermsAskerActivity extends Activity {
private static final int PERMISSION_WRITE_EXTERNAL_STORAGE = 0;
private static final int PERMISSION_VPN = 0;
private Button button_request_write_ext_storage_perms;
private TextView textview_retry;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startMainActivity();
/*
//if less than Android 6, no runtime perms req system present
if (android.os.Build.VERSION.SDK_INT < 23) {
startMainActivity();
return;
}
setContentView(R.layout.activity_perms_asker);
button_request_write_ext_storage_perms = (Button) findViewById(R.id.button_request_write_ext_storage_perms);
textview_retry = (TextView) findViewById(R.id.textview_retry);
@ -41,6 +42,7 @@ public class PermsAskerActivity extends Activity {
}
});
request_write_ext_storage_perms();
*/
}
private void request_write_ext_storage_perms() {
@ -63,7 +65,7 @@ public class PermsAskerActivity extends Activity {
Integer resultObj;
try {
resultObj = (Integer) methodCheckPermission.invoke(
this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
this, Manifest.permission.BIND_VPN_SERVICE);
} catch (Throwable e) {
throw new RuntimeException(e);
}
@ -74,7 +76,7 @@ public class PermsAskerActivity extends Activity {
Boolean aBoolean;
try {
aBoolean = (Boolean) method_shouldShowRequestPermissionRationale.invoke(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE);
Manifest.permission.BIND_VPN_SERVICE);
} catch (Exception e) {
throw new RuntimeException(e);
}
@ -92,8 +94,8 @@ public class PermsAskerActivity extends Activity {
try {
method_requestPermissions.invoke(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
PERMISSION_WRITE_EXTERNAL_STORAGE);
new String[]{Manifest.permission.BIND_VPN_SERVICE},
PERMISSION_VPN);
} catch (Exception e) {
throw new RuntimeException(e);
}
@ -105,7 +107,7 @@ public class PermsAskerActivity extends Activity {
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_WRITE_EXTERNAL_STORAGE: {
case PERMISSION_VPN: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
@ -119,7 +121,7 @@ public class PermsAskerActivity extends Activity {
// permission denied, boo! Disable the
// functionality that depends on this permission.
textview_retry.setText("SD card write permission denied, you need to allow this to continue");
textview_retry.setText("you need to allow this to continue");
textview_retry.setVisibility(TextView.VISIBLE);
button_request_write_ext_storage_perms.setVisibility(Button.VISIBLE);
}
@ -158,8 +160,8 @@ public class PermsAskerActivity extends Activity {
}
try {
method_requestPermissions.invoke(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
PERMISSION_WRITE_EXTERNAL_STORAGE);
new String[]{Manifest.permission.BIND_VPN_SERVICE},
PERMISSION_VPN);
} catch (Exception e) {
throw new RuntimeException(e);
}

@ -35,6 +35,10 @@ extern "C"
void
llarp_main_signal(struct llarp_main *ptr, int sig);
/// give main context a vpn file descriptor (android/ios)
void
llarp_main_inject_vpn_fd(struct llarp_main * m, int fd);
/// setup main context
int
llarp_main_setup(struct llarp_main *ptr);

@ -29,7 +29,7 @@
#define PQ_CIPHERTEXTSIZE crypto_kem_CIPHERTEXTBYTES
#define PQ_PUBKEYSIZE crypto_kem_PUBLICKEYBYTES
#define PQ_SECRETKEYSIZE crypto_kem_SECRETKEYBYTES
#define PQ_KEYPAIRSIZE (PQ_SECRETKEYSIZE + PQ_SECRETKEYSIZE)
#define PQ_KEYPAIRSIZE (PQ_SECRETKEYSIZE + PQ_PUBKEYSIZE)
/// label functors

@ -166,6 +166,14 @@ llarp_tcp_acceptor_close(struct llarp_tcp_acceptor *);
#define IFNAMSIZ (16)
#endif
struct llarp_fd_promise;
/// wait until the fd promise is set
int
llarp_fd_promise_wait_for_value(struct llarp_fd_promise * promise);
struct llarp_tun_io
{
// TODO: more info?
@ -175,6 +183,11 @@ struct llarp_tun_io
void *user;
void *impl;
/// functor for getting a promise that returns the vpn fd
/// dont set me if you don't know how to use this
struct llarp_fd_promise * (*get_fd_promise)(struct llarp_tun_io *);
struct llarp_ev_loop *parent;
/// called when we are able to write right before we write
/// this happens after reading packets
@ -189,6 +202,7 @@ struct llarp_tun_io
bool
llarp_ev_add_tun(struct llarp_ev_loop *ev, struct llarp_tun_io *tun);
/// async write a packet on tun interface
/// returns true if queued, returns false on drop
bool

@ -13,6 +13,7 @@ namespace llarp
{
namespace handlers
{
static const int DefaultTunNetmask = 16;
static const char DefaultTunIfname[] = "lokinet0";
static const char DefaultTunDstAddr[] = "10.10.0.1";
@ -73,6 +74,7 @@ namespace llarp
#endif
llarp_tun_io tunif;
std::unique_ptr<llarp_fd_promise> Promise;
/// called before writing to tun interface
static void
@ -168,6 +170,9 @@ namespace llarp
/// up interface
std::promise< bool > m_TunSetupResult;
#endif
std::promise<int> m_VPNPromise;
/// DNS server per tun
struct dnsd_context dnsd;
/// DNS loki lookup subsystem configuration (also holds optional iptracker

@ -21,7 +21,7 @@ llarp_free_router(struct llarp_router **router);
bool
llarp_configure_router(struct llarp_router *router, struct llarp_config *conf);
void
bool
llarp_run_router(struct llarp_router *router, struct llarp_nodedb *nodedb);
void

@ -137,6 +137,10 @@ extern "C"
struct device
{
/** set me on ios and android to block on a promise for the fd */
int (*obtain_fd)(struct device *);
/** user data */
void * user;
t_tun tun_fd;
int ctrl_sock;
int flags; /* ifr.ifr_flags on Unix */

@ -26,7 +26,7 @@ struct AndroidMain
bool
ReloadConfig()
{
if(!m_Impl)
if(!m_impl)
return false;
llarp_main_signal(m_impl, SIGHUP);
return true;
@ -41,6 +41,12 @@ struct AndroidMain
m_impl = llarp_main_init(configFile.c_str(), true);
if(m_impl == nullptr)
return false;
if(llarp_main_setup(m_impl))
{
llarp_main_free(m_impl);
m_impl = nullptr;
return false;
}
m_thread = new std::thread(std::bind(&AndroidMain::Run, this));
return true;
}
@ -56,18 +62,57 @@ struct AndroidMain
void
Run()
{
llarp_main_run(m_impl);
if(llarp_main_run(m_impl))
{
// on error
llarp::LogError("daemon run fail");
llarp_main * ptr = m_impl;
m_impl = nullptr;
llarp_main_signal(ptr, SIGINT);
llarp_main_free(ptr);
}
}
const char * GetIfAddr()
{
if(m_impl)
{
auto tun = main_router_getFirstTunEndpoint(m_impl);
if(tun)
return tun->tunif.ifaddr;
}
return "";
}
int GetIfRange() const
{
if(m_impl)
{
auto tun = main_router_getFirstTunEndpoint(m_impl);
if(tun)
return tun->tunif.netmask;
}
return -1;
}
void
SetVPN_FD(int fd)
{
if(m_impl)
llarp_main_inject_vpn_fd(m_impl, fd);
}
/// stop daemon thread
void
Stop()
{
llarp_main_signal(m_impl, SIGINT);
if(m_impl)
llarp_main_signal(m_impl, SIGINT);
m_thread->join();
delete m_thread;
m_thread = nullptr;
llarp_main_free(m_impl);
if(m_impl)
llarp_main_free(m_impl);
m_impl = nullptr;
}
@ -86,7 +131,7 @@ extern "C"
}
JNIEXPORT jstring JNICALL
Java_network_loki_lokinet_Lokinet_1JNI_startLokinet(JNIEnv* env, jclass jcl,
Java_network_loki_lokinet_Lokinet_1JNI_startLokinet(JNIEnv* env, jclass,
jstring configfile)
{
if(daemon->Running())
@ -107,17 +152,41 @@ extern "C"
return env->NewStringUTF("failed to start daemon");
}
else
return ev->NewStringUTF("failed to configure daemon");
return env->NewStringUTF("failed to configure daemon");
}
JNIEXPORT void JNICALL
Java_network_loki_lokinet_Lokinet_1JNI_stopLokinet(JNIEnv* env, jclass)
Java_network_loki_lokinet_Lokinet_1JNI_stopLokinet(JNIEnv*, jclass)
{
if(daemon->Running())
{
daemon->Stop();
}
}
JNIEXPORT void JNICALL
Java_network_loki_lokinet_Lokinet_1JNI_setVPNFileDescriptor(JNIEnv*, jclass, jint fd)
{
daemon->SetVPN_FD(fd);
}
JNIEXPORT jstring JNICALL Java_network_loki_lokinet_Lokinet_1JNI_getIfAddr
(JNIEnv * env, jclass)
{
if(daemon)
return env->NewStringUTF(daemon->GetIfAddr());
else
return env->NewStringUTF("");
}
JNIEXPORT jint JNICALL Java_network_loki_lokinet_Lokinet_1JNI_getIfRange
(JNIEnv *, jclass)
{
if(daemon)
return daemon->GetIfRange();
else
return -1;
}
JNIEXPORT void JNICALL
Java_network_loki_lokinet_Lokinet_1JNI_onNetworkStateChanged(JNIEnv*, jclass,

@ -23,6 +23,12 @@ JNIEXPORT jstring JNICALL Java_network_loki_lokinet_Lokinet_1JNI_getABICompiledW
JNIEXPORT jstring JNICALL Java_network_loki_lokinet_Lokinet_1JNI_startLokinet
(JNIEnv *, jclass, jstring);
JNIEXPORT jstring JNICALL Java_network_loki_lokinet_Lokinet_1JNI_getIfAddr
(JNIEnv *, jclass);
JNIEXPORT jint JNICALL Java_network_loki_lokinet_Lokinet_1JNI_getIfRange
(JNIEnv *, jclass);
/*
* Class: network_loki_lokinet_Lokinet_JNI
* Method: stopLokinet
@ -31,6 +37,9 @@ JNIEXPORT jstring JNICALL Java_network_loki_lokinet_Lokinet_1JNI_startLokinet
JNIEXPORT void JNICALL Java_network_loki_lokinet_Lokinet_1JNI_stopLokinet
(JNIEnv *, jclass);
JNIEXPORT void JNICALL Java_network_loki_lokinet_Lokinet_1JNI_setVPNFileDescriptor
(JNIEnv *, jclass, jint);
/*
* Class: network_loki_lokinet_Lokinet_JNI
* Method: onNetworkStateChanged

@ -327,6 +327,7 @@ interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList)
l_rta = RTA_NEXT(l_rta, l_rtaSize))
{
void *l_rtaData = RTA_DATA(l_rta);
(void) l_rtaData;
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
switch(l_rta->rta_type)
{
@ -454,6 +455,7 @@ interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList,
l_rta = RTA_NEXT(l_rta, l_rtaSize))
{
void *l_rtaData = RTA_DATA(l_rta);
(void) l_rtaData;
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
switch(l_rta->rta_type)

@ -164,7 +164,11 @@ llarp_generic_ensure_config(std::ofstream &f, std::string basepath)
// will this break reproducibility rules?
// (probably)
#ifdef __linux__
#ifdef ANDROID
f << "bind=127.0.0.1:1153" << std::endl;
#else
f << "bind=127.3.2.1:53" << std::endl;
#endif
#else
f << "bind=127.0.0.1:53" << std::endl;
#endif

@ -13,6 +13,8 @@
#include <pthread_np.h>
#endif
#include "ev.hpp"
namespace llarp
{
Context::~Context()
@ -154,10 +156,7 @@ namespace llarp
llarp::LogError("Failed to configure router");
return 1;
}
// set nodedb, load our RC, establish DHT
llarp_run_router(router, nodedb);
return 0; // success
return 0;
}
int
@ -174,7 +173,9 @@ namespace llarp
return 1;
}
}
// run
if(!llarp_run_router(router, nodedb))
return 1; // success
// run net io thread
llarp::LogInfo("running mainloop");
llarp_ev_loop_run_single_process(mainloop, worker, logic);
@ -296,6 +297,17 @@ extern "C"
ptr->ctx->HandleSignal(sig);
}
void
llarp_main_inject_vpn_fd(struct llarp_main * ptr, int fd)
{
llarp::handlers::TunEndpoint * tun = ptr->ctx->router->hiddenServiceContext.getFirstTun();
if(!tun)
return;
if(!tun->Promise)
return;
tun->Promise->Set(fd);
}
int
llarp_main_setup(struct llarp_main *ptr)
{
@ -308,7 +320,7 @@ extern "C"
if(!ptr)
{
llarp::LogError("No ptr passed in");
return 0;
return 1;
}
return ptr->ctx->Run();
}
@ -448,8 +460,8 @@ extern "C"
main_router_mapAddress(struct llarp_main *ptr,
const llarp::service::Address &addr, uint32_t ip)
{
auto *endpoint = &ptr->ctx->router->hiddenServiceContext;
return endpoint->MapAddress(addr, llarp::huint32_t{ip});
auto &endpoint = ptr->ctx->router->hiddenServiceContext;
return endpoint.MapAddress(addr, llarp::huint32_t{ip});
}
bool
@ -463,8 +475,9 @@ extern "C"
llarp::handlers::TunEndpoint *
main_router_getFirstTunEndpoint(struct llarp_main *ptr)
{
auto *context = &ptr->ctx->router->hiddenServiceContext;
return context->getFirstTun();
if(ptr && ptr->ctx && ptr->ctx->router)
return ptr->ctx->router->hiddenServiceContext.getFirstTun();
return nullptr;
}
//#include <llarp/service/context.hpp>

@ -20,6 +20,7 @@
#error No async event loop for your platform, subclass llarp_ev_loop
#endif
void
llarp_ev_loop_alloc(struct llarp_ev_loop **ev)
{
@ -57,6 +58,11 @@ llarp_ev_loop_run(struct llarp_ev_loop *ev, struct llarp_logic *logic)
return 0;
}
int llarp_fd_promise_wait_for_value(struct llarp_fd_promise * p)
{
return p->Get();
}
void
llarp_ev_loop_run_single_process(struct llarp_ev_loop *ev,
struct llarp_threadpool *tp,

@ -14,6 +14,8 @@
#ifdef _WIN32
#include <variant>
#else
#include <sys/un.h>
#endif
#ifndef MAX_WRITE_QUEUE_SIZE
@ -608,6 +610,24 @@ namespace llarp
}; // namespace llarp
struct llarp_fd_promise
{
llarp_fd_promise(std::promise<int> * p) : _impl(p) {}
std::promise<int> * _impl;
void Set(int fd)
{
_impl->set_value(fd);
}
int Get()
{
auto future = _impl->get_future();
future.wait();
return future.get();
}
};
// this (nearly!) abstract base class
// is overriden for each platform
struct llarp_ev_loop

@ -224,26 +224,46 @@ namespace llarp
return ret;
}
static int wait_for_fd_promise(struct device * dev)
{
llarp::tun *t = static_cast<llarp::tun *>(dev->user);
if(t->t->get_fd_promise)
{
struct llarp_fd_promise * promise = t->t->get_fd_promise(t->t);
if(promise)
return llarp_fd_promise_wait_for_value(promise);
}
return -1;
}
bool
setup()
{
// for android
if(t->get_fd_promise)
{
tunif->obtain_fd = &wait_for_fd_promise;
tunif->user = this;
}
llarp::LogDebug("set ifname to ", t->ifname);
strncpy(tunif->if_name, t->ifname, sizeof(tunif->if_name));
if(tuntap_start(tunif, TUNTAP_MODE_TUNNEL, 0) == -1)
{
llarp::LogWarn("failed to start interface");
return false;
}
if(tuntap_up(tunif) == -1)
if(t->get_fd_promise == nullptr)
{
llarp::LogWarn("failed to put interface up: ", strerror(errno));
return false;
}
if(tuntap_set_ip(tunif, t->ifaddr, t->ifaddr, t->netmask) == -1)
{
llarp::LogWarn("failed to set ip");
return false;
if(tuntap_up(tunif) == -1)
{
llarp::LogWarn("failed to put interface up: ", strerror(errno));
return false;
}
if(tuntap_set_ip(tunif, t->ifaddr, t->ifaddr, t->netmask) == -1)
{
llarp::LogWarn("failed to set ip");
return false;
}
}
fd = tunif->tun_fd;
if(fd == -1)
@ -257,6 +277,8 @@ namespace llarp
~tun()
{
if(tunif)
tuntap_destroy(tunif);
}
};
}; // namespace llarp
@ -485,7 +507,10 @@ struct llarp_epoll_loop : public llarp_ev_loop
create_tun(llarp_tun_io* tun)
{
llarp::tun* t = new llarp::tun(tun, this);
if(t->setup())
if(tun->get_fd_promise)
{
} else if(t->setup())
{
return t;
}

@ -23,7 +23,7 @@ namespace llarp
ExitEndpoint::ExitEndpoint(const std::string &name, llarp_router *r)
: m_Router(r)
, m_Name(name)
, m_Tun{{0}, 0, {0}, 0, 0, 0, 0, 0, 0}
, m_Tun{{0}, 0, {0}, 0, 0, 0, 0, 0, 0, 0}
, m_InetToNetwork(name + "_exit_rx", r->netloop, r->netloop)
{

@ -8,16 +8,29 @@
#include <sys/socket.h>
#include <netdb.h>
#endif
#include "ev.hpp"
namespace llarp
{
namespace handlers
{
static llarp_fd_promise * get_tun_fd_promise(llarp_tun_io * tun)
{
return static_cast<TunEndpoint *>(tun->user)->Promise.get();
}
TunEndpoint::TunEndpoint(const std::string &nickname, llarp_router *r)
: service::Endpoint(nickname, r)
, m_UserToNetworkPktQueue(nickname + "_sendq", r->netloop, r->netloop)
, m_NetworkToUserPktQueue(nickname + "_recvq", r->netloop, r->netloop)
{
#ifdef ANDROID
tunif.get_fd_promise = &get_tun_fd_promise;
Promise.reset(new llarp_fd_promise(&m_VPNPromise));
#else
tunif.get_fd_promise = nullptr;
#endif
tunif.user = this;
tunif.netmask = DefaultTunNetmask;
strncpy(tunif.ifaddr, DefaultTunSrcAddr, sizeof(tunif.ifaddr) - 1);

@ -703,7 +703,7 @@ llarp_router::async_verify_RC(const llarp::RouterContact &rc,
llarp_nodedb_async_verify(job);
}
void
bool
llarp_router::Run()
{
if(enableRPCServer)
@ -807,12 +807,12 @@ llarp_router::Run()
if(!_rc.Sign(&crypto, identity))
{
llarp::LogError("failed to sign rc");
return;
return false;
}
if(!SaveRC())
{
return;
return false;
}
llarp::LogInfo("have ", llarp_nodedb_num_loaded(nodedb), " routers");
@ -821,6 +821,7 @@ llarp_router::Run()
if(!outboundLink->Start(logic))
{
llarp::LogWarn("outbound link failed to start");
return false;
}
int IBLinksStarted = 0;
@ -844,8 +845,7 @@ llarp_router::Run()
if(!InitServiceNode())
{
llarp::LogError("Failed to initialize service node");
Close();
return;
return false;
}
delay = llarp_randint() % 50;
}
@ -860,16 +860,14 @@ llarp_router::Run()
if(!_rc.Sign(&crypto, identity))
{
llarp::LogError("failed to regenerate keys and sign RC");
Close();
return;
return false;
}
// generate default hidden service
llarp::LogInfo("setting up default network endpoint");
if(!CreateDefaultHiddenService())
{
llarp::LogError("failed to set up default network endpoint");
Close();
return;
return false;
}
}
@ -877,8 +875,7 @@ llarp_router::Run()
if(!hiddenServiceContext.StartAll())
{
llarp::LogError("Failed to start hidden service context");
Close();
return;
return false;
}
llarp::PubKey ourPubkey = pubkey();
llarp::LogInfo("starting dht context as ", ourPubkey);
@ -886,6 +883,7 @@ llarp_router::Run()
ScheduleTicker(1000);
// delayed connect all
llarp_logic_call_later(logic, {delay, this, &ConnectAll});
return true;
}
bool
@ -1041,11 +1039,11 @@ llarp_configure_router(struct llarp_router *router, struct llarp_config *conf)
return router->EnsureIdentity();
}
void
bool
llarp_run_router(struct llarp_router *router, struct llarp_nodedb *nodedb)
{
router->nodedb = nodedb;
router->Run();
return router->Run();
}
void

@ -200,7 +200,7 @@ struct llarp_router
bool
Ready();
void
bool
Run();
void

@ -45,9 +45,10 @@ namespace llarp
llarp::LogError("No endpoints found");
return nullptr;
}
auto firstEndpoint = m_Endpoints.begin();
auto *uniqueEndpoint = &firstEndpoint->second;
return uniqueEndpoint->get();
auto itr = m_Endpoints.begin();
if(itr == m_Endpoints.end())
return nullptr;
return itr->second.get();
}
bool

@ -36,6 +36,7 @@
int
tuntap_sys_start(struct device *dev, int mode, int tun)
{
int fd;
int persist;
char *ifname;
@ -79,15 +80,27 @@ tuntap_sys_start(struct device *dev, int mode, int tun)
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'tun'");
return -1;
}
/* Open the clonable interface */
fd = -1;
if((fd = open("/dev/net/tun", O_RDWR)) == -1)
if(dev->obtain_fd)
{
tuntap_log(TUNTAP_LOG_ERR, "Can't open /dev/net/tun");
return -1;
// for android
fd = dev->obtain_fd(dev);
if(fd == -1)
{
tuntap_log(TUNTAP_LOG_ERR, "failed to get network interface");
return -1;
}
return fd;
}
else
{
/* Open the clonable interface */
if((fd = open("/dev/net/tun", O_RDWR)) == -1)
{
tuntap_log(TUNTAP_LOG_ERR, "Can't open /dev/net/tun");
return -1;
}
}
/* Set the interface name, if any */
if(fd > TUNTAP_ID_MAX)

@ -56,7 +56,8 @@ extern "C"
if((dev = (struct device *)malloc(sizeof(*dev))) == NULL)
return NULL;
dev->obtain_fd = nullptr;
dev->user = nullptr;
(void)memset(dev->if_name, '\0', sizeof(dev->if_name));
dev->tun_fd = TUNFD_INVALID_VALUE;
dev->ctrl_sock = -1;

Loading…
Cancel
Save