1 package edu.uci.iotproject;
3 import org.pcap4j.core.PacketListener;
4 import org.pcap4j.core.PcapPacket;
5 import org.pcap4j.packet.Packet;
6 import org.pcap4j.packet.DnsPacket;
7 import org.pcap4j.packet.DnsResourceRecord;
8 import org.pcap4j.packet.namednumber.DnsResourceRecordType;
11 import java.net.Inet4Address;
12 import java.net.UnknownHostException;
17 * This is a class that does DNS mapping.
18 * Basically an IP address is mapped to its
19 * respective DNS hostnames.
21 * @author Rahmadi Trimananda (rtrimana@uci.edu)
24 public class DnsMap implements PacketListener {
26 /* Class properties */
27 private Map<String, Set<String>> ipToHostnameMap;
30 private static final Set<String> EMPTY_SET = Collections.unmodifiableSet(new HashSet<>());
35 ipToHostnameMap = new HashMap<>();
39 public void gotPacket(PcapPacket packet) {
41 validateAndAddNewEntry(packet);
42 } catch (UnknownHostException e) {
48 * Gets a packet and determine if this is a DNS packet
50 * @param packet Packet object
51 * @return DnsPacket object or null
53 private DnsPacket getDnsPacket(Packet packet) {
54 DnsPacket dnsPacket = packet.get(DnsPacket.class);
59 * Checks DNS packet and build the map data structure that
60 * maps IP addresses to DNS hostnames
62 * @param packet PcapPacket object
64 public void validateAndAddNewEntry(PcapPacket packet) throws UnknownHostException {
65 // Make sure that this is a DNS packet
66 DnsPacket dnsPacket = getDnsPacket(packet);
67 if (dnsPacket != null) {
68 // We only care about DNS answers
69 if (dnsPacket.getHeader().getAnswers().size() != 0) {
70 String hostname = dnsPacket.getHeader().getQuestions().get(0).getQName().getName();
71 for(DnsResourceRecord answer : dnsPacket.getHeader().getAnswers()) {
72 // We only care about type A records
73 if (!answer.getDataType().equals(DnsResourceRecordType.A))
75 // Sanity check. For some reason the hostname appears to be the empty string in the answer .
76 // We hence have to assume that all answers correspond to a single question that holds the hostname as part of its object tree.
77 // Therefore, if there are more questions in one query-reply exchange, we are in trouble.
78 if (!answer.getName().getName().equals("") && !answer.getName().getName().equals(hostname))
79 throw new RuntimeException("[DNS parser] mismatch between hostname in question and hostname in answer");
80 // The IP in byte representation.
81 byte[] ipBytes = answer.getRData().getRawData();
82 // Convert to string representation.
83 String ip = Inet4Address.getByAddress(ipBytes).getHostAddress();
84 Set<String> hostnameSet = new HashSet<>();
85 hostnameSet.add(hostname);
86 // Update or insert depending on presence of key:
87 // Concat the existing set and the new set if ip already present as key,
88 // otherwise add an entry for ip pointing to new set.
89 ipToHostnameMap.merge(ip, hostnameSet, (v1, v2) -> { v1.addAll(v2); return v1; });
97 * Checks DNS packet and build the map data structure that
98 * maps IP addresses to DNS hostnames
100 * @param address Address to check
101 * @param hostname Hostname to check
103 public boolean isRelatedToCloudServer(String address, String hostname) {
104 return ipToHostnameMap.getOrDefault(address, EMPTY_SET).contains(hostname);
107 public Set<String> getHostnamesForIp(String ip) {
108 Set<String> hostnames = ipToHostnameMap.get(ip);
109 return hostnames != null ? Collections.unmodifiableSet(hostnames) : null;