From fb6a3a36b3a405e8041a86cd2ca7636c6e3fd965 Mon Sep 17 00:00:00 2001
From: Joel Grunbaum <joelgrun@gmail.com>
Date: Fri, 16 Oct 2020 12:49:56 +0000
Subject: [PATCH] Finished copying gist code
---
main.c | 252 ++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 242 insertions(+), 10 deletions(-)
diff --git a/main.c b/main.c
index 15ea1d1..7836ad1 100644
--- a/main.c
+++ b/main.c
@@ -3,9 +3,13 @@
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
-#include <netint/in.h>
+//#include <netint/in.h>
//#include <netdb.h>
#include <sys/time.h>
+#include <unistd.h>
+
+// DNS code copied from
+// https://gist.github.com/fffaraz/9d9170b57791c28ccda9255b48315168
// DNS resource records
#define T_A 1 // IPv4 address
@@ -15,30 +19,258 @@
#define T_PTR 12 // Domain name pointer
#define T_MX 15 // Mail exchange
-struct DNS_QUERY
+/* DNS header struct */
+struct DNS_HEADER
{
unsigned short id; //ID number
unsigned char rd :1; //recursion
- unsigned char aa :1; //truncated message
+ unsigned char tc :1; //truncated message
+ unsigned char aa :1; //authoritive answer
unsigned char opcode :4; //message purpose
- unsigned char qr :1; //query/response
+ unsigned char qr :1; //query response
unsigned char rcode :4; //response code
-
-}
+ unsigned char cd :1; //checking disabled
+ unsigned char ad :1; //authenticated data
+ unsigned char z :1; //reserved for future use
+ unsigned char ra :1; //recursion available
+ unsigned short q_count; //number of question entries
+ unsigned short ans_count; //number of answer entries
+ unsigned short auth_count; //number of authority entries
+ unsigned short add_count; //number of resource entries
+};
+
+/* structured for query structure */
+struct QUESTION
+{
+ unsigned short qtype;
+ unsigned short qclass;
+};
+
+/* Query structure */
+struct QUERY
+{
+ unsigned char* name;
+ struct QUESTION* ques;
+};
+
+/* Constant sized fields of record structure */
+#pragma pack(push, 1)
+struct R_DATA
+{
+ unsigned short type;
+ unsigned short _class;
+ unsigned int ttl;
+ unsigned short data_len;
+};
+#pragma pack(pop)
+
+/* Pointers to record components */
+struct RES_RECORD
+{
+ unsigned char* name;
+ struct R_DATA* resource;
+ unsigned char* rdata;
+};
+
+void resolve(char* hostname, char* dns_ip, int query_type, int read);
+void change_to_DNS_name_format(unsigned char* dns, unsigned char* host);
+u_char* read_name(unsigned char* reader, unsigned char* buffer, int* count);
int main(int argc, char** argv)
{
-
+ resolve("google.com", "1.1.1.1", T_A, 1);
+ return 0;
}
-void resolve(char* hostname, char* dns_ip)
+void resolve(char* hostname, char* dns_ip, int query_type, int read)
{
- int s;
- struct sockaddr_in dest;
+ int s, i, j;
+ struct sockaddr_in dest, a;
+ unsigned char buf[65536], *qname, *reader;
+ struct DNS_HEADER* dns = NULL;
+ struct QUESTION* qinfo = NULL;
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
dest.sin_family = AF_INET;
dest.sin_port = htons(53);
dest.sin_addr.s_addr = inet_addr(dns_ip);
+ //dns packet header
+ dns = (struct DNS_HEADER*)&buf;
+ dns->id = (unsigned short) htons(getpid());
+ dns->qr = 0; //make query
+ dns->opcode = 0; //standard query
+ dns->aa = 0; //not authoritive
+ dns->tc = 0; //not trucated
+ dns->rd = 1; //want recursion
+ dns->ra = 0; //recursion not available
+ dns->z = 0;
+ dns->ad = 0;
+ dns->cd = 0;
+ dns->rcode = 0;
+ dns->q_count = htons(1); //one question
+ dns->ans_count = 0;
+ dns->auth_count = 0;
+ dns->add_count = 0;
+
+ //dns packet query
+ qname = (unsigned char*)&buf[sizeof(struct DNS_HEADER)];
+ change_to_DNS_name_format(qname, (unsigned char*)hostname);
+ qinfo = (struct QUESTION*)&buf[sizeof(struct DNS_HEADER) + strlen((const char*)qname) + 1];
+ qinfo->qtype = htons(query_type); //type of query from argument (A,AAAA,MX,CNAME,NS,...)
+ qinfo->qclass = htons(1); //internet class
+
+ //send request
+ // return less than 0 is a fail
+ sendto(s,(char*)buf, sizeof(struct DNS_HEADER)+strlen((const char*)qname)+1+sizeof(struct QUESTION), 0, (struct sockaddr*)&dest, sizeof(dest));
+
+ //receive response
+ //negative return is a fail
+ i = sizeof(dest);
+ recvfrom(s, (char*)buf, 65536, 0, (struct sockaddr*)&dest, (socklen_t*)&i);
+
+ //read response
+ if (read) {
+ struct RES_RECORD answers[20], auth[20], addit[20];
+ int stop;
+ dns = (struct DNS_HEADER*)buf;
+ reader = &buf[sizeof(struct DNS_HEADER)+strlen((const char*)qname)+1+sizeof(struct QUESTION)];
+ printf("Response contains %d Qs, %d ans, %d auth serv, %d add reconds\n", ntohs(dns->q_count), ntohs(dns->ans_count), ntohs(dns->auth_count), ntohs(dns->add_count));
+ stop = 0;
+ for (i = 0; i < ntohs(dns->ans_count); i++) {
+ answers[i].name = read_name(reader, buf, &stop);
+ reader = reader + stop;
+ answers[i].resource = (struct R_DATA*)reader;
+ reader = reader+sizeof(struct R_DATA);
+
+ if (ntohs(answers[i].resource->type) == 1) { //IPv6 address
+ answers[i].rdata[j] = (unsigned char*)malloc(ntohs(answers[i].resource->data_len));
+ for (j = 0; j < ntohs(answers[i].resource->data_len); j++) {
+ answers[i].rdata[j] = reader[j];
+ }
+ answers[i].rdata[ntohs(answers[i].resource->data_len)] = '\0';
+ reader = reader + ntohs(answers[i].resource->data_len);
+ } else {
+ answers[i].rdata = read_name(reader, buf, &stop);
+ reader = reader + stop;
+ }
+ }
+
+ //read authorities
+ for (i = 0; i < ntohs(dns->auth_count); i++) {
+ auth[i].name = read_name(reader, buf, &stop);
+ reader += stop;
+ auth[i].resource = (struct R_DATA*)reader;
+ reader += sizeof(struct R_DATA);
+ auth[i].rdata = read_name(reader, buf, &stop);
+ reader += stop;
+ }
+
+ //read additional
+ for (i = 0; i < ntohs(dns->add_count); i++) {
+ addit[i].name = read_name(reader, buf, &stop);
+ reader += stop;
+ addit[i].resource = (struct R_DATA*)reader;
+ reader += sizeof(struct R_DATA);
+
+ if (ntohs(addit[i].resource->type) == 1) {
+ addit[i].rdata = malloc(ntohs(addit[i].resource->data_len));
+ for (j = 0; j < ntohs(addit[i].resource->data_len); j++)
+ addit[i].rdata[j] = reader[j];
+
+ addit[i].rdata[ntohs(addit[i].resource->data_len)] = '\0';
+ reader += ntohs(addit[i].resource->data_len);
+ } else {
+ addit[i].rdata = read_name(reader, buf, &stop);
+ reader += stop;
+ }
+ }
+
+ //print answers
+ printf("ans recs: %d\n", ntohs(dns->ans_count));
+ for (i = 0; i < ntohs(dns->ans_count); i++) {
+ printf("name: %s ", answers[i].name);
+ if (ntohs(answers[i].resource->type == T_A)) { //IPv4
+ long* p;
+ p = (long*)answers[i].rdata;
+ a.sin_addr.s_addr=(*p);
+ printf("has IPv4 addresss: %s", inet_ntoa(a.sin_addr));
+ } else if (ntohs(answers[i].resource->type) == T_CNAME) { //CNAME
+ printf("has alias: %s", answers[i].rdata);
+ }
+ putc('\n', stdout);
+ }
+
+ //print authorities
+ printf("Auth recs: %d\n", ntohs(dns->auth_count));
+ for (i = 0; i < ntohs(dns->auth_count); i++) {
+ printf("name: %s ", addit[i].name);
+ if (ntohs(addit[i].resource->type) == 1) {
+ long* p;
+ p = (long*)addit[i].rdata;
+ a.sin_addr.s_addr = *p;
+ printf("has IPv4 address: %s", inet_ntoa(a.sin_addr));
+ }
+ putc('\n', stdout);
+ }
+ }
+ return;
+}
+
+
+void change_to_DNS_name_format(unsigned char* dns, unsigned char* host)
+{
+ int lock = 0;
+ strcat((char*)host,".");
+
+ for (int i = 0; i < strlen((char*)host); i++) {
+ if (host[i] == '.') {
+ *dns++ = i-lock;
+ for (;lock<i;i++) {
+ *dns++ = host[lock];
+ }
+ lock++;
+ }
+ }
+ *dns++ = '\0';
+}
+
+u_char* read_name(unsigned char* reader, unsigned char* buffer, int* count)
+{
+ unsigned char* name;
+ unsigned int p=0, jumped=0, offset;
+ int i, j;
+ *count = 1;
+ name = (unsigned char*)malloc(256);
+ name[0]='\0';
+
+ while (*reader != 0) {
+ if (*reader >= 192) {
+ offset = (*reader)*256+ *(reader+1) - 49152;
+ reader = buffer+offset-1;
+ jumped=1;
+ } else {
+ name[p++]=*reader;
+ }
+ reader = reader+1;
+ if (jumped == 0) {
+ *count = *count+1;
+ }
+ }
+ name[p] = '\0';
+ if (jumped == 0) {
+ *count = *count + 1;
+ }
+
+ //convert from dns format to normal
+ for (i = 0; i < strlen((const char*)name); i++) {
+ p = name[i];
+ for (j = 0; j < p; j++) {
+ name[i] = name[i+1];
+ i++;
+ }
+ name[i] = '.';
+ }
+ name[i-1] = '\0';
+ return name;
}
--
Gitblit v1.10.0