mirror of
https://github.com/M66B/NetGuard.git
synced 2025-01-01 12:54:07 +00:00
Use reentrant read/write lock to protect database / optimize performance
Refs #243
This commit is contained in:
parent
e738cddd80
commit
29d3c74a9a
5 changed files with 175 additions and 186 deletions
|
@ -79,7 +79,7 @@ am start -a eu.faircode.netguard.START_PORT_FORWARD \
|
|||
--ei dport 53 \
|
||||
--es raddr 8.8.4.4 \
|
||||
--ei rport 53 \
|
||||
--ei ruid 1 \
|
||||
--ei ruid 9999 \
|
||||
--user 0
|
||||
*/
|
||||
Log.i(TAG, "Start forwarding protocol " + protocol + " port " + dport + " to " + raddr + "/" + rport + " uid " + ruid);
|
||||
|
|
|
@ -527,11 +527,11 @@ public class ActivitySettings extends AppCompatActivity implements SharedPrefere
|
|||
if (vpn4 == null || TextUtils.isEmpty(vpn4.trim()))
|
||||
throw new IllegalArgumentException("vpn4");
|
||||
InetAddress.getByName(vpn4);
|
||||
SinkholeService.reload(null, "changed " + name, this);
|
||||
} catch (Throwable ex) {
|
||||
Log.w(TAG, ex.toString());
|
||||
prefs.edit().remove("vpn4").apply();
|
||||
}
|
||||
SinkholeService.reload(null, "changed " + name, this);
|
||||
getPreferenceScreen().findPreference(name).setTitle(getString(R.string.setting_vpn4, prefs.getString("vpn4", "10.1.10.1")));
|
||||
|
||||
} else if ("vpn6".equals(name)) {
|
||||
|
@ -540,11 +540,11 @@ public class ActivitySettings extends AppCompatActivity implements SharedPrefere
|
|||
if (vpn6 == null || TextUtils.isEmpty(vpn6.trim()))
|
||||
throw new IllegalArgumentException("vpn6");
|
||||
InetAddress.getByName(vpn6);
|
||||
SinkholeService.reload(null, "changed " + name, this);
|
||||
} catch (Throwable ex) {
|
||||
Log.w(TAG, ex.toString());
|
||||
prefs.edit().remove("vpn6").apply();
|
||||
}
|
||||
SinkholeService.reload(null, "changed " + name, this);
|
||||
getPreferenceScreen().findPreference(name).setTitle(getString(R.string.setting_vpn6, prefs.getString("vpn6", "fd00:1:fd00:1:fd00:1:fd00:1")));
|
||||
|
||||
} else if ("dns".equals(name)) {
|
||||
|
@ -553,11 +553,11 @@ public class ActivitySettings extends AppCompatActivity implements SharedPrefere
|
|||
if (dns == null || TextUtils.isEmpty(dns.trim()))
|
||||
throw new IllegalArgumentException("dns");
|
||||
InetAddress.getByName(dns);
|
||||
SinkholeService.reload(null, "changed " + name, this);
|
||||
} catch (Throwable ex) {
|
||||
Log.w(TAG, ex.toString());
|
||||
prefs.edit().remove("dns").apply();
|
||||
}
|
||||
SinkholeService.reload(null, "changed " + name, this);
|
||||
getPreferenceScreen().findPreference(name).setTitle(getString(R.string.setting_dns, prefs.getString("dns", Util.getDefaultDNS(this))));
|
||||
|
||||
} else if ("show_stats".equals(name))
|
||||
|
|
|
@ -35,6 +35,7 @@ import java.text.SimpleDateFormat;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
public class DatabaseHelper extends SQLiteOpenHelper {
|
||||
private static final String TAG = "NetGuard.Database";
|
||||
|
@ -53,6 +54,10 @@ public class DatabaseHelper extends SQLiteOpenHelper {
|
|||
private final static int MSG_LOG = 1;
|
||||
private final static int MSG_ACCESS = 2;
|
||||
|
||||
private ReentrantReadWriteLock mLock = new ReentrantReadWriteLock(true);
|
||||
|
||||
// TODO precompiled statements
|
||||
|
||||
static {
|
||||
hthread = new HandlerThread("DatabaseHelper");
|
||||
hthread.start();
|
||||
|
@ -299,8 +304,9 @@ public class DatabaseHelper extends SQLiteOpenHelper {
|
|||
|
||||
// Log
|
||||
|
||||
public DatabaseHelper insertLog(Packet packet, String dname, int connection, boolean interactive) {
|
||||
synchronized (context.getApplicationContext()) {
|
||||
public void insertLog(Packet packet, String dname, int connection, boolean interactive) {
|
||||
mLock.writeLock().lock();
|
||||
try {
|
||||
SQLiteDatabase db = this.getWritableDatabase();
|
||||
|
||||
ContentValues cv = new ContentValues();
|
||||
|
@ -345,59 +351,74 @@ public class DatabaseHelper extends SQLiteOpenHelper {
|
|||
|
||||
if (db.insert("log", null, cv) == -1)
|
||||
Log.e(TAG, "Insert log failed");
|
||||
} finally {
|
||||
mLock.writeLock().unlock();
|
||||
}
|
||||
|
||||
notifyLogChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
public DatabaseHelper clearLog() {
|
||||
synchronized (context.getApplicationContext()) {
|
||||
public void clearLog() {
|
||||
mLock.writeLock().lock();
|
||||
try {
|
||||
SQLiteDatabase db = this.getReadableDatabase();
|
||||
db.delete("log", null, new String[]{});
|
||||
db.execSQL("VACUUM");
|
||||
} finally {
|
||||
mLock.writeLock().unlock();
|
||||
}
|
||||
|
||||
notifyLogChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
public Cursor getLog(boolean udp, boolean tcp, boolean other, boolean allowed, boolean blocked) {
|
||||
// There is no index on protocol/allowed for write performance
|
||||
SQLiteDatabase db = this.getReadableDatabase();
|
||||
String query = "SELECT ID AS _id, *";
|
||||
query += " FROM log";
|
||||
query += " WHERE (0 = 1";
|
||||
if (udp)
|
||||
query += " OR protocol = 17";
|
||||
if (tcp)
|
||||
query += " OR protocol = 6";
|
||||
if (other)
|
||||
query += " OR (protocol <> 6 AND protocol <> 17)";
|
||||
query += ") AND (0 = 1";
|
||||
if (allowed)
|
||||
query += " OR allowed = 1";
|
||||
if (blocked)
|
||||
query += " OR allowed = 0";
|
||||
query += ")";
|
||||
query += " ORDER BY time DESC";
|
||||
return db.rawQuery(query, new String[]{});
|
||||
mLock.readLock().lock();
|
||||
try {
|
||||
// There is no index on protocol/allowed for write performance
|
||||
SQLiteDatabase db = this.getReadableDatabase();
|
||||
String query = "SELECT ID AS _id, *";
|
||||
query += " FROM log";
|
||||
query += " WHERE (0 = 1";
|
||||
if (udp)
|
||||
query += " OR protocol = 17";
|
||||
if (tcp)
|
||||
query += " OR protocol = 6";
|
||||
if (other)
|
||||
query += " OR (protocol <> 6 AND protocol <> 17)";
|
||||
query += ") AND (0 = 1";
|
||||
if (allowed)
|
||||
query += " OR allowed = 1";
|
||||
if (blocked)
|
||||
query += " OR allowed = 0";
|
||||
query += ")";
|
||||
query += " ORDER BY time DESC";
|
||||
return db.rawQuery(query, new String[]{});
|
||||
} finally {
|
||||
mLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public Cursor searchLog(String find) {
|
||||
SQLiteDatabase db = this.getReadableDatabase();
|
||||
String query = "SELECT ID AS _id, *";
|
||||
query += " FROM log";
|
||||
query += " WHERE daddr LIKE ? OR dname LIKE ? OR dport = ? OR uid LIKE ?";
|
||||
query += " ORDER BY time DESC";
|
||||
return db.rawQuery(query, new String[]{"%" + find + "%", "%" + find + "%", find, "%" + find + "%"});
|
||||
mLock.readLock().lock();
|
||||
try {
|
||||
SQLiteDatabase db = this.getReadableDatabase();
|
||||
String query = "SELECT ID AS _id, *";
|
||||
query += " FROM log";
|
||||
query += " WHERE daddr LIKE ? OR dname LIKE ? OR dport = ? OR uid LIKE ?";
|
||||
query += " ORDER BY time DESC";
|
||||
return db.rawQuery(query, new String[]{"%" + find + "%", "%" + find + "%", find, "%" + find + "%"});
|
||||
} finally {
|
||||
mLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
// Access
|
||||
|
||||
public boolean updateAccess(Packet packet, String dname, int block) {
|
||||
int rows;
|
||||
synchronized (context.getApplicationContext()) {
|
||||
|
||||
mLock.writeLock().lock();
|
||||
try {
|
||||
SQLiteDatabase db = this.getWritableDatabase();
|
||||
|
||||
ContentValues cv = new ContentValues();
|
||||
|
@ -427,14 +448,17 @@ public class DatabaseHelper extends SQLiteOpenHelper {
|
|||
Log.e(TAG, "Insert access failed");
|
||||
} else if (rows != 1)
|
||||
Log.e(TAG, "Update access failed rows=" + rows);
|
||||
} finally {
|
||||
mLock.writeLock().unlock();
|
||||
}
|
||||
|
||||
notifyAccessChanged();
|
||||
return (rows == 0);
|
||||
}
|
||||
|
||||
public DatabaseHelper setAccess(long id, int block) {
|
||||
synchronized (context.getApplicationContext()) {
|
||||
public void setAccess(long id, int block) {
|
||||
mLock.writeLock().lock();
|
||||
try {
|
||||
SQLiteDatabase db = this.getWritableDatabase();
|
||||
|
||||
ContentValues cv = new ContentValues();
|
||||
|
@ -443,66 +467,92 @@ public class DatabaseHelper extends SQLiteOpenHelper {
|
|||
|
||||
if (db.update("access", cv, "ID = ?", new String[]{Long.toString(id)}) != 1)
|
||||
Log.e(TAG, "Set access failed");
|
||||
} finally {
|
||||
mLock.writeLock().unlock();
|
||||
}
|
||||
|
||||
notifyAccessChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
public DatabaseHelper clearAccess() {
|
||||
synchronized (context.getApplicationContext()) {
|
||||
public void clearAccess() {
|
||||
mLock.writeLock().lock();
|
||||
try {
|
||||
SQLiteDatabase db = this.getReadableDatabase();
|
||||
db.delete("access", null, null);
|
||||
} finally {
|
||||
mLock.writeLock().unlock();
|
||||
}
|
||||
|
||||
notifyAccessChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
public DatabaseHelper clearAccess(int uid) {
|
||||
synchronized (context.getApplicationContext()) {
|
||||
public void clearAccess(int uid) {
|
||||
mLock.writeLock().lock();
|
||||
try {
|
||||
SQLiteDatabase db = this.getReadableDatabase();
|
||||
db.delete("access", "uid = ? AND block < 0", new String[]{Integer.toString(uid)});
|
||||
} finally {
|
||||
mLock.writeLock().unlock();
|
||||
}
|
||||
|
||||
notifyAccessChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
public Cursor getAccess(int uid) {
|
||||
SQLiteDatabase db = this.getReadableDatabase();
|
||||
String query = "SELECT ID AS _id, *";
|
||||
query += " FROM access WHERE uid = ?";
|
||||
query += " ORDER BY time DESC";
|
||||
query += " LIMIT 50";
|
||||
return db.rawQuery(query, new String[]{Integer.toString(uid)});
|
||||
mLock.readLock().lock();
|
||||
try {
|
||||
SQLiteDatabase db = this.getReadableDatabase();
|
||||
String query = "SELECT ID AS _id, *";
|
||||
query += " FROM access WHERE uid = ?";
|
||||
query += " ORDER BY time DESC";
|
||||
query += " LIMIT 50";
|
||||
return db.rawQuery(query, new String[]{Integer.toString(uid)});
|
||||
} finally {
|
||||
mLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public Cursor getAccess() {
|
||||
SQLiteDatabase db = this.getReadableDatabase();
|
||||
return db.query("access", null, "block >= 0", null, null, null, "uid");
|
||||
mLock.readLock().lock();
|
||||
try {
|
||||
SQLiteDatabase db = this.getReadableDatabase();
|
||||
return db.query("access", null, "block >= 0", null, null, null, "uid");
|
||||
} finally {
|
||||
mLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public Cursor getAccessUnset(int uid) {
|
||||
SQLiteDatabase db = this.getReadableDatabase();
|
||||
String query = "SELECT MAX(time) AS time, daddr, allowed";
|
||||
query += " FROM access";
|
||||
query += " WHERE uid = ?";
|
||||
query += " AND block < 0";
|
||||
query += " GROUP BY daddr, allowed";
|
||||
query += " ORDER BY time DESC";
|
||||
return db.rawQuery(query, new String[]{Integer.toString(uid)});
|
||||
mLock.readLock().lock();
|
||||
try {
|
||||
SQLiteDatabase db = this.getReadableDatabase();
|
||||
String query = "SELECT MAX(time) AS time, daddr, allowed";
|
||||
query += " FROM access";
|
||||
query += " WHERE uid = ?";
|
||||
query += " AND block < 0";
|
||||
query += " GROUP BY daddr, allowed";
|
||||
query += " ORDER BY time DESC";
|
||||
return db.rawQuery(query, new String[]{Integer.toString(uid)});
|
||||
} finally {
|
||||
mLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public long getRuleCount(int uid) {
|
||||
SQLiteDatabase db = this.getReadableDatabase();
|
||||
return db.compileStatement("SELECT COUNT(*) FROM access WHERE block >=0 AND uid =" + uid).simpleQueryForLong();
|
||||
mLock.readLock().lock();
|
||||
try {
|
||||
SQLiteDatabase db = this.getReadableDatabase();
|
||||
return db.compileStatement("SELECT COUNT(*) FROM access WHERE block >=0 AND uid =" + uid).simpleQueryForLong();
|
||||
} finally {
|
||||
mLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
// DNS
|
||||
|
||||
public DatabaseHelper insertDns(ResourceRecord rr) {
|
||||
synchronized (context.getApplicationContext()) {
|
||||
public void insertDns(ResourceRecord rr) {
|
||||
mLock.writeLock().lock();
|
||||
try {
|
||||
SQLiteDatabase db = this.getWritableDatabase();
|
||||
|
||||
ContentValues cv = new ContentValues();
|
||||
|
@ -521,51 +571,62 @@ public class DatabaseHelper extends SQLiteOpenHelper {
|
|||
Log.e(TAG, "Insert dns failed");
|
||||
} else if (rows != 1)
|
||||
Log.e(TAG, "Update dns failed rows=" + rows);
|
||||
} finally {
|
||||
mLock.writeLock().unlock();
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public DatabaseHelper cleanupDns(long time) {
|
||||
public void cleanupDns(long time) {
|
||||
// There is no index on time for write performance
|
||||
synchronized (context.getApplicationContext()) {
|
||||
mLock.writeLock().lock();
|
||||
try {
|
||||
SQLiteDatabase db = this.getWritableDatabase();
|
||||
int rows = db.delete("dns", "time < ?", new String[]{Long.toString(time)});
|
||||
Log.i(TAG, "Cleanup DNS" +
|
||||
" before=" + SimpleDateFormat.getDateTimeInstance().format(new Date(time)) +
|
||||
" rows=" + rows);
|
||||
} finally {
|
||||
mLock.writeLock().unlock();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getQName(String ip) {
|
||||
SQLiteDatabase db = this.getReadableDatabase();
|
||||
mLock.readLock().lock();
|
||||
try {
|
||||
SQLiteDatabase db = this.getReadableDatabase();
|
||||
return db.compileStatement(
|
||||
"SELECT qname FROM dns WHERE resource = '" + ip.replace("'", "''") + "'")
|
||||
.simpleQueryForString();
|
||||
} catch (SQLiteDoneException ignored) {
|
||||
// Not found
|
||||
return null;
|
||||
} finally {
|
||||
mLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public Cursor getDns() {
|
||||
SQLiteDatabase db = this.getReadableDatabase();
|
||||
mLock.readLock().lock();
|
||||
try {
|
||||
SQLiteDatabase db = this.getReadableDatabase();
|
||||
|
||||
String query = "SELECT a.uid, a.version, a.protocol, a.daddr, d.resource, a.dport, a.block";
|
||||
query += " FROM access AS a";
|
||||
query += " JOIN dns AS d";
|
||||
query += " ON d.qname = a.daddr";
|
||||
query += " WHERE a.block >= 0";
|
||||
String query = "SELECT a.uid, a.version, a.protocol, a.daddr, d.resource, a.dport, a.block";
|
||||
query += " FROM access AS a";
|
||||
query += " JOIN dns AS d";
|
||||
query += " ON d.qname = a.daddr";
|
||||
query += " WHERE a.block >= 0";
|
||||
|
||||
return db.rawQuery(query, new String[]{});
|
||||
return db.rawQuery(query, new String[]{});
|
||||
} finally {
|
||||
mLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
// Forward
|
||||
|
||||
public DatabaseHelper addForward(int protocol, int dport, String raddr, int rport, int ruid) {
|
||||
synchronized (context.getApplicationContext()) {
|
||||
public void addForward(int protocol, int dport, String raddr, int rport, int ruid) {
|
||||
mLock.writeLock().lock();
|
||||
try {
|
||||
SQLiteDatabase db = this.getWritableDatabase();
|
||||
|
||||
ContentValues cv = new ContentValues();
|
||||
|
@ -577,25 +638,33 @@ public class DatabaseHelper extends SQLiteOpenHelper {
|
|||
|
||||
if (db.insert("forward", null, cv) < 0)
|
||||
Log.e(TAG, "Insert forward failed");
|
||||
} finally {
|
||||
mLock.writeLock().unlock();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public DatabaseHelper deleteForward(int protocol, int dport) {
|
||||
synchronized (context.getApplicationContext()) {
|
||||
public void deleteForward(int protocol, int dport) {
|
||||
mLock.writeLock().lock();
|
||||
try {
|
||||
SQLiteDatabase db = this.getWritableDatabase();
|
||||
db.delete("forward", "protocol = ? AND dport = ?",
|
||||
new String[]{Integer.toString(protocol), Integer.toString(dport)});
|
||||
} finally {
|
||||
mLock.writeLock().unlock();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Cursor getForwarding() {
|
||||
SQLiteDatabase db = this.getReadableDatabase();
|
||||
String query = "SELECT ID AS _id, *";
|
||||
query += " FROM forward";
|
||||
query += " ORDER BY dport";
|
||||
return db.rawQuery(query, new String[]{});
|
||||
mLock.readLock().lock();
|
||||
try {
|
||||
SQLiteDatabase db = this.getReadableDatabase();
|
||||
String query = "SELECT ID AS _id, *";
|
||||
query += " FROM forward";
|
||||
query += " ORDER BY dport";
|
||||
return db.rawQuery(query, new String[]{});
|
||||
} finally {
|
||||
mLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void addLogChangedListener(LogChangedListener listener) {
|
||||
|
|
|
@ -177,7 +177,7 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
|
|||
private List<Float> gtx = new ArrayList<>();
|
||||
private List<Float> grx = new ArrayList<>();
|
||||
|
||||
private HashMap<ApplicationInfo, Long> app = new HashMap<>();
|
||||
private HashMap<Integer, Long> mapUidBytes = new HashMap<>();
|
||||
|
||||
public ServiceHandler(Looper looper) {
|
||||
super(looper);
|
||||
|
@ -458,7 +458,7 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
|
|||
gt.clear();
|
||||
gtx.clear();
|
||||
grx.clear();
|
||||
app.clear();
|
||||
mapUidBytes.clear();
|
||||
stats = true;
|
||||
updateStats();
|
||||
}
|
||||
|
@ -518,39 +518,40 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
|
|||
|
||||
// Calculate application speeds
|
||||
if (show_top) {
|
||||
if (app.size() == 0) {
|
||||
if (mapUidBytes.size() == 0) {
|
||||
for (ApplicationInfo ainfo : getPackageManager().getInstalledApplications(0))
|
||||
if (ainfo.uid != Process.myUid())
|
||||
app.put(ainfo, TrafficStats.getUidTxBytes(ainfo.uid) + TrafficStats.getUidRxBytes(ainfo.uid));
|
||||
mapUidBytes.put(ainfo.uid, TrafficStats.getUidTxBytes(ainfo.uid) + TrafficStats.getUidRxBytes(ainfo.uid));
|
||||
|
||||
} else if (t > 0) {
|
||||
TreeMap<Float, ApplicationInfo> mapSpeed = new TreeMap<>(new Comparator<Float>() {
|
||||
TreeMap<Float, Integer> mapSpeedUid = new TreeMap<>(new Comparator<Float>() {
|
||||
@Override
|
||||
public int compare(Float value, Float other) {
|
||||
return -value.compareTo(other);
|
||||
}
|
||||
});
|
||||
float dt = (ct - t) / 1000f;
|
||||
for (ApplicationInfo aInfo : app.keySet()) {
|
||||
long bytes = TrafficStats.getUidTxBytes(aInfo.uid) + TrafficStats.getUidRxBytes(aInfo.uid);
|
||||
float speed = (bytes - app.get(aInfo)) / dt;
|
||||
for (int uid : mapUidBytes.keySet()) {
|
||||
long bytes = TrafficStats.getUidTxBytes(uid) + TrafficStats.getUidRxBytes(uid);
|
||||
float speed = (bytes - mapUidBytes.get(uid)) / dt;
|
||||
if (speed > 0) {
|
||||
mapSpeed.put(speed, aInfo);
|
||||
app.put(aInfo, bytes);
|
||||
mapSpeedUid.put(speed, uid);
|
||||
mapUidBytes.put(uid, bytes);
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int i = 0;
|
||||
for (float s : mapSpeed.keySet()) {
|
||||
for (float speed : mapSpeedUid.keySet()) {
|
||||
if (i++ >= 3)
|
||||
break;
|
||||
if (s < 1000 * 1000)
|
||||
sb.append(getString(R.string.msg_kbsec, s / 1000));
|
||||
if (speed < 1000 * 1000)
|
||||
sb.append(getString(R.string.msg_kbsec, speed / 1000));
|
||||
else
|
||||
sb.append(getString(R.string.msg_mbsec, s / 1000 / 1000));
|
||||
sb.append(getString(R.string.msg_mbsec, speed / 1000 / 1000));
|
||||
sb.append(' ');
|
||||
sb.append(getPackageManager().getApplicationLabel(mapSpeed.get(s)).toString());
|
||||
List<String> apps = Util.getApplicationNames(mapSpeedUid.get(speed), SinkholeService.this);
|
||||
sb.append(apps.size() > 0 ? apps.get(0) : "?");
|
||||
sb.append("\r\n");
|
||||
}
|
||||
if (sb.length() > 0)
|
||||
|
@ -698,7 +699,7 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
|
|||
}
|
||||
|
||||
if (packet.uid < 0 && packet.dport != 53)
|
||||
Log.w(TAG, "Unknown application packet=" + packet);
|
||||
Log.w(TAG, "Unknown application packet " + packet);
|
||||
}
|
||||
|
||||
private void resolved(ResourceRecord rr) {
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
This file is part of NetGuard.
|
||||
|
||||
NetGuard is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
NetGuard is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with NetGuard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2015-2016 by Marcel Bokhorst (M66B)
|
||||
*/
|
||||
|
||||
#include "netguard.h"
|
||||
|
||||
int max_tun_msg = 0;
|
||||
extern FILE *pcap_file;
|
||||
|
||||
int check_tun(const struct arguments *args, fd_set *rfds, fd_set *wfds, fd_set *efds) {
|
||||
// Check tun error
|
||||
if (FD_ISSET(args->tun, efds)) {
|
||||
log_android(ANDROID_LOG_ERROR, "tun %d exception", args->tun);
|
||||
if (fcntl(args->tun, F_GETFL) < 0) {
|
||||
log_android(ANDROID_LOG_ERROR, "fcntl tun %d F_GETFL error %d: %s",
|
||||
args->tun, errno, strerror(errno));
|
||||
report_exit(args, "fcntl tun %d F_GETFL error %d: %s",
|
||||
args->tun, errno, strerror(errno));
|
||||
} else
|
||||
report_exit(args, "tun %d exception", args->tun);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Check tun read
|
||||
if (FD_ISSET(args->tun, rfds)) {
|
||||
uint8_t *buffer = malloc(TUN_MAXMSG);
|
||||
ssize_t length = read(args->tun, buffer, TUN_MAXMSG);
|
||||
if (length < 0) {
|
||||
free(buffer);
|
||||
|
||||
log_android(ANDROID_LOG_ERROR, "tun read error %d: %s", errno, strerror(errno));
|
||||
if (errno == EINTR || errno == EAGAIN)
|
||||
// Retry later
|
||||
return 0;
|
||||
else {
|
||||
report_exit(args, "tun read error %d: %s", errno, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (length > 0) {
|
||||
// Write pcap record
|
||||
if (pcap_file != NULL)
|
||||
write_pcap_rec(buffer, (size_t) length);
|
||||
|
||||
if (length > max_tun_msg) {
|
||||
max_tun_msg = length;
|
||||
log_android(ANDROID_LOG_WARN, "Maximum tun msg length %d", max_tun_msg);
|
||||
}
|
||||
|
||||
// Handle IP from tun
|
||||
handle_ip(args, buffer, (size_t) length);
|
||||
|
||||
free(buffer);
|
||||
}
|
||||
else {
|
||||
// tun eof
|
||||
free(buffer);
|
||||
|
||||
log_android(ANDROID_LOG_ERROR, "tun %d empty read", args->tun);
|
||||
report_exit(args, "tun %d empty read", args->tun);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue