]>
git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/cms/dns/DnsBrowser.java
1 package org
.argeo
.cms
.dns
;
3 import java
.io
.Closeable
;
4 import java
.io
.IOException
;
5 import java
.io
.PrintStream
;
6 import java
.util
.ArrayList
;
7 import java
.util
.Base64
;
8 import java
.util
.Collections
;
9 import java
.util
.Hashtable
;
10 import java
.util
.List
;
12 import java
.util
.Objects
;
13 import java
.util
.SortedSet
;
14 import java
.util
.StringJoiner
;
15 import java
.util
.TreeMap
;
16 import java
.util
.TreeSet
;
18 import javax
.naming
.Binding
;
19 import javax
.naming
.Context
;
20 import javax
.naming
.NameNotFoundException
;
21 import javax
.naming
.NamingEnumeration
;
22 import javax
.naming
.NamingException
;
23 import javax
.naming
.directory
.Attribute
;
24 import javax
.naming
.directory
.Attributes
;
25 import javax
.naming
.directory
.DirContext
;
26 import javax
.naming
.directory
.InitialDirContext
;
28 public class DnsBrowser
implements Closeable
{
29 private final DirContext initialCtx
;
32 this(new ArrayList
<>());
35 public DnsBrowser(List
<String
> dnsServerUrls
) {
37 Objects
.requireNonNull(dnsServerUrls
);
38 Hashtable
<String
, Object
> env
= new Hashtable
<>();
39 env
.put(Context
.INITIAL_CONTEXT_FACTORY
, "com.sun.jndi.dns.DnsContextFactory");
40 if (!dnsServerUrls
.isEmpty()) {
41 boolean specified
= false;
42 StringJoiner providerUrl
= new StringJoiner(" ");
43 for (String dnsUrl
: dnsServerUrls
) {
45 providerUrl
.add(dnsUrl
);
50 env
.put(Context
.PROVIDER_URL
, providerUrl
.toString());
52 initialCtx
= new InitialDirContext(env
);
53 } catch (NamingException e
) {
54 throw new IllegalStateException("Cannot initialise DNS borowser.", e
);
58 public Map
<String
, List
<String
>> getAllRecords(String name
) {
60 Map
<String
, List
<String
>> res
= new TreeMap
<>();
61 Attributes attrs
= initialCtx
.getAttributes(name
);
62 NamingEnumeration
<String
> ids
= attrs
.getIDs();
63 while (ids
.hasMore()) {
64 String recordType
= ids
.next();
65 List
<String
> lst
= new ArrayList
<String
>();
66 res
.put(recordType
, lst
);
67 Attribute attr
= attrs
.get(recordType
);
70 return Collections
.unmodifiableMap(res
);
71 } catch (NamingException e
) {
72 throw new IllegalStateException("Cannot get allrecords of " + name
, e
);
77 * Return a single record (typically A, AAAA, etc. or null if not available.
78 * Will fail if multiple records.
80 public String
getRecord(String name
, String recordType
) {
82 Attributes attrs
= initialCtx
.getAttributes(name
, new String
[] { recordType
});
83 if (attrs
.size() == 0)
85 Attribute attr
= attrs
.get(recordType
);
87 throw new IllegalArgumentException("Multiple record type " + recordType
);
88 assert attr
.size() != 0;
89 Object value
= attr
.get();
91 return value
.toString();
92 } catch (NameNotFoundException e
) {
94 } catch (NamingException e
) {
95 throw new IllegalStateException("Cannot get DNS entry " + recordType
+ " of " + name
, e
);
100 * Return records of a given type.
102 public List
<String
> getRecords(String name
, String recordType
) {
104 List
<String
> res
= new ArrayList
<String
>();
105 Attributes attrs
= initialCtx
.getAttributes(name
, new String
[] { recordType
});
106 Attribute attr
= attrs
.get(recordType
);
107 addValues(attr
, res
);
109 } catch (NamingException e
) {
110 throw new IllegalStateException("Cannot get records " + recordType
+ " of " + name
, e
);
114 /** Ordered, with preferred first. */
115 public List
<String
> getSrvRecordsAsHosts(String name
, boolean withPort
) {
116 List
<String
> raw
= getRecords(name
, "SRV");
119 SortedSet
<SrvRecord
> res
= new TreeSet
<>();
120 for (int i
= 0; i
< raw
.size(); i
++) {
121 String record
= raw
.get(i
);
122 String
[] arr
= record
.split(" ");
123 Integer priority
= Integer
.parseInt(arr
[0]);
124 Integer weight
= Integer
.parseInt(arr
[1]);
125 Integer port
= Integer
.parseInt(arr
[2]);
126 String hostname
= arr
[3];
127 SrvRecord order
= new SrvRecord(priority
, weight
, port
, hostname
);
130 List
<String
> lst
= new ArrayList
<>();
131 for (SrvRecord order
: res
) {
132 lst
.add(order
.toHost(withPort
));
134 return Collections
.unmodifiableList(lst
);
137 private void addValues(Attribute attr
, List
<String
> lst
) throws NamingException
{
138 NamingEnumeration
<?
> values
= attr
.getAll();
139 while (values
.hasMore()) {
140 Object value
= values
.next();
142 if (value
instanceof byte[]) {
143 String str
= Base64
.getEncoder().encodeToString((byte[]) value
);
146 lst
.add(value
.toString());
152 public List
<String
> listEntries(String name
) {
154 List
<String
> res
= new ArrayList
<String
>();
155 NamingEnumeration
<Binding
> ne
= initialCtx
.listBindings(name
);
156 while (ne
.hasMore()) {
157 Binding b
= ne
.next();
158 res
.add(b
.getName());
160 return Collections
.unmodifiableList(res
);
161 } catch (NamingException e
) {
162 throw new IllegalStateException("Cannot list entries of " + name
, e
);
167 public void close() throws IOException
{
171 public void destroy() {
174 } catch (NamingException e
) {
179 public static void main(String
[] args
) {
180 if (args
.length
== 0) {
181 printUsage(System
.err
);
184 try (DnsBrowser dnsBrowser
= new DnsBrowser()) {
185 String hostname
= args
[0];
186 String recordType
= args
.length
> 1 ? args
[1] : "A";
187 if (recordType
.equals("*")) {
188 Map
<String
, List
<String
>> records
= dnsBrowser
.getAllRecords(hostname
);
189 for (String type
: records
.keySet()) {
190 for (String record
: records
.get(type
)) {
192 if ("44".equals(type
))
194 else if ("46".equals(type
))
196 else if ("48".equals(type
))
197 typeLabel
= "DNSKEY";
200 System
.out
.println(typeLabel
+ "\t" + record
);
204 System
.out
.println(dnsBrowser
.getRecord(hostname
, recordType
));
207 } catch (Exception e
) {
212 public static void printUsage(PrintStream out
) {
213 out
.println("java org.argeo.naming.DnsBrowser <hostname> [<record type> | *]");