i continued my session with chatgpt to diagnose this weird name
resolution issue today a little.
as the session got longer the browser tab got slower and eventually
crashed on my old overloaded system
here is the dns resolver chatgpt made, in its typical procedural
style. the output looks nice, it successfully resolves the name when
glibc 2.40 won't.
most of the session was working with system configuration issues,
using other versions of glibc etc.
i didn't get to the point of making a clear network log of the failing
and working cases.
but it looks like even the latest glibc fails on this request.
it's stonkson.xyz from 8.8.8.8 today when connected to Lowe's wifi here
Sending DNS query for stonkson.xyz
Packet data (size: 30):
00000000 35 80 01 00 00 01 00 00 00 00 00 00 08 73 74 6f |5............sto|
00000010 6e 6b 73 6f 6e 03 78 79 7a 00 00 01 00 01 |nkson.xyz.....|
Received DNS response
Packet data (size: 73):
00000000 35 80 81 80 00 01 00 01 00 00 00 00 08 73 74 6f |5............sto|
00000010 6e 6b 73 6f 6e 03 78 79 7a 00 00 01 00 01 c0 0c |nkson.xyz.......|
00000020 00 05 00 01 00 00 00 01 00 1f 08 73 69 6e 6b 68 |...........sinkh|
00000030 6f 6c 65 10 70 61 6c 6f 61 6c 74 6f 6e 65 74 77 |ole.paloaltonetw|
00000040 6f 72 6b 73 03 63 6f 6d 00 |orks.com.|
Response ID: 0x3580
Flags: 0x8180
Questions: 1, Answers: 1, Authority Records: 0, Additional Records: 0
Answer 1: Type: 5, TTL: 1, Data length: 31
CNAME: .sinkhole.paloaltonetworks.com.
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/socket.h>
#include <ctype.h>
#define DNS_SERVER "8.8.8.8" // Google's public DNS server
#define DNS_PORT 53
#define BUFFER_SIZE 512
// Structure of a DNS header
struct dns_header {
unsigned short id; // Identification number
unsigned short flags; // DNS flags
unsigned short qcount; // Number of questions
unsigned short ancount; // Number of answers
unsigned short nscount; // Number of authority records
unsigned short arcount; // Number of additional records
};
// Structure of a DNS question
struct dns_question {
unsigned short qtype; // Question type
unsigned short qclass; // Question class
};
// Function to convert a domain name into the DNS format
void format_domain_name(unsigned char *dns, const char *host) {
char modifiable_host[256]; // Create a modifiable copy of the hostname
strncpy(modifiable_host, host, sizeof(modifiable_host) - 1);
modifiable_host[sizeof(modifiable_host) - 1] = '\0'; // Ensure null termination
strcat(modifiable_host, ".");
int lock = 0;
for (int i = 0; i < strlen(modifiable_host); i++) {
if (modifiable_host[i] == '.') {
*dns++ = i - lock;
for (; lock < i; lock++) {
*dns++ = modifiable_host[lock];
}
lock++;
}
}
*dns++ = '\0';
}
// Function to log a packet in hexadecimal and ASCII format (like hexdump -C)
void log_packet(unsigned char *packet, ssize_t size) {
printf("Packet data (size: %ld):\n", size);
for (ssize_t i = 0; i < size; i += 16) {
printf("%08lx ", i); // Offset
// Hexadecimal output
for (ssize_t j = 0; j < 16; j++) {
if (i + j < size) {
printf("%02x ", packet[i + j]);
} else {
printf(" "); // Padding
}
}
// ASCII output
printf(" |");
for (ssize_t j = 0; j < 16 && i + j < size; j++) {
printf("%c", isprint(packet[i + j]) ? packet[i + j] : '.');
}
printf("|\n");
}
printf("\n");
}
// Function to parse and display DNS response
void parse_dns_response(unsigned char *buffer, ssize_t size) {
struct dns_header *dns = (struct dns_header*) buffer;
printf("Response ID: 0x%04x\n", ntohs(dns->id));
printf("Flags: 0x%04x\n", ntohs(dns->flags));
printf("Questions: %d, Answers: %d, Authority Records: %d, Additional Records: %d\n",
ntohs(dns->qcount), ntohs(dns->ancount), ntohs(dns->nscount), ntohs(dns->arcount));
// Move pointer to the end of the DNS query section
unsigned char *reader = buffer + sizeof(struct dns_header);
while (*reader != 0) reader++; // Skip over the query name
reader += 5; // Skip the null byte and the query type/class
// Parse the answer section
for (int i = 0; i < ntohs(dns->ancount); i++) {
// Skip over the name pointer
reader += 2;
// Get the record type
unsigned short type = ntohs(*(unsigned short*)reader);
reader += 2;
// Get the class (usually IN)
reader += 2;
// Get the TTL
unsigned int ttl = ntohl(*(unsigned int*)reader);
reader += 4;
// Get the data length
unsigned short data_len = ntohs(*(unsigned short*)reader);
reader += 2;
printf("Answer %d: Type: %d, TTL: %u, Data length: %d\n", i + 1, type, ttl, data_len);
// If it's a CNAME (type 5) or an A record (type 1)
if (type == 5) {
printf("CNAME: ");
for (int j = 0; j < data_len; j++) {
if (reader[j] > 32 && reader[j] < 127) {
printf("%c", reader[j]);
} else {
printf(".");
}
}
printf("\n");
} else if (type == 1 && data_len == 4) { // A record (IPv4 address)
struct sockaddr_in a;
memcpy(&a.sin_addr.s_addr, reader, 4);
printf("Resolved A record: %s\n", inet_ntoa(a.sin_addr));
}
reader += data_len;
}
}
// Function to resolve a domain using raw sockets and display network logging
void resolve_a_record(const char *hostname) {
int sockfd;
struct sockaddr_in dest;
unsigned char buffer[BUFFER_SIZE];
// Create a socket for UDP communication
sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sockfd < 0) {
perror("Socket creation failed");
return;
}
// Set up destination (DNS server)
dest.sin_family = AF_INET;
dest.sin_port = htons(DNS_PORT);
dest.sin_addr.s_addr = inet_addr(DNS_SERVER);
// Build the DNS query
struct dns_header *dns = (struct dns_header *)&buffer;
dns->id = (unsigned short) htons(getpid()); // Random ID
dns->flags = htons(0x0100); // Standard query
dns->qcount = htons(1); // One question
dns->ancount = 0;
dns->nscount = 0;
dns->arcount = 0;
// Prepare the query
unsigned char *qname = (unsigned char*)&buffer[sizeof(struct dns_header)];
format_domain_name(qname, hostname);
struct dns_question *qinfo = (struct dns_question*)&buffer[sizeof(struct dns_header) + strlen((char*)qname) + 1];
qinfo->qtype = htons(1); // Type A
qinfo->qclass = htons(1); // Internet class
ssize_t query_size = sizeof(struct dns_header) + strlen((char*)qname) + 1 + sizeof(struct dns_question);
// Log the packet being sent
printf("Sending DNS query for %s\n", hostname);
log_packet(buffer, query_size);
// Send the DNS query
if (sendto(sockfd, buffer, query_size, 0, (struct sockaddr*)&dest, sizeof(dest)) < 0) {
perror("Sendto failed");
close(sockfd);
return;
}
// Receive the DNS response
socklen_t len = sizeof(dest);
ssize_t response_size = recvfrom(sockfd, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&dest, &len);
if (response_size < 0) {
perror("Recvfrom failed");
close(sockfd);
return;
}
// Log the response packet
printf("Received DNS response\n");
log_packet(buffer, response_size);
// Parse and display the DNS response
parse_dns_response(buffer, response_size);
close(sockfd);
}
int main() {
resolve_a_record("stonkson.xyz");
return 0;
}