summaryrefslogtreecommitdiff
path: root/app/java/src/DNSProxyService.java
blob: 10e127b2a6e88ab0a8b764a96cc42af73a06c568 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
package org.pihole.dnsproxy;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.SharedPreferences;

import android.content.Context;
import android.content.Intent;

import android.net.DhcpInfo;
import android.net.VpnService;
import android.net.wifi.WifiManager;

import android.preference.PreferenceManager;

import android.util.Log;

import java.net.InetAddress;

public class DNSProxyService extends VpnService {

    public static String LOG_TAG = "org.pihole.dnsproxy.log";
    public static String NOTIFICATION_NOTIFY = "org.pihole.dnsproxy.service.dnsproxy.notification.NOTIFY";
    public static String NOTIFICATION_CHANNEL_ID = "org.pihole.dnsproxy.service.dnsproxy.NOTIFICATION";
    public static String ACTION_START = "org.pihole.dnsproxy.service.dnsproxy.START";
    public static String ACTION_STOP = "org.pihole.dnsproxy.service.dnsproxy.STOP";

    public static String PIHOLE_ADDRESS = "";

    private static DNSProxyConnection connection;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId)    {
        if (intent.getAction().equals(DNSProxyService.ACTION_START)) {
            this.connect();

            return Service.START_STICKY;
        } else {
            this.disconnect();

            return Service.START_NOT_STICKY;
        }
    }

    @Override
    public void onDestroy() {
        this.disconnect();

        super.onDestroy();
    }

    /**
     * Builder has to be created by service
     */
    public VpnService.Builder newBuilder() {
        return new VpnService.Builder();
    }

    /**
     * Whether the proxy is setup running
     */
    public static boolean isRunning()
    {
        return DNSProxyService.connection != null;
    }

    /**
     * Start this service
     */
    public static void start(Context context) {
        context.startService((new Intent(context, DNSProxyService.class)).setAction(DNSProxyService.ACTION_START));
    }

    /**
     * Stop this service
     */
    public static void stop(Context context) {
        context.startService((new Intent(context, DNSProxyService.class)).setAction(DNSProxyService.ACTION_STOP));
    }

    /**
     * Setup connection
     */
    private void connect() {
        this.setPiholeAddress();

        DNSProxyService.connection = new DNSProxyConnection(this);
        DNSProxyService.connection.start();

        this.startForeground();

        // send notification when started
        Intent notification = new Intent(DNSProxyService.NOTIFICATION_NOTIFY);
        sendBroadcast(notification);
    }

    /**
     * Disconnect from connection
     */
    private void disconnect() {
        DNSProxyService.connection.stop();
        DNSProxyService.connection = null;

        stopForeground(true);

        // send notification when stopped
        Intent notification = new Intent(DNSProxyService.NOTIFICATION_NOTIFY);
        sendBroadcast(notification);
    }

    /**
     * Get and set IP address of Pihole DNS server
     */
    private void setPiholeAddress() {
        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
        if (!sharedPreferences.getBoolean("use_automatic_dns_server_discovery", true)) {
            DNSProxyService.PIHOLE_ADDRESS = sharedPreferences.getString("dns_server_address", "");
            return;
        }

        WifiManager manager = (WifiManager) getSystemService(WIFI_SERVICE);
        DhcpInfo info = manager.getDhcpInfo();

        byte[] addressBytes = {
            (byte) (0xff & info.dns1),
            (byte) (0xff & (info.dns1 >> 8)),
            (byte) (0xff & (info.dns1 >> 16)),
            (byte) (0xff & (info.dns1 >> 24)),
        };

        try {
            DNSProxyService.PIHOLE_ADDRESS = InetAddress.getByAddress(addressBytes).toString().replaceAll("/", "");
        } catch (Exception e) {
            DNSProxyService.PIHOLE_ADDRESS = "";
        }
    }

    /**
     * Start the Foreground notification process
     */
    private void startForeground() {
        NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

        NotificationChannel channel = new NotificationChannel(
            DNSProxyService.NOTIFICATION_CHANNEL_ID,
            DNSProxyService.NOTIFICATION_CHANNEL_ID,
            NotificationManager.IMPORTANCE_DEFAULT
        );
        manager.createNotificationChannel(channel);

        Notification notification = new Notification.Builder(this, DNSProxyService.NOTIFICATION_CHANNEL_ID)
            .setSmallIcon(R.drawable.logo)
            .setContentTitle(getString(R.string.app_label))
            .setContentText(String.format(getString(R.string.dns_proxy_service__notification__text), DNSProxyService.PIHOLE_ADDRESS))
            .setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), Intent.FLAG_ACTIVITY_NEW_TASK))
            .addAction(
                R.drawable.logo,
                getString(R.string.dns_proxy_service__notification__action__stop),
                PendingIntent.getService(this, 0,
                    (new Intent(this, DNSProxyService.class)).setAction(DNSProxyService.ACTION_STOP),
                    PendingIntent.FLAG_IMMUTABLE
                )
            )
            .build();

        startForeground(1, notification);
    }
}