Added sub sequence search function, and put this into effect; seems to work just...
[pingpong.git] / Code / Projects / SmartPlugDetector / src / main / java / edu / uci / iotproject / DnsMap.java
1 package edu.uci.iotproject;
2
3 import org.pcap4j.packet.Packet;
4 import org.pcap4j.packet.DnsPacket;
5 import org.pcap4j.packet.DnsResourceRecord;
6 import org.pcap4j.packet.namednumber.DnsResourceRecordType;
7
8 import java.io.EOFException;
9 import java.net.Inet4Address;
10 import java.net.UnknownHostException;
11 import java.time.Instant;
12 import java.util.*;
13 import java.util.concurrent.TimeoutException;
14
15 /**
16  * This is a class that does DNS mapping.
17  * Basically an IP address is mapped to its
18  * respective DNS hostnames.
19  *
20  * @author Rahmadi Trimananda (rtrimana@uci.edu)
21  * @version 0.1
22  */
23 public class DnsMap {
24
25     /* Class properties */
26     private Map<String, Set<String>> ipToHostnameMap;
27
28     /* Class constants */
29     private static final Set<String> EMPTY_SET = Collections.unmodifiableSet(new HashSet<>());
30
31     
32     /* Constructor */
33     public DnsMap() {
34
35         ipToHostnameMap = new HashMap<String, Set<String>>();
36     }
37
38     
39     /**
40      * Gets a packet and determine if this is a DNS packet
41      *
42      * @param   packet  Packet object
43      * @return          DnsPacket object or null
44      */
45     private DnsPacket getDnsPacket(Packet packet) {
46
47         DnsPacket dnsPacket = packet.get(DnsPacket.class);
48         return dnsPacket;
49     }
50
51
52     /**
53      * Checks DNS packet and build the map data structure that
54      * maps IP addresses to DNS hostnames
55      *
56      * @param   packet  Packet object
57      */
58     public void validateAndAddNewEntry(Packet packet) throws UnknownHostException {
59
60         // Make sure that this is a DNS packet
61         DnsPacket dnsPacket = getDnsPacket(packet);
62         if (dnsPacket != null) {
63
64             // We only care about DNS answers
65             if (dnsPacket.getHeader().getAnswers().size() != 0) {
66
67                 String hostname = dnsPacket.getHeader().getQuestions().get(0).getQName().getName();
68                 for(DnsResourceRecord answer : dnsPacket.getHeader().getAnswers()) {
69                     // We only care about type A records
70                     if (!answer.getDataType().equals(DnsResourceRecordType.A))
71                         continue;
72                     // Sanity check. For some reason the hostname appears to be the empty string in the answer .
73                     // We hence have to assume that all answers correspond to a single question that holds the hostname as part of its object tree.
74                     // Therefore, if there are more questions in one query-reply exchange, we are in trouble.
75                     if (!answer.getName().getName().equals("") && !answer.getName().getName().equals(hostname))
76                         throw new RuntimeException("[DNS parser] mismatch between hostname in question and hostname in answer");
77                     // The IP in byte representation.
78                     byte[] ipBytes = answer.getRData().getRawData();
79                     // Convert to string representation.
80                     String ip = Inet4Address.getByAddress(ipBytes).getHostAddress();
81                     Set<String> hostnameSet = new HashSet<String>();
82                     hostnameSet.add(hostname);
83                     // Update or insert depending on presence of key:
84                     // Concat the existing set and the new set if ip already present as key,
85                     // otherwise add an entry for ip pointing to new set.
86                     ipToHostnameMap.merge(ip, hostnameSet, (v1, v2) -> { v1.addAll(v2); return v1; });
87                 }
88             }
89         }
90     }
91     
92     
93     /**
94      * Checks DNS packet and build the map data structure that
95      * maps IP addresses to DNS hostnames
96      *
97      * @param   address     Address to check
98      * @param   hostname    Hostname to check
99      */
100     public boolean isRelatedToCloudServer(String address, String hostname) {
101         
102         return ipToHostnameMap.getOrDefault(address, EMPTY_SET).contains(hostname);
103     }
104 }