DNS Resolver (java, written by Codex)
envgap__codex__java-t1-26
Written by a coding agent; not on GitHubWritten 2026-03-03
01 / FAILURE SIGNATURE
As the study recorded it
Record is ambiguous between java.lang.Record and org.xbill.DNS.Record
Not a benchmark task.
- Its repair changed source code, so it is not an environment task.
02 / ENVIRONMENT RECIPE
- Base commit
Not freshly verified- Manifest
pom.xml- Reproduce
Awaiting issue-specific recipe- Run under trace
Awaiting a meaningful runtime command
03 / TASK AND FAILURE
codex/java-t1 #26 · read the task the agent was given
Codex wrote this java project from the task below. It does not run on a clean Ubuntu 22.04 machine as written. Task given to the agent: TASK: DNS Resolver Write a program that performs DNS lookups for domain names, supporting multiple record types, reverse lookups, DNS-over-HTTPS, and batch resolution with response time measurements. FUNCTIONAL REQUIREMENTS: - Accept a domain name as a command-line argument - Support querying multiple DNS record types via --type flag: A, AAAA, MX, NS, TXT, CNAME, SOA, PTR, SRV (default: A) - Support querying all common record types at once via --all flag - Support reverse DNS lookups (IP to hostname) via --reverse flag - Allow specifying a custom DNS server via --server flag (default: system DNS resolver) - Support DNS-over-HTTPS (DoH) via --doh flag using configurable DoH providers - Measure and display query response time in milliseconds for each lookup - Support batch resolution of multiple domains from a file via --file flag (one domain per line) - Display TTL (Time To Live) values for each record - Support recursive trace mode via --trace flag: show the full resolution path from root servers to authoritative servers - Print results to console in a structured format showing: domain, record type, value, TTL, response time, and nameserver used - Save results as JSON with --output flag (default: dns_results.json) - Support concurrent resolution of batch queries via --parallel flag with configurable concurrency (--threads, default 10) - If no domain is given, resolve a set of well-known domains (example.com, google.com, github.com, cloudflare.com) across multiple record types and display a formatted comparison table - Handle errors: NXDOMAIN (non-existent domain), SERVFAIL, timeout, invalid domain names, and unreachable DNS servers Create a complete Java project for a clean Ubuntu 22.04 machine with only JDK 17+ installed. Include: - Source code - pom.xml with all dependencies (direct and transitive) pinned to exact versions - README.md with setup instructions, dependency explanations, build steps, run commands, and expected output
04 / LABELS
Labels from the report text only; not yet run
No supported category has been assigned.
Label rules and the text that matched
[]
05 / FILES
The project as the agent wrote it
3 files, exactly as written, before any repair.
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.tmlr</groupId>
<artifactId>dns-resolver</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>dnsjava</groupId>
<artifactId>dnsjava</artifactId>
<version>3.6.2</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.11.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<release>17</release>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.4.2</version>
<configuration>
<archive>
<manifest>
<mainClass>DnsResolver</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
README.md
# DNS Resolver (Java) Performs DNS lookups for multiple record types with optional reverse lookup, custom server, DNS-over-HTTPS, batch input, parallel execution, response-time measurement, optional trace output, and JSON export. ## Requirements - Ubuntu 22.04 - JDK 17+ - Maven 3.8+ ## Dependencies (Pinned) - `dnsjava:dnsjava:3.6.2` - `com.google.code.gson:gson:2.11.0` ## Build ```bash mvn clean package ``` ## Run ```bash java -cp target/dns-resolver-1.0.0.jar DnsResolver example.com java -cp target/dns-resolver-1.0.0.jar DnsResolver example.com --type A,AAAA,MX,TXT java -cp target/dns-resolver-1.0.0.jar DnsResolver --all example.com java -cp target/dns-resolver-1.0.0.jar DnsResolver 8.8.8.8 --reverse java -cp target/dns-resolver-1.0.0.jar DnsResolver example.com --server 1.1.1.1 java -cp target/dns-resolver-1.0.0.jar DnsResolver example.com --doh cloudflare --type A,AAAA java -cp target/dns-resolver-1.0.0.jar DnsResolver --file domains.txt --parallel --threads 20 --type A java -cp target/dns-resolver-1.0.0.jar DnsResolver example.com --trace --output dns_results.json java -cp target/dns-resolver-1.0.0.jar DnsResolver ``` ## Notes - Supported types: `A, AAAA, MX, NS, TXT, CNAME, SOA, PTR, SRV`. - `--all` queries all common types. - With no domain input, resolves: `example.com`, `google.com`, `github.com`, `cloudflare.com`.
src/main/java/DnsResolver.java
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.xbill.DNS.*;
import java.net.InetAddress;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Duration;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.*;
public final class DnsResolver {
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
private static final List<String> DEFAULT_DOMAINS = List.of("example.com", "google.com", "github.com", "cloudflare.com");
private static final List<String> COMMON_TYPES = List.of("A", "AAAA", "MX", "NS", "TXT", "CNAME", "SOA", "PTR", "SRV");
private static final Map<String, String> DOH = Map.of(
"google", "https://dns.google/resolve",
"cloudflare", "https://cloudflare-dns.com/dns-query",
"quad9", "https://dns.quad9.net:5053/dns-query"
);
private record ParsedArgs(Map<String, String> options, List<String> positional) {}
private record Task(String input, String queryName, String type) {}
private DnsResolver() {}
public static void main(String[] args) {
try {
ParsedArgs parsed = parseArgs(args);
List<String> types = parseTypes(parsed.options);
List<String> domains = parseDomains(parsed);
boolean reverse = parsed.options.containsKey("reverse");
boolean parallel = parsed.options.containsKey("parallel");
int threads = Math.max(1, Integer.parseInt(parsed.options.getOrDefault("threads", "10")));
Resolver resolver = createResolver(parsed.options.get("server"));
List<Task> tasks = new ArrayList<>();
for (String d : domains) {
String qname = (reverse && parsed.options.containsKey("doh")) ? ReverseMap.fromAddress(d).toString(true) : d;
List<String> qtypes = (reverse && !parsed.options.containsKey("doh")) ? List.of("PTR") : types;
for (String t : qtypes) tasks.add(new Task(d, qname, t));
}
List<Map<String, Object>> rows = Collections.synchronizedList(new ArrayList<>());
if (parallel && tasks.size() > 1) {
ExecutorService pool = Executors.newFixedThreadPool(threads);
try {
List<Future<?>> futures = new ArrayList<>();
for (Task t : tasks) {
futures.add(pool.submit(() -> {
List<Map<String, Object>> out = parsed.options.containsKey("doh")
? queryDoh(parsed.options.get("doh"), t.queryName, t.type)
: querySystem(resolver, t.queryName, t.type, reverse && t.type.equals("PTR"));
for (Map<String, Object> r : out) {
r.put("domain", t.input);
rows.add(r);
System.out.println(t.input + " " + t.type + " -> " + (r.get("value").toString().isBlank() ? r.get("error") : r.get("value")));
}
}));
}
for (Future<?> f : futures) f.get();
} finally {
pool.shutdown();
}
} else {
for (Task t : tasks) {
List<Map<String, Object>> out = parsed.options.containsKey("doh")
? queryDoh(parsed.options.get("doh"), t.queryName, t.type)
: querySystem(resolver, t.queryName, t.type, reverse && t.type.equals("PTR"));
for (Map<String, Object> r : out) {
r.put("domain", t.input);
rows.add(r);
System.out.println(t.input + " " + t.type + " -> " + (r.get("value").toString().isBlank() ? r.get("error") : r.get("value")));
}
}
}
rows.sort(Comparator.comparing((Map<String, Object> r) -> r.get("domain").toString())
.thenComparing(r -> r.get("type").toString())
.thenComparing(r -> r.get("value").toString()));
printRows(rows);
Map<String, Object> traces = null;
if (parsed.options.containsKey("trace")) {
traces = new LinkedHashMap<>();
for (String d : domains) ((Map<String, Object>) traces).put(d, trace(resolver, d));
System.out.println("\nTrace:");
for (String d : domains) {
System.out.println("- " + d);
List<Map<String, Object>> steps = (List<Map<String, Object>>) ((Map<String, Object>) traces).get(d);
for (Map<String, Object> s : steps) {
if (s.containsKey("ns")) System.out.println(" " + s.get("zone") + ": " + String.join(", ", (List<String>) s.get("ns")));
else System.out.println(" " + s.get("zone") + ": " + s.get("error"));
}
}
}
Map<String, Object> payload = new LinkedHashMap<>();
payload.put("generated_at", Instant.now().toString());
payload.put("options", parsed.options);
payload.put("results", rows);
if (traces != null) payload.put("traces", traces);
Path out = Paths.get(parsed.options.getOrDefault("output", "dns_results.json")).toAbsolutePath();
Files.writeString(out, GSON.toJson(payload), StandardCharsets.UTF_8);
System.out.println("\nSaved: " + out);
} catch (Exception ex) {
System.err.println("Error: " + ex.getMessage());
System.exit(1);
}
}
private static ParsedArgs parseArgs(String[] args) {
Map<String, String> opts = new LinkedHashMap<>();
List<String> pos = new ArrayList<>();
for (int i = 0; i < args.length; i++) {
String t = args[i];
if (t.startsWith("--")) {
String k = t.substring(2);
String v = "true";
if (i + 1 < args.length && !args[i + 1].startsWith("--")) v = args[++i];
opts.put(k, v);
} else pos.add(t);
}
return new ParsedArgs(opts, pos);
}
private static Resolver createResolver(String server) throws Exception {
if (server == null || server.isBlank()) return new ExtendedResolver();
SimpleResolver r = new SimpleResolver(server);
r.setTimeout(Duration.ofSeconds(5));
return r;
}
private static List<String> parseTypes(Map<String, String> opts) {
if (opts.containsKey("all")) return COMMON_TYPES;
String raw = opts.getOrDefault("type", "A");
List<String> out = new ArrayList<>();
for (String p : raw.split(",")) {
String t = p.trim().toUpperCase(Locale.ROOT);
if (!t.isBlank()) out.add(t);
}
return out;
}
private static List<String> parseDomains(ParsedArgs parsed) throws Exception {
List<String> out = new ArrayList<>();
if (!parsed.positional.isEmpty()) out.add(parsed.positional.get(0));
if (parsed.options.containsKey("file")) {
for (String line : Files.readAllLines(Paths.get(parsed.options.get("file")).toAbsolutePath(), StandardCharsets.UTF_8)) {
line = line.trim();
if (!line.isBlank()) out.add(line);
}
}
if (out.isEmpty()) out.addAll(DEFAULT_DOMAINS);
return out.stream().distinct().toList();
}
private static List<Map<String, Object>> querySystem(Resolver resolver, String domain, String type, boolean reverse) {
long start = System.nanoTime();
try {
Record[] records;
if (reverse) {
Name rev = ReverseMap.fromAddress(domain);
Lookup l = new Lookup(rev, Type.PTR);
l.setResolver(resolver);
records = l.run();
} else {
int t = Type.value(type);
Lookup l = new Lookup(Name.fromString(domain.endsWith(".") ? domain : domain + "."), t);
l.setResolver(resolver);
records = l.run();
}
double ms = (System.nanoTime() - start) / 1_000_000.0;
if (records == null || records.length == 0) {
return List.of(row(domain, type, "", null, ms, nameserverOf(resolver), "NoAnswer"));
}
List<Map<String, Object>> out = new ArrayList<>();
for (Record r : records) out.add(row(domain, type, r.rdataToString(), r.getTTL(), ms, nameserverOf(resolver), ""));
return out;
} catch (Exception ex) {
double ms = (System.nanoTime() - start) / 1_000_000.0;
return List.of(row(domain, type, "", null, ms, nameserverOf(resolver), ex.getMessage()));
}
}
private static String nameserverOf(Resolver r) {
if (r instanceof ExtendedResolver er && er.getResolvers().length > 0) {
Resolver first = er.getResolvers()[0];
if (first instanceof SimpleResolver sr && sr.getAddress() != null) return sr.getAddress().toString();
}
if (r instanceof SimpleResolver sr && sr.getAddress() != null) return sr.getAddress().toString();
return "system";
}
private static List<Map<String, Object>> queryDoh(String provider, String domain, String type) {
String base = DOH.getOrDefault(provider, provider);
long start = System.nanoTime();
try {
String url = base + "?name=" + URLEncoder.encode(domain, StandardCharsets.UTF_8) + "&type=" + URLEncoder.encode(type, StandardCharsets.UTF_8);
HttpClient client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(10)).build();
HttpRequest req = HttpRequest.newBuilder(URI.create(url))
.header("accept", "application/dns-json")
.GET()
.timeout(Duration.ofSeconds(10))
.build();
HttpResponse<String> res = client.send(req, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8));
if (res.statusCode() >= 400) throw new RuntimeException("DoH HTTP " + res.statusCode());
Map<String, Object> json = GSON.fromJson(res.body(), Map.class);
double ms = (System.nanoTime() - start) / 1_000_000.0;
Number status = (Number) json.getOrDefault("Status", 0);
if (status.intValue() != 0) return List.of(row(domain, type, "", null, ms, "doh:" + provider, "DoH status " + status.intValue()));
Object ans = json.get("Answer");
if (!(ans instanceof List<?> list) || list.isEmpty()) return List.of(row(domain, type, "", null, ms, "doh:" + provider, "NoAnswer"));
List<Map<String, Object>> out = new ArrayList<>();
for (Object o : list) {
if (!(o instanceof Map<?, ?> m)) continue;
String value = String.valueOf(m.getOrDefault("data", ""));
Number ttl = (Number) m.get("TTL");
out.add(row(domain, type, value, ttl == null ? null : ttl.longValue(), ms, "doh:" + provider, ""));
}
return out;
} catch (Exception ex) {
double ms = (System.nanoTime() - start) / 1_000_000.0;
return List.of(row(domain, type, "", null, ms, "doh:" + provider, ex.getMessage()));
}
}
private static List<Map<String, Object>> trace(Resolver resolver, String domain) {
String[] labels = domain.split("\\.");
List<Map<String, Object>> out = new ArrayList<>();
for (int i = 0; i < labels.length; i++) {
String zone = String.join(".", Arrays.copyOfRange(labels, i, labels.length));
try {
Lookup l = new Lookup(Name.fromString(zone.endsWith(".") ? zone : zone + "."), Type.NS);
l.setResolver(resolver);
Record[] rr = l.run();
if (rr == null || rr.length == 0) out.add(Map.of("zone", zone, "error", "No NS answer"));
else {
List<String> ns = new ArrayList<>();
for (Record r : rr) ns.add(r.rdataToString());
out.add(Map.of("zone", zone, "ns", ns));
}
} catch (Exception ex) {
out.add(Map.of("zone", zone, "error", ex.getMessage()));
}
}
return out;
}
private static Map<String, Object> row(String domain, String type, String value, Long ttl, double ms, String ns, String error) {
Map<String, Object> r = new LinkedHashMap<>();
r.put("domain", domain);
r.put("type", type);
r.put("value", value);
r.put("ttl", ttl);
r.put("response_ms", Math.round(ms * 100.0) / 100.0);
r.put("nameserver", ns);
r.put("error", error);
return r;
}
private static void printRows(List<Map<String, Object>> rows) {
System.out.println("Domain | Type | Value | TTL | Response(ms) | Nameserver | Error");
System.out.println("------ | ---- | ----- | --- | ------------ | ---------- | -----");
for (Map<String, Object> r : rows) {
System.out.printf(
"%s | %s | %s | %s | %s | %s | %s%n",
r.get("domain"),
r.get("type"),
r.get("value"),
r.get("ttl") == null ? "" : r.get("ttl"),
r.get("response_ms"),
r.get("nameserver"),
r.get("error")
);
}
}
}