Having a large file containing DNS names line-by-line (such as spam domains), the task is to check whether each domain-name can be resolved. The code below can be compiled with:
gcc checkdns.c -lpthread -o checkdns
and the resulting program can be executed, by taking a file containing domains line-by-line as parameter and the number of threads to use. For example:
./checkdns -d domains.txt -t 50
will read the file domains.txt
and create 50
resolver threads. Any domain that resolves properly will be spat out on stdout
whereas failing domains will silently be suppressed.
/////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 // // Please see: http://www.gnu.org/licenses/gpl.html for legal details, // // rights of fair usage, the disclaimer and warranty conditions. // /////////////////////////////////////////////////////////////////////////// #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <ctype.h> #include <pthread.h> #include <string.h> #include <netdb.h> int active_workers = 0; void *check(void *host) { struct hostent *ent = gethostbyname(host); if (!ent || strlen(ent->h_name) == 0) goto release; fprintf(stdout, "%s\n", ent->h_name); fflush(stdout); release: --active_workers; } int main(int argc, char **argv) { pthread_t *threads; int max_workers = 1; int i; char **domains; int domaincount = 0; char **nameservers; int nameservercount = 0; FILE *fp; size_t len = 0; ssize_t read; char *line; while ((i = getopt(argc, argv, "d:t:")) != -1) { switch (i) { case 't': max_workers = atoi(optarg); threads = (pthread_t *) malloc(max_workers * sizeof(pthread_t)); break; case 'd': if ((fp = fopen(optarg, "r")) == NULL) { fprintf(stderr, "cannot open domains file\n"); return 1; } domains = (char **) malloc(sizeof(char **)); while ((read = getline(&line, &len, fp)) != -1) { domains[domaincount] = (char *) malloc(read * sizeof(char)); strncpy(domains[domaincount], line, read - 1); domains = (char **) realloc(domains, ++domaincount * sizeof(char **) + sizeof(domains)); } break; default: fprintf(stderr, "syntax: %s <-d domains.txt> <-t number>\n"); return 1; } } if(domaincount == 0) { fprintf(stderr, "syntax: %s <-d domains.txt> <-t number>\n"); return 1; } --domaincount; do { wind: if (active_workers >= max_workers) { usleep(100); goto wind; } i = max_workers - 1; do { pthread_create(&threads[i], NULL, check, (void *) domains[domaincount--]); ++active_workers; } while (--i > -1); } while (domaincount > 0); return 0; }