Show blocked/allowed IPs per application
|
@ -0,0 +1,77 @@
|
|||
package eu.faircode.netguard;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.os.AsyncTask;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CursorAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
public class AccessAdapter extends CursorAdapter {
|
||||
private static String TAG = "NetGuard.Access";
|
||||
|
||||
private int colDaddr;
|
||||
private int colDPort;
|
||||
private int colTime;
|
||||
private int colAllowed;
|
||||
|
||||
public AccessAdapter(Context context, Cursor cursor) {
|
||||
super(context, cursor, 0);
|
||||
colDaddr = cursor.getColumnIndex("daddr");
|
||||
colDPort = cursor.getColumnIndex("dport");
|
||||
colTime = cursor.getColumnIndex("time");
|
||||
colAllowed = cursor.getColumnIndex("allowed");
|
||||
}
|
||||
|
||||
@Override
|
||||
public View newView(Context context, Cursor cursor, ViewGroup parent) {
|
||||
return LayoutInflater.from(context).inflate(R.layout.access, parent, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(final View view, final Context context, final Cursor cursor) {
|
||||
// Get values
|
||||
final String dest = cursor.getString(colDaddr);
|
||||
final int dport = (cursor.isNull(colDPort) ? -1 : cursor.getInt(colDPort));
|
||||
long time = cursor.getLong(colTime);
|
||||
int allowed = cursor.getInt(colAllowed);
|
||||
|
||||
// Get views
|
||||
TextView tvTime = (TextView) view.findViewById(R.id.tvTime);
|
||||
CheckBox cbIp = (CheckBox) view.findViewById(R.id.cbIp);
|
||||
final TextView tvDest = (TextView) view.findViewById(R.id.tvDest);
|
||||
|
||||
// Set values
|
||||
tvTime.setText(new SimpleDateFormat("HH:mm:ss").format(time));
|
||||
cbIp.setChecked(allowed != 0);
|
||||
|
||||
new AsyncTask<String, Object, String>() {
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
tvDest.setText(dest + ":" + dport);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String doInBackground(String... args) {
|
||||
try {
|
||||
// This requires internet permission
|
||||
return InetAddress.getByName(args[0]).getHostName();
|
||||
} catch (UnknownHostException ignored) {
|
||||
return args[0];
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(String host) {
|
||||
tvDest.setText(host + ":" + dport);
|
||||
}
|
||||
}.execute(dest);
|
||||
}
|
||||
}
|
|
@ -62,6 +62,7 @@ public class ActivityMain extends AppCompatActivity implements SharedPreferences
|
|||
|
||||
private boolean running = false;
|
||||
private SwipeRefreshLayout swipeRefresh;
|
||||
private DatabaseHelper dh;
|
||||
private RuleAdapter adapter = null;
|
||||
private MenuItem menuSearch = null;
|
||||
private AlertDialog dialogFirst = null;
|
||||
|
@ -186,7 +187,8 @@ public class ActivityMain extends AppCompatActivity implements SharedPreferences
|
|||
RecyclerView rvApplication = (RecyclerView) findViewById(R.id.rvApplication);
|
||||
rvApplication.setHasFixedSize(true);
|
||||
rvApplication.setLayoutManager(new LinearLayoutManager(this));
|
||||
adapter = new RuleAdapter(this);
|
||||
dh = new DatabaseHelper(this);
|
||||
adapter = new RuleAdapter(dh, this);
|
||||
rvApplication.setAdapter(adapter);
|
||||
|
||||
// Swipe to refresh
|
||||
|
@ -306,6 +308,8 @@ public class ActivityMain extends AppCompatActivity implements SharedPreferences
|
|||
|
||||
running = false;
|
||||
|
||||
dh.close();
|
||||
|
||||
PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(this);
|
||||
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(onRulesetChanged);
|
||||
|
|
|
@ -7,6 +7,7 @@ import android.database.sqlite.SQLiteDatabase;
|
|||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
@ -15,8 +16,9 @@ public class DatabaseHelper extends SQLiteOpenHelper {
|
|||
private static final String TAG = "NetGuard.Database";
|
||||
|
||||
private static final String DB_NAME = "Netguard";
|
||||
private static final int DB_VERSION = 8;
|
||||
private static final int DB_VERSION = 9;
|
||||
|
||||
private static boolean once = true;
|
||||
private static List<LogChangedListener> logChangedListeners = new ArrayList<LogChangedListener>();
|
||||
|
||||
private Context mContext;
|
||||
|
@ -24,15 +26,39 @@ public class DatabaseHelper extends SQLiteOpenHelper {
|
|||
public DatabaseHelper(Context context) {
|
||||
super(context, DB_NAME, null, DB_VERSION);
|
||||
mContext = context;
|
||||
|
||||
if (!once) {
|
||||
once = true;
|
||||
|
||||
File dbfile = context.getDatabasePath(DB_NAME);
|
||||
if (dbfile.exists()) {
|
||||
Log.w(TAG, "Deleting " + dbfile);
|
||||
dbfile.delete();
|
||||
}
|
||||
|
||||
File dbjournal = context.getDatabasePath(DB_NAME + "-journal");
|
||||
if (dbjournal.exists()) {
|
||||
Log.w(TAG, "Deleting " + dbjournal);
|
||||
dbjournal.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
Log.i(TAG, "Creating database " + DB_NAME + ":" + DB_VERSION);
|
||||
Log.i(TAG, "Creating database " + DB_NAME + " version " + DB_VERSION);
|
||||
createTableLog(db);
|
||||
createTableAccess(db);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigure(SQLiteDatabase db) {
|
||||
//db.enableWriteAheadLogging();
|
||||
super.onConfigure(db);
|
||||
}
|
||||
|
||||
private void createTableLog(SQLiteDatabase db) {
|
||||
Log.i(TAG, "Creating log table");
|
||||
db.execSQL("CREATE TABLE log (" +
|
||||
" ID INTEGER PRIMARY KEY AUTOINCREMENT" +
|
||||
", time INTEGER NOT NULL" +
|
||||
|
@ -55,9 +81,22 @@ public class DatabaseHelper extends SQLiteOpenHelper {
|
|||
db.execSQL("CREATE INDEX idx_log_uid ON log(uid)");
|
||||
}
|
||||
|
||||
private void createTableAccess(SQLiteDatabase db) {
|
||||
Log.i(TAG, "Creating access table");
|
||||
db.execSQL("CREATE TABLE access (" +
|
||||
" ID INTEGER PRIMARY KEY AUTOINCREMENT" +
|
||||
", uid INTEGER NOT NULL" +
|
||||
", daddr TEXT NOT NULL" +
|
||||
", dport INTEGER NULL" +
|
||||
", time INTEGER NOT NULL" +
|
||||
", allowed INTEGER NOT NULL" +
|
||||
");");
|
||||
db.execSQL("CREATE UNIQUE INDEX idx_access ON access(uid, daddr, dport)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
Log.i(TAG, "Upgrading from version " + oldVersion + " to " + newVersion);
|
||||
Log.i(TAG, DB_NAME + " upgrading from version " + oldVersion + " to " + newVersion);
|
||||
|
||||
db.beginTransaction();
|
||||
try {
|
||||
|
@ -98,10 +137,18 @@ public class DatabaseHelper extends SQLiteOpenHelper {
|
|||
db.execSQL("CREATE INDEX idx_log_uid ON log(uid)");
|
||||
oldVersion = 8;
|
||||
}
|
||||
if (oldVersion < 9) {
|
||||
createTableAccess(db);
|
||||
oldVersion = 9;
|
||||
}
|
||||
|
||||
db.setVersion(DB_VERSION);
|
||||
if (oldVersion == DB_VERSION) {
|
||||
db.setVersion(oldVersion);
|
||||
db.setTransactionSuccessful();
|
||||
Log.e(TAG, DB_NAME + " upgraded to " + DB_VERSION);
|
||||
} else
|
||||
throw new IllegalArgumentException(DB_NAME + " upgraded to " + oldVersion + " but required " + DB_VERSION);
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
} catch (Throwable ex) {
|
||||
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
|
||||
} finally {
|
||||
|
@ -109,7 +156,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
|
|||
}
|
||||
}
|
||||
|
||||
// Location
|
||||
// Log
|
||||
|
||||
public DatabaseHelper insertLog(Packet packet, int connection, boolean interactive) {
|
||||
synchronized (mContext.getApplicationContext()) {
|
||||
|
@ -196,6 +243,38 @@ public class DatabaseHelper extends SQLiteOpenHelper {
|
|||
return db.rawQuery(query, new String[]{"%" + find + "%", "%" + find + "%", "%" + find + "%"});
|
||||
}
|
||||
|
||||
// Access
|
||||
|
||||
public DatabaseHelper updateAccess(Packet packet) {
|
||||
synchronized (mContext.getApplicationContext()) {
|
||||
SQLiteDatabase db = this.getWritableDatabase();
|
||||
|
||||
ContentValues cv = new ContentValues();
|
||||
cv.put("time", packet.time);
|
||||
cv.put("allowed", packet.allowed ? 1 : 0);
|
||||
|
||||
int rows = db.update("access", cv, "uid = ? AND daddr = ? AND dport = ?", new String[]{
|
||||
Integer.toString(packet.uid), packet.daddr, Integer.toString(packet.dport)});
|
||||
|
||||
if (rows == 0) {
|
||||
cv.put("uid", packet.uid);
|
||||
cv.put("daddr", packet.daddr);
|
||||
cv.put("dport", packet.dport);
|
||||
if (db.insert("access", null, cv) == -1)
|
||||
Log.e(TAG, "Insert access failed");
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Cursor getAccess(int uid) {
|
||||
SQLiteDatabase db = this.getReadableDatabase();
|
||||
String query = "SELECT ID AS _id, * FROM access WHERE uid = ?";
|
||||
query += " ORDER BY time DESC";
|
||||
return db.rawQuery(query, new String[]{Integer.toString(uid)});
|
||||
}
|
||||
|
||||
public static void addLogChangedListener(LogChangedListener listener) {
|
||||
logChangedListeners.add(listener);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package eu.faircode.netguard;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ListView;
|
||||
|
||||
public class ExpandedListView extends ListView {
|
||||
public ExpandedListView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public ExpandedListView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public ExpandedListView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 4, MeasureSpec.AT_MOST));
|
||||
}
|
||||
}
|
|
@ -33,9 +33,9 @@ public class LogAdapter extends CursorAdapter {
|
|||
private int colVersion;
|
||||
private int colProtocol;
|
||||
private int colFlags;
|
||||
private int colSource;
|
||||
private int colSAddr;
|
||||
private int colSPort;
|
||||
private int colDest;
|
||||
private int colDaddr;
|
||||
private int colDPort;
|
||||
private int colUid;
|
||||
private int colData;
|
||||
|
@ -53,9 +53,9 @@ public class LogAdapter extends CursorAdapter {
|
|||
colVersion = cursor.getColumnIndex("version");
|
||||
colProtocol = cursor.getColumnIndex("protocol");
|
||||
colFlags = cursor.getColumnIndex("flags");
|
||||
colSource = cursor.getColumnIndex("saddr");
|
||||
colSAddr = cursor.getColumnIndex("saddr");
|
||||
colSPort = cursor.getColumnIndex("sport");
|
||||
colDest = cursor.getColumnIndex("daddr");
|
||||
colDaddr = cursor.getColumnIndex("daddr");
|
||||
colDPort = cursor.getColumnIndex("dport");
|
||||
colUid = cursor.getColumnIndex("uid");
|
||||
colData = cursor.getColumnIndex("data");
|
||||
|
@ -84,9 +84,9 @@ public class LogAdapter extends CursorAdapter {
|
|||
int version = (cursor.isNull(colVersion) ? -1 : cursor.getInt(colVersion));
|
||||
int protocol = (cursor.isNull(colProtocol) ? -1 : cursor.getInt(colProtocol));
|
||||
String flags = cursor.getString(colFlags);
|
||||
String source = cursor.getString(colSource);
|
||||
String saddr = cursor.getString(colSAddr);
|
||||
int sport = (cursor.isNull(colSPort) ? -1 : cursor.getInt(colSPort));
|
||||
final String dest = cursor.getString(colDest);
|
||||
String daddr = cursor.getString(colDaddr);
|
||||
int dport = (cursor.isNull(colDPort) ? -1 : cursor.getInt(colDPort));
|
||||
int uid = (cursor.isNull(colUid) ? -1 : cursor.getInt(colUid));
|
||||
String data = cursor.getString(colData);
|
||||
|
@ -98,9 +98,9 @@ public class LogAdapter extends CursorAdapter {
|
|||
TextView tvTime = (TextView) view.findViewById(R.id.tvTime);
|
||||
TextView tvProtocol = (TextView) view.findViewById(R.id.tvProtocol);
|
||||
TextView tvFlags = (TextView) view.findViewById(R.id.tvFlags);
|
||||
final TextView tvSource = (TextView) view.findViewById(R.id.tvSource);
|
||||
final TextView tvSAddr = (TextView) view.findViewById(R.id.tvSAddr);
|
||||
TextView tvSPort = (TextView) view.findViewById(R.id.tvSPort);
|
||||
final TextView tvDest = (TextView) view.findViewById(R.id.tvDest);
|
||||
final TextView tvDaddr = (TextView) view.findViewById(R.id.tvDAddr);
|
||||
TextView tvDPort = (TextView) view.findViewById(R.id.tvDPort);
|
||||
ImageView ivIcon = (ImageView) view.findViewById(R.id.ivIcon);
|
||||
TextView tvUid = (TextView) view.findViewById(R.id.tvUid);
|
||||
|
@ -172,14 +172,14 @@ public class LogAdapter extends CursorAdapter {
|
|||
tvUid.setText(Integer.toString(uid));
|
||||
|
||||
// TODO resolve source when inbound
|
||||
tvSource.setText(getKnownAddress(source));
|
||||
tvSAddr.setText(getKnownAddress(saddr));
|
||||
|
||||
if (resolve && !isKnownAddress(dest))
|
||||
if (resolve && !isKnownAddress(daddr))
|
||||
synchronized (mapIPHost) {
|
||||
if (mapIPHost.containsKey(dest))
|
||||
tvDest.setText(mapIPHost.get(dest));
|
||||
if (mapIPHost.containsKey(daddr))
|
||||
tvDaddr.setText(mapIPHost.get(daddr));
|
||||
else {
|
||||
tvDest.setText(dest);
|
||||
tvDaddr.setText(daddr);
|
||||
new AsyncTask<String, Object, String>() {
|
||||
@Override
|
||||
protected String doInBackground(String... args) {
|
||||
|
@ -187,7 +187,7 @@ public class LogAdapter extends CursorAdapter {
|
|||
// This requires internet permission
|
||||
return InetAddress.getByName(args[0]).getHostName();
|
||||
} catch (UnknownHostException ignored) {
|
||||
return dest;
|
||||
return args[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -197,13 +197,13 @@ public class LogAdapter extends CursorAdapter {
|
|||
if (!mapIPHost.containsKey(host))
|
||||
mapIPHost.put(host, host);
|
||||
}
|
||||
tvDest.setText(host);
|
||||
tvDaddr.setText(host);
|
||||
}
|
||||
}.execute(dest);
|
||||
}.execute(daddr);
|
||||
}
|
||||
}
|
||||
else
|
||||
tvDest.setText(getKnownAddress(dest));
|
||||
tvDaddr.setText(getKnownAddress(daddr));
|
||||
|
||||
if (TextUtils.isEmpty(data)) {
|
||||
tvData.setText("");
|
||||
|
|
|
@ -28,11 +28,16 @@ public class Packet {
|
|||
public int sport;
|
||||
public String daddr;
|
||||
public int dport;
|
||||
public boolean outbound;
|
||||
public String data;
|
||||
public int uid;
|
||||
public boolean allowed;
|
||||
|
||||
public Packet() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "uid=" + uid + " daddr=" + daddr + ":" + dport;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ import android.widget.Filterable;
|
|||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
@ -59,6 +60,7 @@ public class RuleAdapter extends RecyclerView.Adapter<RuleAdapter.ViewHolder> im
|
|||
private static final String TAG = "NetGuard.Adapter";
|
||||
|
||||
private Activity context;
|
||||
private DatabaseHelper dh;
|
||||
private boolean wifi;
|
||||
private boolean telephony;
|
||||
private boolean debuggable;
|
||||
|
@ -105,6 +107,7 @@ public class RuleAdapter extends RecyclerView.Adapter<RuleAdapter.ViewHolder> im
|
|||
public ImageButton btnSettings;
|
||||
public Button btnLaunch;
|
||||
|
||||
public ListView lvAccess;
|
||||
public TextView tvStatistics;
|
||||
|
||||
public ViewHolder(View itemView) {
|
||||
|
@ -143,6 +146,7 @@ public class RuleAdapter extends RecyclerView.Adapter<RuleAdapter.ViewHolder> im
|
|||
btnSettings = (ImageButton) itemView.findViewById(R.id.btnSettings);
|
||||
btnLaunch = (Button) itemView.findViewById(R.id.btnLaunch);
|
||||
|
||||
lvAccess = (ListView) itemView.findViewById(R.id.lvAccess);
|
||||
tvStatistics = (TextView) itemView.findViewById(R.id.tvStatistics);
|
||||
|
||||
final View wifiParent = (View) cbWifi.getParent();
|
||||
|
@ -173,8 +177,9 @@ public class RuleAdapter extends RecyclerView.Adapter<RuleAdapter.ViewHolder> im
|
|||
}
|
||||
}
|
||||
|
||||
public RuleAdapter(Activity context) {
|
||||
public RuleAdapter(DatabaseHelper dh, Activity context) {
|
||||
this.context = context;
|
||||
this.dh = dh;
|
||||
this.wifi = Util.hasWifi(context);
|
||||
this.telephony = Util.hasTelephony(context);
|
||||
this.debuggable = Util.isDebuggable(context);
|
||||
|
@ -442,6 +447,12 @@ public class RuleAdapter extends RecyclerView.Adapter<RuleAdapter.ViewHolder> im
|
|||
}
|
||||
});
|
||||
|
||||
if (rule.expanded) {
|
||||
AccessAdapter adapter = new AccessAdapter(context, dh.getAccess(rule.info.applicationInfo.uid));
|
||||
holder.lvAccess.setAdapter(adapter);
|
||||
} else
|
||||
holder.lvAccess.setAdapter(null);
|
||||
|
||||
// Traffic statistics
|
||||
holder.tvStatistics.setText(context.getString(R.string.msg_mbday, rule.upspeed, rule.downspeed));
|
||||
}
|
||||
|
|
|
@ -629,10 +629,11 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
|
|||
}
|
||||
|
||||
private void log(Packet packet) {
|
||||
new DatabaseHelper(SinkholeService.this).insertLog(
|
||||
packet,
|
||||
(last_connected ? last_metered ? 2 : 1 : 0),
|
||||
last_interactive).close();
|
||||
DatabaseHelper dh = new DatabaseHelper(SinkholeService.this);
|
||||
dh.insertLog(packet, (last_connected ? last_metered ? 2 : 1 : 0), last_interactive);
|
||||
if (packet.uid > 0 && packet.outbound)
|
||||
dh.updateAccess(packet);
|
||||
dh.close();
|
||||
}
|
||||
|
||||
private void set(Intent intent) {
|
||||
|
|
|
@ -1108,10 +1108,13 @@ void handle_ip(const struct arguments *args, const uint8_t *pkt, const size_t le
|
|||
log = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
log = 1;
|
||||
|
||||
// Log traffic
|
||||
if (args->log && (!args->filter || log))
|
||||
log_packet(args, version, protocol, flags, source, sport, dest, dport, extra, uid, allowed);
|
||||
log_packet(args, version, protocol, flags, source, sport, dest, dport, 1, extra, uid,
|
||||
allowed);
|
||||
}
|
||||
|
||||
jboolean handle_udp(const struct arguments *args,
|
||||
|
@ -2101,7 +2104,7 @@ ssize_t write_udp(const struct arguments *args, const struct udp_session *cur,
|
|||
if (res >= 0) {
|
||||
if (args->log && ntohs(cur->dest) != 53)
|
||||
log_packet(args, cur->version, IPPROTO_UDP, "",
|
||||
dest, ntohs(udp->dest), source, ntohs(udp->source), "", cur->uid, 1);
|
||||
dest, ntohs(udp->dest), source, ntohs(udp->source), 0, "", cur->uid, 1);
|
||||
|
||||
// Write pcap record
|
||||
if (pcap_file != NULL)
|
||||
|
@ -2519,6 +2522,7 @@ void log_packet(
|
|||
jint sport,
|
||||
const char *dest,
|
||||
jint dport,
|
||||
jboolean outbound,
|
||||
const char *data,
|
||||
jint uid,
|
||||
jboolean allowed) {
|
||||
|
@ -2555,6 +2559,8 @@ void log_packet(
|
|||
(*env)->SetIntField(env, objPacket, jniGetFieldID(env, clsPacket, "sport", "I"), sport);
|
||||
(*env)->SetObjectField(env, objPacket, jniGetFieldID(env, clsPacket, "daddr", string), jdest);
|
||||
(*env)->SetIntField(env, objPacket, jniGetFieldID(env, clsPacket, "dport", "I"), dport);
|
||||
(*env)->SetBooleanField(env, objPacket, jniGetFieldID(env, clsPacket, "outbound", "Z"),
|
||||
outbound);
|
||||
(*env)->SetObjectField(env, objPacket, jniGetFieldID(env, clsPacket, "data", string), jdata);
|
||||
(*env)->SetIntField(env, objPacket, jniGetFieldID(env, clsPacket, "uid", "I"), uid);
|
||||
(*env)->SetBooleanField(env, objPacket, jniGetFieldID(env, clsPacket, "allowed", "Z"), allowed);
|
||||
|
|
|
@ -309,6 +309,7 @@ void log_packet(const struct arguments *args,
|
|||
jint sport,
|
||||
const char *dest,
|
||||
jint dport,
|
||||
jboolean outbound,
|
||||
const char *data,
|
||||
jint uid,
|
||||
jboolean allowed);
|
||||
|
|
After Width: | Height: | Size: 181 B |
After Width: | Height: | Size: 221 B |
After Width: | Height: | Size: 137 B |
After Width: | Height: | Size: 175 B |
After Width: | Height: | Size: 199 B |
After Width: | Height: | Size: 257 B |
After Width: | Height: | Size: 276 B |
After Width: | Height: | Size: 347 B |
After Width: | Height: | Size: 308 B |
After Width: | Height: | Size: 436 B |
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/ip_allowed" android:state_checked="true" />
|
||||
<item android:drawable="@drawable/ip_blocked" android:state_checked="false" />
|
||||
</selector>
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:src="@drawable/ic_check_white_24dp"
|
||||
android:tint="?attr/colorOn" />
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:src="@drawable/ic_close_white_24dp"
|
||||
android:tint="?attr/colorOff" />
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal"
|
||||
tools:context=".ActivityMain">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvTime"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:textAppearance="@android:style/TextAppearance.Material.Small"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbIp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:button="@drawable/ip"
|
||||
android:scaleX="0.8"
|
||||
android:scaleY="0.8" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvDest"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="@android:style/TextAppearance.Material.Small"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
|
@ -93,7 +93,7 @@
|
|||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvSource"
|
||||
android:id="@+id/tvSAddr"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
|
@ -115,7 +115,7 @@
|
|||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvDest"
|
||||
android:id="@+id/tvDAddr"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
|
|
|
@ -279,6 +279,12 @@
|
|||
android:text="@string/title_launch" />
|
||||
</LinearLayout>
|
||||
|
||||
<eu.faircode.netguard.ExpandedListView
|
||||
android:id="@+id/lvAccess"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvStatistics"
|
||||
android:layout_width="wrap_content"
|
||||
|
|