forked from KolibriOS/kolibrios
99922e4c2c
git-svn-id: svn://kolibrios.org@9766 a494cfbc-eb01-0410-851d-a64ba20cac60
299 lines
7.9 KiB
C
299 lines
7.9 KiB
C
/*
|
|
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 <clayer/network.h>
|
|
#include <conio.h>
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/socket.h>
|
|
|
|
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 <host> [-f <file>]\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;
|
|
}
|