From 8ee2bac0af0a194d99fb1073b5362b0cd5c07130 Mon Sep 17 00:00:00 2001
From: Joel Grunbaum <joelgrun@gmail.com>
Date: Sun, 18 Oct 2020 11:30:53 +0000
Subject: [PATCH] split dns into own file and printing into own function
---
Makefile | 12 +
main.c | 273 ---------------------------
dns.h | 12 +
dns.c | 269 ++++++++++++++++++++++++++
4 files changed, 294 insertions(+), 272 deletions(-)
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..80b5744
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,12 @@
+CC=gcc
+OBJ=main.o dns.o
+DEPS=dns.h
+CFLAGS=-g
+
+default: all
+
+%.o: %.c $(DEPS)
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+all: $(OBJ)
+ $(CC) $(CFLAGS) $^
diff --git a/dns.c b/dns.c
new file mode 100644
index 0000000..af08c44
--- /dev/null
+++ b/dns.c
@@ -0,0 +1,269 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+//#include <netint/in.h>
+//#include <netdb.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include "dns.h"
+
+// DNS code copied from
+// https://gist.github.com/fffaraz/9d9170b57791c28ccda9255b48315168
+
+/* DNS header struct */
+struct DNS_HEADER
+{
+ unsigned short id; //ID number
+ unsigned char rd :1; //recursion
+ 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 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)
+{
+ 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) {
+ print_packet(buf);
+ }
+ return;
+}
+
+void print_packet(unsigned char* buf)
+{
+ struct RES_RECORD answers[20], auth[20], addit[20];
+ struct DNS_HEADER *dns;
+ struct sockaddr_in a;
+ char* qname = buf+sizeof(struct DNS_HEADER), *reader;
+ int stop, i, j;
+ 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) == T_A) { //IPv4 address
+ answers[i].rdata = (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);
+ }
+}
+
+
+void change_to_DNS_name_format(unsigned char* dns, unsigned char* host)
+{
+ int lock = 0;
+ char h[300];
+ strcpy(h, host);
+ strcat((char*)h,".");
+
+ for (int i = 0; i < strlen((char*)h); i++) {
+ if (h[i] == '.') {
+ *dns++ = i-lock;
+ for (;lock<i;lock++) {
+ *dns++ = h[lock];
+ }
+ lock++;
+ }
+ }
+ *dns++ = '\0';
+}
+
+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 == 1) {
+ *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;
+}
diff --git a/dns.h b/dns.h
new file mode 100644
index 0000000..1443dbf
--- /dev/null
+++ b/dns.h
@@ -0,0 +1,12 @@
+// DNS resource records
+#define T_A 1 // IPv4 address
+#define T_NS // Name Server
+#define T_CNAME 5 // Cannonical name
+#define T_SOA 6 // State of Authority
+#define T_PTR 12 // Domain name pointer
+#define T_MX 15 // Mail exchange
+
+void resolve(char* hostname, char* dns_ip, int query_type, int read);
+void print_packet(unsigned char* buf);
+void change_to_DNS_name_format(unsigned char* dns, unsigned char* host);
+char* read_name(unsigned char* reader, unsigned char* buffer, int* count);
diff --git a/main.c b/main.c
index 3c5961c..1e36b9e 100644
--- a/main.c
+++ b/main.c
@@ -1,278 +1,7 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <arpa/inet.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
-#define T_NS // Name Server
-#define T_CNAME 5 // Cannonical name
-#define T_SOA 6 // State of Authority
-#define T_PTR 12 // Domain name pointer
-#define T_MX 15 // Mail exchange
-
-/* DNS header struct */
-struct DNS_HEADER
-{
- unsigned short id; //ID number
- unsigned char rd :1; //recursion
- 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 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);
+#include "dns.h"
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, int query_type, int read)
-{
- 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) == T_A) { //IPv4 address
- answers[i].rdata = (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;
- char h[300];
- strcpy(h, host);
- strcat((char*)h,".");
-
- for (int i = 0; i < strlen((char*)h); i++) {
- if (h[i] == '.') {
- *dns++ = i-lock;
- for (;lock<i;lock++) {
- *dns++ = h[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 == 1) {
- *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