diff options
Diffstat (limited to 'pa5_dns_resolver')
-rw-r--r-- | pa5_dns_resolver/Makefile | 8 | ||||
-rw-r--r-- | pa5_dns_resolver/lookup.c | 71 | ||||
-rw-r--r-- | pa5_dns_resolver/readme.md | 37 |
3 files changed, 116 insertions, 0 deletions
diff --git a/pa5_dns_resolver/Makefile b/pa5_dns_resolver/Makefile new file mode 100644 index 0000000..d256f8e --- /dev/null +++ b/pa5_dns_resolver/Makefile @@ -0,0 +1,8 @@ +OBJS = lookup.o +CFLAGS = -Wall + +all: $(OBJS) + cc $(CFLAGS) -o lookup $(OBJS) + +clean: + rm *.o *lookup hostnames.log diff --git a/pa5_dns_resolver/lookup.c b/pa5_dns_resolver/lookup.c new file mode 100644 index 0000000..5b8e4cd --- /dev/null +++ b/pa5_dns_resolver/lookup.c @@ -0,0 +1,71 @@ +// Jack Sangdahl +// CSCI3753 SP24 +// PA5 DNS infoolver +#include <arpa/inet.h> +#include <errno.h> +#include <netdb.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/time.h> +#define MAX_NAME_LENGTH 16 // longest string in data/ +#define MAX_NAME_COUNT 24 // longest file by lines in data/ +struct addrinfo hints; + +char *domain_ip(char *domain) { + char *res = (char *)malloc(sizeof(char) * INET_ADDRSTRLEN); + struct addrinfo *info, *i; + if (getaddrinfo(domain, NULL, &hints, &info)) + return (char *)"NOT_RESOLVED"; + for (i = info; i != NULL; i = i->ai_next) { + struct sockaddr_in *ipv4 = (struct sockaddr_in *)i->ai_addr; + char ipstr[INET_ADDRSTRLEN]; // INET_ADDRSTRLEN translates to 16 + inet_ntop(AF_INET, &(ipv4->sin_addr), ipstr, INET_ADDRSTRLEN); + strcpy(res, ipstr); + break; + } + freeaddrinfo(info); + return res; +} + +int main(int argc, char **argv) { + if (argc < 3) { + fprintf(stdout, "usage: %s <log_file> [ <datafile> ...]\n", argv[0]); + return EXIT_FAILURE; + } + struct timeval begin, end; + gettimeofday(&begin, NULL); + if (!memset(&hints, 0, sizeof(hints))) { + fprintf(stderr, "ERROR: memset failed\n"); + return EXIT_FAILURE; + } + hints.ai_family = AF_INET; // limit to only ipv4 + hints.ai_socktype = SOCK_STREAM; // limit to tcp ports + FILE *log_file = fopen(argv[1], "w"); + for (uint8_t i = 1; i < argc; i++) { + FILE *data_file = fopen(argv[i], "r"); + if (!data_file) { + fprintf(stdout, "ERROR: %s\n", strerror(errno)); + return EXIT_FAILURE; + } + char buffer[MAX_NAME_LENGTH]; + char **hostnames = (char **)malloc(sizeof(char *) * MAX_NAME_COUNT); + uint8_t name_cnt = 0; + while (fgets(buffer, sizeof(buffer), data_file)) { + hostnames[name_cnt] = (char *)malloc(sizeof(char) * (strlen(buffer) + 1)); + buffer[strcspn(buffer, "\n")] = 0; + strcpy(hostnames[name_cnt], buffer); + name_cnt++; + } + for (uint8_t i = 0; i < name_cnt; i++) + fprintf(log_file, "%s, %s\n", hostnames[i], domain_ip(hostnames[i])); + free(hostnames); + fclose(data_file); + } + fclose(log_file); + gettimeofday(&end, NULL); + double runtime = (double)(end.tv_usec - begin.tv_usec) / 1000000 + + (double)(end.tv_sec - begin.tv_sec); + fprintf(stdout, "%s: total time is %f seconds\n", argv[0], runtime); + return EXIT_SUCCESS; +} diff --git a/pa5_dns_resolver/readme.md b/pa5_dns_resolver/readme.md new file mode 100644 index 0000000..c213c9b --- /dev/null +++ b/pa5_dns_resolver/readme.md @@ -0,0 +1,37 @@ +## PA5 - DNS Resolver +### overview +this assignment will develop an application that resolves domain names +to ip addresses. this is similar to the operation performed each time +you access a new website in your browser. provided are a set of input +files that contain one hostname per line. your program will process each +of these files by reading the file line by line, look up the ip address +for that hostname, and then write the hostname and ip address to the +specified log file using the following format: +``` +google.com, 74.125.224.81 +``` +if the resolved is unable to fid the ip address for a hostname, it +should leave `NOT_RESOLVED` instead of an ip address. the program must +end after all names in each input file have been serviced by the +application. prior to exiting, the program should print the total time +taken to stdout +``` +./lookup: total time is 2.420237 seconds +``` +`gettimeofday()` library function is recommended for this purpose. + +### error handling +program should deal with the following conditions +* missing arguments - terminate with a usage synopsis to stdout +* arguments that are out of range (ie. too many input files) should +terminate with an error message to stderr +* if a log file exists and is writeable, it should be overwritten +* if a log file does not exist, it should be created by the program +* missing or unreadable input files should print `invalid file <filename>` +to stderr, then move onto next file + +all system and library calls should be checked for errors. if you +encounter errors not listed above, you should print an appropriate +message to stderr, and then either exit or continue depending up +whether or not you can recover from the error gracefully. make sure +your program returns an appropriate exit status. |