/* WHOIS port for KolibriOS (Adapted by turbocat2001). The main code is taken from the site: https://www.binarytides.com/whois-client-code-in-c-with-linux-sockets/ */ #include "sys/ksys.h" #include #include #include #include #include #include #include FILE* out = stdout; #ifdef DEBUG FILE* out = stderr; #endif #define EXIT_SUCCESS 0 #define EXIT_FAILURE 1 #define fprintf fprintf void show_help() { puts("Usage: whois [-f ]\n"); puts(" host Connect to server host"); puts(" -f file Redirecting output to file\n"); puts("Example: whois google.com -f my.txt"); } int get_whois_data(char*, char**); int hostname_to_ip(char*, char*); int whois_query(char*, char*, char**); char* str_replace(char* search, char* replace, char* subject); char* str_copy(char*); int main(int argc, char* argv[]) { char *domain, *data = NULL; int f_flag = 0; if (argc == 2) { domain = strdup(argv[1]); } else if (!strcmp(argv[2], "-f") && argc == 4) { domain = strdup(argv[1]); if ((out = fopen(argv[3], "w")) == NULL) { printf("Error writing to file: '%s' !\n", argv[3]); exit(0); } } else { show_help(); exit(0); } if (out == stdout) { con_init(); (*con_set_title)("Whois"); } get_whois_data(domain, &data); exit(0); } /* Get the whois data of a domain */ int get_whois_data(char* domain, char** data) { char ext[1024], *pch, *response = NULL, *response_2 = NULL, *wch, *dt; // remove "http://" and "www." domain = str_replace("http://", "", domain); domain = str_replace("www.", "", domain); // get the extension , com , org , edu dt = strdup(domain); if (dt == NULL) { fprintf(out, "strdup failed"); } pch = (char*)strtok(dt, "."); while (pch != NULL) { strcpy(ext, pch); pch = strtok(NULL, "."); } // This will tell the whois server for the particular TLD like com , org if (whois_query("whois.iana.org", ext, &response) == EXIT_FAILURE) { fprintf(out, "Whois query failed"); return 1; } fprintf(out, "\n\nResponse is:\n\n"); fprintf(out, "%s", response); // Now analysze the response pch = strtok(response, "\n"); while (pch != NULL) { // Check if whois line wch = strstr(pch, "whois."); if (wch != NULL) { break; } // Next line please pch = strtok(NULL, "\n"); } // Now we have the TLD whois server in wch , query again // This will provide minimal whois information along with the parent whois server of the specific domain :) wch = strdup(wch); free(response); // This should not be necessary , but segmentation fault without this , why ? response = NULL; if (wch != NULL) { fprintf(out, "\nTLD Whois server is : %s", wch); if (whois_query(wch, domain, &response) == EXIT_FAILURE) { fprintf(out, "Whois query failed\n"); return EXIT_FAILURE; } } else { fprintf(out, "\nTLD whois server for %s not found\n", ext); return EXIT_SUCCESS; } response_2 = strdup(response); // Again search for a whois server in this response. :) pch = strtok(response, "\n"); while (pch != NULL) { // Check if whois line wch = strstr(pch, "whois."); if (wch != NULL) { break; } // Next line please pch = strtok(NULL, "\n"); } /* If a registrar whois server is found then query it */ if (wch) { // Now we have the registrar whois server , this has the direct full information of the particular domain // so lets query again fprintf(out, "\nRegistrar Whois server is : %s", wch); if (whois_query(wch, domain, &response) == EXIT_FAILURE) { fprintf(out, "Whois query failed"); } else { fprintf(out, "\n%s", response); } } /* otherwise echo the output from the previous whois result */ else { fprintf(out, "%s", response_2); } return 0; } /* Perform a whois query to a server and record the response */ int whois_query(char* server, char* query, char** response) { char ip[32], message[100], buffer[1500]; int sock, read_size, total_size = 0; int WHOIS_PORT = 43; struct sockaddr dest; sock = socket(AF_INET4, SOCK_STREAM, IPPROTO_TCP); // Prepare connection structures :) memset(&dest, 0, sizeof(dest)); dest.sin_family = AF_INET; server = str_copy(server); server[strcspn(server, "\r\n")] = '\0'; fprintf(out, "\nResolving: %s ...\n", server); if (hostname_to_ip(server, ip) == EXIT_FAILURE) { fprintf(out, "Failed\n"); return EXIT_FAILURE; } fprintf(out, "Found ip: %s \n", ip); dest.sin_addr = inet_addr(ip); dest.sin_port = PORT(WHOIS_PORT); ; // Now connect to remote server if (connect(sock, (const struct sockaddr*)&dest, sizeof(dest)) < 0) { perror("connect failed"); perror(strerror(errno)); return EXIT_FAILURE; } // Now send some data or message fprintf(out, "\nQuerying for: %s ...\n", query); sprintf(message, "%s\r\n", query); if (send(sock, message, strlen(message), 0) < 0) { perror("send failed"); return EXIT_FAILURE; } // Now receive the response while ((read_size = recv(sock, buffer, sizeof(buffer), 0))) { *response = realloc(*response, read_size + total_size); if (*response == NULL) { fprintf(out, "realloc failed"); return EXIT_FAILURE; } memcpy(*response + total_size, buffer, read_size); total_size += read_size; } fprintf(out, "Done\n"); *response = realloc(*response, total_size + 1); *(*response + total_size) = '\0'; close(sock); return EXIT_SUCCESS; } /* Get the ip address of a given hostname */ int hostname_to_ip(char* hostname, char* ip) { struct addrinfo* addr_info; char port_str[16]; sprintf(port_str, "%d", 80); struct addrinfo hints; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; // IPv4 or IPv6 doesnt matter hints.ai_socktype = SOCK_STREAM; // TCP stream sockets if (getaddrinfo(hostname, port_str, 0, &addr_info) != 0) { freeaddrinfo(addr_info); return EXIT_FAILURE; } else { strcpy(ip, inet_ntoa(addr_info->ai_addr->sin_addr)); return EXIT_SUCCESS; } } /* Search and replace a string with another string , in a string */ char* str_replace(char* search, char* replace, char* subject) { char *p = NULL, *old = NULL, *new_subject = NULL; int c = 0, search_size; search_size = strlen(search); // Count how many occurences for (p = strstr(subject, search); p != NULL; p = strstr(p + search_size, search)) { c++; } // Final size c = (strlen(replace) - search_size) * c + strlen(subject); // New subject with new size new_subject = malloc(c); // Set it to blank strcpy(new_subject, ""); // The start position old = subject; for (p = strstr(subject, search); p != NULL; p = strstr(p + search_size, search)) { // move ahead and copy some text from original subject , from a certain position strncpy(new_subject + strlen(new_subject), old, p - old); // move ahead and copy the replacement text strcpy(new_subject + strlen(new_subject), replace); // The new start position after this search match old = p + search_size; } // Copy the part after the last search match strcpy(new_subject + strlen(new_subject), old); return new_subject; } char* str_copy(char* source) { char* copy = malloc(strlen(source) + 1); if (copy) { strcpy(copy, source); } return copy; }