Commit 6434a8a8 authored by Daniel Wolf's avatar Daniel Wolf
Browse files

Current working state

parent 86fb7b97
......@@ -32,4 +32,13 @@
# See http://stackoverflow.com/questions/5701126, happens in dnsjava
-optimizations !code/allocation/variable
-keep class android.support.v7.widget.SearchView { *; }
-keepattributes SourceFile,LineNumberTable
\ No newline at end of file
-keepattributes SourceFile,LineNumberTable
-keepclassmembers public class * extends com.frostnerd.utils.database.orm.Serializer {
public <init>(...);
private <fields>;
}
-keepclassmembers public class * extends com.frostnerd.utils.database.orm.Entity {
public <init>(...);
private <fields>;
}
\ No newline at end of file
package com.frostnerd.dnsserver.activities;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.app.AppCompatActivity;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import com.frostnerd.dnsserver.R;
import com.frostnerd.dnsserver.server.DNSServer;
import com.frostnerd.dnsserver.server.UDPServer;
import com.frostnerd.dnsserver.util.IPPortPair;
import com.frostnerd.dnsserver.database.DatabaseHelper;
import java.util.ArrayList;
import java.util.List;
import de.measite.minidns.Record;
/**
* Copyright Daniel Wolf 2017
* All rights reserved.
......@@ -35,21 +29,6 @@ public class MainActivity extends AppCompatActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list = findViewById(R.id.list);
final List<String> obj = new ArrayList<>();
list.setAdapter(adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, obj));
DNSServer.Configuration configuration = new DNSServer.Configuration.Builder().setLogUpstreamQueryResults(false)
.setQueryListener(new DNSServer.QueryListener() {
@Override
public void queryReceived(final String host, final String query, final Record.TYPE type, boolean forwardedToUpstream) {
runOnUiThread(new Runnable() {
@Override
public void run() {
adapter.add(host + " ---> " + query + "(" + type + ")");
System.out.println("Received Query: " + query + " from " + host + " (" + type + ")");
}
});
}
}).build();
new Thread(new UDPServer(this, 5301, new IPPortPair("8.8.8.8", 53, false), configuration)).start();
new DatabaseHelper(this);
}
}
package com.frostnerd.dnsserver.util;
package com.frostnerd.dnsserver.database;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import com.frostnerd.dnsserver.database.entities.DNSServerSetting;
import com.frostnerd.dnsserver.database.entities.IPPortPair;
import com.frostnerd.utils.database.orm.Entity;
import java.util.HashSet;
import java.util.Set;
/**
* Copyright Daniel Wolf 2017
* All rights reserved.
......@@ -13,48 +20,37 @@ import android.database.sqlite.SQLiteOpenHelper;
* <p>
* development@frostnerd.com
*/
public class DatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "data";
public class DatabaseHelper extends com.frostnerd.utils.database.DatabaseHelper {
private static final String DATABASE_NAME = "main";
private static final int DATABASE_VERSION = 1;
private SQLiteDatabase currentDB;
private static final Set<Class<? extends Entity>> entities = new HashSet<>();
static{
entities.add(IPPortPair.class);
entities.add(DNSServerSetting.class);
}
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
super(context, DATABASE_NAME, DATABASE_VERSION, entities);
}
@Override
public void onCreate(SQLiteDatabase db) {
currentDB = db;
db.execSQL("CREATE TABLE IF NOT EXISTS DNSRules(Domain TEXT NOT NULL, IPv6 BOOL DEFAULT 0, Target TEXT NOT NULL, Wildcard BOOL DEFAULT 0, PRIMARY KEY(Domain, IPv6))");
public void onBeforeCreate(SQLiteDatabase db) {
currentDB = null;
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
currentDB = db;
public void onAfterCreate(SQLiteDatabase db) {
currentDB = null;
}
@Override
public void onConfigure(SQLiteDatabase db) {
super.onConfigure(db);
}
public void onBeforeUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
@Override
public SQLiteDatabase getWritableDatabase() {
if(currentDB != null){
return currentDB;
}
return super.getWritableDatabase();
}
@Override
public SQLiteDatabase getReadableDatabase() {
if(currentDB != null){
return currentDB;
}
return super.getReadableDatabase();
public void onAfterUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
package com.frostnerd.dnsserver.database.entities;
import com.frostnerd.dnsserver.server.DNSServer;
import com.frostnerd.utils.database.orm.Entity;
import com.frostnerd.utils.database.orm.annotations.Ignore;
import com.frostnerd.utils.database.orm.annotations.Named;
import com.frostnerd.utils.database.orm.annotations.NotNull;
import com.frostnerd.utils.database.orm.annotations.RowID;
import com.frostnerd.utils.database.orm.annotations.Table;
import java.io.Serializable;
/**
* Copyright Daniel Wolf 2017
* All rights reserved.
* Code may NOT be used without proper permission, neither in binary nor in source form.
* All redistributions of this software in source code must retain this copyright header
* All redistributions of this software in binary form must visibly inform users about usage of this software
* <p>
* development@frostnerd.com
*/
@Table(name = "DNSServerSetting")
public class DNSServerSetting extends Entity implements Serializable{
@RowID
private int rowID;
@Named(name = "Name")
@NotNull
private String name;
@Named(name = "Port")
private int port;
@Named(name = "ServerTimeout")
private int serverTimeout;
@Named(name = "UpstreamPrimary")
@NotNull
private IPPortPair upstreamPrimary;
@Named(name = "UpstreamSecondary")
private IPPortPair upstreamSecondary;
@Named(name = "LogQueries")
private boolean logQueries;
@Named(name = "LogQueryResponses")
private boolean logQueryResponses ;
@Named(name = "UpstreamUDP")
private boolean upstreamUDP;
@Named(name = "ResolveLocal")
private boolean resolveLocal;
@Ignore
private DNSServer.ErrorListener errorListener;
@Ignore
private DNSServer.QueryListener queryListener;
public String getName() {
return name;
}
public int getPort() {
return port;
}
public int getServerTimeout() {
return serverTimeout;
}
public IPPortPair getUpstreamPrimary() {
return upstreamPrimary;
}
public IPPortPair getUpstreamSecondary() {
return upstreamSecondary;
}
public boolean isQueryLoggingEnabled() {
return logQueries;
}
public boolean isQueryResponseLoggingEnabled() {
return logQueryResponses;
}
public boolean isUpstreamUDP() {
return upstreamUDP;
}
public DNSServer.ErrorListener getErrorListener() {
return errorListener;
}
public void setErrorListener(DNSServer.ErrorListener errorListener) {
this.errorListener = errorListener;
}
public DNSServer.QueryListener getQueryListener() {
return queryListener;
}
public void setQueryListener(DNSServer.QueryListener queryListener) {
this.queryListener = queryListener;
}
public boolean shouldResolveLocal(){
return resolveLocal;
}
}
package com.frostnerd.dnsserver.util;
package com.frostnerd.dnsserver.database.entities;
import com.frostnerd.dnsserver.util.Util;
import com.frostnerd.utils.database.orm.Entity;
import com.frostnerd.utils.database.orm.annotations.AutoIncrement;
import com.frostnerd.utils.database.orm.annotations.Named;
import com.frostnerd.utils.database.orm.annotations.PrimaryKey;
import com.frostnerd.utils.database.orm.annotations.Table;
import java.io.Serializable;
public class IPPortPair implements Serializable{
/**
* Copyright Daniel Wolf 2017
* All rights reserved.
* Code may NOT be used without proper permission, neither in binary nor in source form.
* All redistributions of this software in source code must retain this copyright header
* All redistributions of this software in binary form must visibly inform users about usage of this software
* <p>
* development@frostnerd.com
*/
@Table(name = "IPPortPair")
public class IPPortPair extends Entity implements Serializable {
@Named(name = "IP")
private String ip;
@Named(name = "Port")
private int port;
@Named(name = "Ipv6")
private boolean ipv6;
public static final IPPortPair EMPTY = new IPPortPair("", -1, false);
@PrimaryKey
@AutoIncrement
private int id;
public IPPortPair(){
}
public IPPortPair(String ip, int port, boolean IPv6) {
this.ip = ip;
......@@ -14,7 +44,11 @@ public class IPPortPair implements Serializable{
}
public static IPPortPair wrap(String s){
return Util.validateInput(s, s.contains("[") || s.matches("[a-fA-F0-9:]+"), true);
return Util.validateInput(s, s.contains("[") || s.matches("[a-fA-F0-9:]+"), true, true);
}
public static IPPortPair wrap(String s, int defPort){
return Util.validateInput(s, s.contains("[") || s.matches("[a-fA-F0-9:]+"), true, defPort);
}
public String getAddress() {
......@@ -43,7 +77,13 @@ public class IPPortPair implements Serializable{
@Override
public String toString() {
return ipv6 ? "[" + getAddress() + "]:" + getPort() : getAddress() + ":" + getPort();
return toString(true);
}
public String toString(boolean port){
if(isEmpty())return "";
if(port)return ipv6 ? "[" + getAddress() + "]:" + getPort() : getAddress() + ":" + getPort();
else return getAddress();
}
public String formatForTextfield(boolean customPorts){
......@@ -54,4 +94,9 @@ public class IPPortPair implements Serializable{
return customPorts ? ip + ":" + port : ip;
}
}
public boolean isEmpty(){
return getAddress().equals("");
}
}
\ No newline at end of file
......@@ -2,8 +2,8 @@ package com.frostnerd.dnsserver.server;
import android.content.Context;
import com.frostnerd.dnsserver.database.entities.DNSServerSetting;
import com.frostnerd.dnsserver.util.DNSResolver;
import com.frostnerd.dnsserver.util.IPPortPair;
import com.frostnerd.dnsserver.util.QueryLogger;
import com.frostnerd.dnsserver.util.Util;
......@@ -22,173 +22,90 @@ import de.measite.minidns.Record;
* development@frostnerd.com
*/
public abstract class DNSServer implements Runnable {
protected DNSResolver resolver;
protected int port;
protected Configuration configuration;
protected IPPortPair upstreamServer;
protected InetAddress upstreamServerAddress;
protected QueryLogger queryLogger;
protected QueryListener queryListener;
DNSResolver resolver;
DNSServerSetting settings;
InetAddressWithPort primaryAddress, secondaryAddress;
QueryLogger queryLogger;
QueryListener queryListener;
public DNSServer(Context context, int port, IPPortPair upstreamServer, final Configuration configuration) {
DNSServer(Context context, DNSServerSetting settings) {
this.resolver = Util.getDnsResolver(context);
this.port = port;
this.configuration = configuration;
this.upstreamServer = upstreamServer;
this.settings = settings;
try {
this.upstreamServerAddress = InetAddress.getByName(upstreamServer.getAddress());
this.primaryAddress = new InetAddressWithPort(InetAddress.getByName(settings.getUpstreamPrimary().getAddress()), settings.getUpstreamPrimary().getPort());
this.secondaryAddress = new InetAddressWithPort(InetAddress.getByName(settings.getUpstreamSecondary().getAddress()), settings.getUpstreamSecondary().getPort());
} catch (UnknownHostException ignored) {}
if(configuration.shouldLogQueries() || configuration.shouldLogForwardedQuery() ||
configuration.shouldLogUpstreamQueryResults())
if(settings.isQueryLoggingEnabled() || settings.isQueryResponseLoggingEnabled())
queryLogger = new QueryLogger(context);
if(configuration.shouldLogQueries() || configuration.shouldLogForwardedQuery() ||
configuration.shouldLogUpstreamQueryResults() || configuration.getQueryListener() != null){
if((configuration.shouldLogQueries() || configuration.shouldLogForwardedQuery()) && configuration.getQueryListener() != null){
if(settings.isQueryLoggingEnabled() && settings.getQueryListener() != null){
queryListener = new QueryListener() {
@Override
public void queryReceived(String host, String query, Record.TYPE type, boolean forwardedToUpstream) {
if(configuration.shouldLogQueries() || configuration.shouldLogForwardedQuery())
queryLogger.logQuery(host,query, type, forwardedToUpstream);
configuration.getQueryListener().queryReceived(host, query, type, forwardedToUpstream);
queryLogger.logQuery(host,query, type, forwardedToUpstream);
DNSServer.this.settings.getQueryListener().queryReceived(host, query, type, forwardedToUpstream);
}
};
}else if(configuration.getQueryListener() != null){
}else if(settings.getQueryListener() != null){
queryListener = new QueryListener() {
@Override
public void queryReceived(String host, String query, Record.TYPE type, boolean forwardedToUpstream) {
configuration.getQueryListener().queryReceived(host, query, type, forwardedToUpstream);
DNSServer.this.settings.getQueryListener().queryReceived(host, query, type, forwardedToUpstream);
}
};
}else if(settings.isQueryLoggingEnabled()){
queryListener = new QueryListener() {
@Override
public void queryReceived(String host, String query, Record.TYPE type, boolean forwardedToUpstream) {
queryLogger.logQuery(host, query, type, forwardedToUpstream);
}
};
}else{
queryListener = new QueryListener() {
@Override
public void queryReceived(String host, String query, Record.TYPE type, boolean forwardedToUpstream) {
if(configuration.shouldLogQueries() || configuration.shouldLogForwardedQuery())
queryLogger.logQuery(host,query, type, forwardedToUpstream);
// -Dust-
}
};
}
}else{
queryListener = new QueryListener() {
@Override
public void queryReceived(String host, String query, Record.TYPE type, boolean forwardedToUpstream) {
// - Dust -
}
};
}
System.out.println("Listing on port " + port);
}
public abstract void stopServer();
protected abstract void stopServer();
public void stop() {
public final void stop() {
stopServer();
resolver.cleanup();
if(queryLogger != null)queryLogger.cleanup();
resolver = null;
queryLogger = null;
primaryAddress = null;
secondaryAddress = null;
settings = null;
}
public static class Configuration{
private final boolean logQueries, upstreamUDP, logForwardedQuery, logUpstreamQueryResults, resolveLocal;
private final ErrorListener errorListener;
private final QueryListener queryListener;
private Configuration(boolean logQueries, ErrorListener errorListener, boolean upstreamUDP,
boolean logForwardedQuery, boolean logUpstreamQueryResults, QueryListener listener,
boolean resolveLocal){
this.logQueries = logQueries;
this.errorListener = errorListener;
this.upstreamUDP = upstreamUDP;
this.logForwardedQuery = logForwardedQuery;
this.logUpstreamQueryResults = logUpstreamQueryResults;
this.queryListener = listener;
this.resolveLocal = resolveLocal;
}
public boolean shouldLogQueries() {
return logQueries;
}
public boolean shouldLogForwardedQuery() {
return logForwardedQuery;
}
public interface ErrorListener{
public void onError(Exception e);
}
public boolean shouldLogUpstreamQueryResults() {
return logUpstreamQueryResults;
}
public interface QueryListener{
public void queryReceived(String host, String query, Record.TYPE type, boolean forwardedToUpstream);
}
public boolean isUpstreamUDP() {
return upstreamUDP;
}
protected final class InetAddressWithPort{
InetAddress address;
int port;
public ErrorListener getErrorListener() {
return errorListener;
public InetAddressWithPort(InetAddress address, int port){
this.address = address;
this.port = port;
}
public QueryListener getQueryListener() {
return queryListener;
public InetAddress getAddress() {
return address;
}
public boolean shouldResolveLocal() {
return resolveLocal;
public int getPort() {
return port;
}
public static class Builder {
private boolean logQueries;
private DNSServer.ErrorListener errorListener;
private boolean upstreamUDP, logForwardedQuery, logUpstreamQueryResults, resolveLocal;
private QueryListener queryListener;
public Builder setLogQueries(boolean logQueries) {
this.logQueries = logQueries;
return this;
}
public Builder setErrorListener(DNSServer.ErrorListener errorListener) {
this.errorListener = errorListener;
return this;
}
public Builder setUpstreamUDP(boolean upstreamUDP) {
this.upstreamUDP = upstreamUDP;
return this;
}
public Builder setLogForwardedQuery(boolean logForwardedQuery){
this.logForwardedQuery = logForwardedQuery;
return this;
}
public Builder setResolveLocal(boolean resolveLocal) {
this.resolveLocal = resolveLocal;
return this;
}
public Builder setLogUpstreamQueryResults(boolean logUpstreamQueryResults) {
this.logUpstreamQueryResults = logUpstreamQueryResults;
return this;
}
public Builder setQueryListener(QueryListener queryListener) {
this.queryListener = queryListener;
return this;
}
public DNSServer.Configuration build() {
return new DNSServer.Configuration(logQueries, errorListener, upstreamUDP,
logForwardedQuery, logUpstreamQueryResults, queryListener, resolveLocal);
}
}
}
public interface ErrorListener{
public void onError(Exception e);
}
public interface QueryListener{
public void queryReceived(String host, String query, Record.TYPE type, boolean forwardedToUpstream);
}
}
......@@ -2,9 +2,8 @@ package com.frostnerd.dnsserver.server;
import android.content.Context;
import com.frostnerd.dnsserver.database.entities.DNSServerSetting;
import com.frostnerd.dnsserver.util.DNSResolver;
import com.frostnerd.dnsserver.util.IPPortPair;
import com.frostnerd.utils.general.SortUtil;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
......@@ -31,28 +30,29 @@ public class UDPServer extends DNSServer{
private DatagramSocket serverSocket;
private HashMap<ExpiredPacket, Query> futureAnswers = new HashMap<>();
public UDPServer(Context context, int port, IPPortPair upstreamServer, Configuration configuration) {
super(context, port, upstreamServer, configuration);
public UDPServer(Context context, DNSServerSetting settings) {
super(context, settings);
}
@Override
public void run() {