I wrote it for support “some big corporate application”.
“Pure C” for portability.
# m5dc.exe 2019-02-25 11:52:10 UTC ######## THE BEGIN ######## 2019-02-25 11:52:10 UTC ############################## 2019-02-25 11:52:10 UTC start checking: traceroute for host web.xxxxx.lazurit.us 2019-02-25 11:52:11 UTC good: host web.ost.lazurit.us have ipv4 address 172.17.8.124 2019-02-25 11:52:11 UTC good: ttl= 1 icmp type 11 from 192.168.xxxx 2019-02-25 11:52:11 UTC good: ttl= 2 icmp type 11 from 192.168.xxxx 2019-02-25 11:52:11 UTC good: ttl= 3 icmp type 11 from 10.xxxxx 2019-02-25 11:52:11 UTC good: ttl= 4 icmp type 11 from 10.xxxxx 2019-02-25 11:52:11 UTC good: ttl= 5 icmp type 0 from 172.xxxxx 2019-02-25 11:52:11 UTC result: type ICMP_ECHOREPLY 2019-02-25 11:52:11 UTC result: icmp id 1234 2019-02-25 11:52:12 UTC result: icmp seq 4567 2019-02-25 11:52:12 UTC ############################## 2019-02-25 11:52:12 UTC start checking: web connect for host webxxxx.lazurit.us 2019-02-25 11:52:12 UTC good: host webxxxx.lazurit.us have ipv4 address 172.xxxxx 2019-02-25 11:52:12 UTC good: connected to 172.xxxxx port 80 2019-02-25 11:52:12 UTC good: wrote 143 bytes to 172.xxxxx port 80 2019-02-25 11:52:12 UTC good: read 319 bytes from 172.xxxx port 80 2019-02-25 11:52:12 UTC result: http responce code: HTTP/1.1 200 OK 2019-02-25 11:52:12 UTC ############################## 2019-02-25 11:52:13 UTC start checking: traceroute for host pgxxxxx.lazurit.us 2019-02-25 11:52:13 UTC good: host pgdb-mosaic-ost.lazurit.us have ipv4 address 172.xxxxxx 2019-02-25 11:52:13 UTC good: ttl= 1 icmp type 11 from 192.168.xxxxx 2019-02-25 11:52:13 UTC good: ttl= 2 icmp type 11 from 192.168.xxxxx 2019-02-25 11:52:13 UTC good: ttl= 3 icmp type 11 from 10.xxxxx 2019-02-25 11:52:13 UTC good: ttl= 4 icmp type 11 from 10.xxxxx 2019-02-25 11:52:13 UTC good: ttl= 5 icmp type 0 from 172.xxxxx 2019-02-25 11:52:14 UTC result: type ICMP_ECHOREPLY 2019-02-25 11:52:14 UTC result: icmp id 1234 2019-02-25 11:52:14 UTC result: icmp seq 4567 2019-02-25 11:52:14 UTC ############################## 2019-02-25 11:52:14 UTC start checking: postgreql connect for host pgxxxx.lazurit.us 2019-02-25 11:52:14 UTC good: connection to database is successful 2019-02-25 11:52:14 UTC good: request SELECT project_guid FROM projects5d LIMIT 5 is successful 2019-02-25 11:52:14 UTC result: column 0 have name project_guid 2019-02-25 11:52:14 UTC result: 5c609f5a-2857-4720-8273-70a9ccf7d9ee 2019-02-25 11:52:15 UTC result: b294735a-25f0-4292-aa1c-307dc898af89 2019-02-25 11:52:15 UTC result: c6efe350-668f-4784-a632-a9b1c9f1198a 2019-02-25 11:52:15 UTC result: a26abf9b-438e-46e2-b917-d147eeab985d 2019-02-25 11:52:15 UTC result: aaf27bb2-6d62-4458-baf8-260441a46adb 2019-02-25 11:52:15 UTC ######## THE END ########
/* $Id: m5dc.c,v 1.1 2019/02/20 13:01:37 ziggi Exp ziggi $ */ /* * Author, Copyright: Borodin Oleg <onborodin@gmail.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifdef __WINNT__ #define _WIN32_WINNT 0x0600 #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include <stdarg.h> #include <time.h> #include <limits.h> #include <unistd.h> #ifdef __WINNT__ #include <sys/types.h> #include <sys/stat.h> #include <winsock2.h> #include <ws2tcpip.h> #include <pshpack1.h> #else #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/ip_icmp.h> #include <netdb.h> #endif #ifdef __WINNT__ struct ip { u_char ip_hl:4; /* header length */ u_char ip_v:4; /* version */ u_char ip_tos; /* type of service */ u_short ip_len; /* total length */ u_short ip_id; /* identification */ u_short ip_off; /* fragment offset field */ u_char ip_ttl; /* time to live */ u_char ip_p; /* protocol */ u_short ip_sum; /* checksum */ struct in_addr ip_src; struct in_addr ip_dst; /* source and dest address */ } __packed; struct icmp { u_char icmp_type; u_char icmp_code; u_short icmp_cksum; u_short icmp_id; u_short icmp_seq; }; #endif typedef struct ip ip_hdr_t; typedef struct icmp icmp_hdr_t; #define LOG_BUFFER_SIZE 1024 void wc_log(const char *fmt, ...) { char buffer[LOG_BUFFER_SIZE]; memset(buffer, 0, LOG_BUFFER_SIZE); time_t rawtime = time(NULL); struct tm *ptm = gmtime(&rawtime); sprintf(buffer, "%04d-%02d-%02d %02d:%02d:%02d UTC ", ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec); char *record = buffer + strlen(buffer); va_list ap; va_start(ap, fmt); (void) vsnprintf(record, LOG_BUFFER_SIZE, fmt, ap); va_end(ap); printf("%s", buffer); #ifdef __WINNT__ FILE *log; if ((log = fopen("c:\\m5dc.log", "a")) == NULL) { if ((log = fopen("d:\\m5dc.log", "a")) == NULL) { printf("error: cannot open log file: %s\n", strerror(errno)); return; } } fprintf(log, "%s", buffer); fclose(log); #endif } static const char b64_table[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; char *b64_encode(const unsigned char *src, size_t len) { int i = 0; int j = 0; char *enc = NULL; size_t size = 0; unsigned char buf[4]; unsigned char tmp[3]; enc = (char *)malloc(1); if (NULL == enc) { return NULL; } while (len--) { tmp[i++] = *(src++); if (3 == i) { buf[0] = (tmp[0] & 0xfc) >> 2; buf[1] = ((tmp[0] & 0x03) << 4) + ((tmp[1] & 0xf0) >> 4); buf[2] = ((tmp[1] & 0x0f) << 2) + ((tmp[2] & 0xc0) >> 6); buf[3] = tmp[2] & 0x3f; enc = (char *)realloc(enc, size + 4); for (i = 0; i < 4; ++i) { enc[size++] = b64_table[buf[i]]; } i = 0; } } if (i > 0) { for (j = i; j < 3; ++j) { tmp[j] = '\0'; } buf[0] = (tmp[0] & 0xfc) >> 2; buf[1] = ((tmp[0] & 0x03) << 4) + ((tmp[1] & 0xf0) >> 4); buf[2] = ((tmp[1] & 0x0f) << 2) + ((tmp[2] & 0xc0) >> 6); buf[3] = tmp[2] & 0x3f; for (j = 0; (j < i + 1); ++j) { enc = (char *)realloc(enc, size + 1); enc[size++] = b64_table[buf[j]]; } while ((i++ < 3)) { enc = (char *)realloc(enc, size + 1); enc[size++] = '='; } } enc = (char *)realloc(enc, size + 1); enc[size] = '\0'; return enc; } uint16_t icmpv4_checksum(const uint16_t * const data, const size_t byte_sz) { if (0 != (byte_sz & 1)) { fprintf(stderr, "# wrong number of bytes %u must be even", (int)byte_sz); } uint32_t accu = 0; for (size_t i = 0; i < (byte_sz >> 1); ++i) { accu = accu + data[i]; } while (accu >> 16) { accu = (accu & 0xffff) + (accu >> 16); } const uint16_t checksum = ~accu; return checksum; } int __exit(void) { #ifdef __WINNT__ WSACleanup(); #endif exit(1); } void wc_close(int sock) { #ifdef __WINNT__ shutdown(sock, SD_BOTH); #else shutdown(sock, SHUT_RDWR); #endif close(sock); } struct sockaddr_in * wc_resolve(const char *hostname) { struct addrinfo hints; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; struct addrinfo *result = NULL; int retval; if ((retval = getaddrinfo(hostname, NULL, &hints, &result)) != 0) { wc_log("error: getaddrinfo() failed with error: %d\n", retval); __exit(); } struct sockaddr_in *sockaddr = NULL; for (struct addrinfo * ptr = result; ptr != NULL; ptr = ptr->ai_next) { switch (ptr->ai_family) { case AF_INET: sockaddr = (struct sockaddr_in *)ptr->ai_addr; wc_log("good: host %s have ipv4 address %s\n", hostname, inet_ntoa(sockaddr->sin_addr)); break; default: break; } if (sockaddr != NULL) { break; } } struct sockaddr_in *dest_sockaddr = NULL; if ((dest_sockaddr = malloc(sizeof(struct sockaddr))) == NULL) { wc_log("error: cannot allocate memory for address\n"); return NULL; } memset(dest_sockaddr, 0, sizeof(struct sockaddr)); memcpy(dest_sockaddr, sockaddr, sizeof(struct sockaddr_in)); freeaddrinfo(result); return dest_sockaddr; } #define SOCKET_ERROR (-1) #define PAYLOAD_LEN 4 #define OBUFFER_SIZE sizeof(icmp_hdr_t) + PAYLOAD_LEN #define ICMP_ECHOREPLY 0 #define ICMP_ECHO 8 #define ICMP_CODE 0 #define MAX_TTL 10 #define ICMP_IBUFFER_SIZE 204 #define SLEEP_TIME 100 #define SOCK_TIMEOUT 100 #define MAX_COUNT 4 void wping(char *hostname) { wc_log("##############################\n"); wc_log("start checking: traceroute for host %s\n", hostname); struct sockaddr_in *dest_sockaddr; if ((dest_sockaddr = wc_resolve(hostname)) == NULL) { wc_log("error: cannot resolve hostname %s\n", hostname); return; } #ifdef __WINNT__ char ttl; #else int ttl; #endif for (ttl = 1; ttl < MAX_TTL; ttl++) { int sock; if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) { wc_log("error: cannot create raw socker\n"); wc_close(sock); return; } char obuffer[OBUFFER_SIZE]; memset(obuffer, 0, OBUFFER_SIZE); icmp_hdr_t *icmp_hdr; icmp_hdr = (icmp_hdr_t *) obuffer; icmp_hdr->icmp_type = ICMP_ECHO; icmp_hdr->icmp_code = ICMP_CODE; icmp_hdr->icmp_id = htons(1234); icmp_hdr->icmp_cksum = 0; icmp_hdr->icmp_seq = htons(4567); char *payload = obuffer + sizeof(icmp_hdr_t); memset(payload, '<', PAYLOAD_LEN); icmp_hdr->icmp_cksum = icmpv4_checksum((uint16_t *) obuffer, OBUFFER_SIZE); #ifdef __WINNT__ if (setsockopt(sock, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)) < 0) { wc_log("error: setting ttl setsockopt failed\n"); wc_close(sock); return; } #else if (setsockopt(sock, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)) < 0) { wc_log("error: setting ttl setsockopt failed\n"); wc_close(sock); return; } #endif //wc_log("debug: send ICMP_ECHO with ttl = %d\n", ttl); if (sendto(sock, (char *)obuffer, OBUFFER_SIZE, 0, (struct sockaddr *)dest_sockaddr, sizeof(struct sockaddr_in)) < 0) { wc_log("error: sendto failed\n"); wc_close(sock); return; } char ibuffer[ICMP_IBUFFER_SIZE]; memset(ibuffer, 0, ICMP_IBUFFER_SIZE); struct sockaddr_in src_sockaddr; memset(&src_sockaddr, 0, sizeof(src_sockaddr)); socklen_t src_sockaddr_size = sizeof(src_sockaddr); int i = 0; while (i < MAX_COUNT) { //wc_log("debug: try icmp read %d\n", i); i++; #ifdef __WINNT__ int read_timeout = SOCK_TIMEOUT; if(setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char *)&read_timeout, sizeof(read_timeout)) < 0) { wc_log("error: set socket option failed\n"); wc_close(sock); return; } ssize_t res_count = recvfrom(sock, (char *)ibuffer, ICMP_IBUFFER_SIZE, 0, (struct sockaddr *)&src_sockaddr, &src_sockaddr_size); #else ssize_t res_count = recvfrom(sock, (char *)ibuffer, ICMP_IBUFFER_SIZE, MSG_DONTWAIT, (struct sockaddr *)&src_sockaddr, &src_sockaddr_size); #endif if (res_count > 0) { ip_hdr_t *ip_hdr = (struct ip *)ibuffer; size_t ip_header_len = ip_hdr->ip_hl >> 2; struct icmp *icmp_header = (struct icmp *)(ip_hdr + ip_header_len); wc_log("good: ttl= %d icmp type %d from %s\n", ttl, icmp_header->icmp_type, inet_ntoa(src_sockaddr.sin_addr)); if (icmp_header->icmp_type == ICMP_ECHOREPLY) { wc_log("result: type ICMP_ECHOREPLY\n"); wc_log("result: icmp id %d\n", ntohs(icmp_header->icmp_id)); wc_log("result: icmp seq %d\n", ntohs(icmp_header->icmp_seq)); return; } break; } if (i == MAX_COUNT) { wc_log("warning: ttl %d icmp timeout\n", ttl); break; } #ifdef __WINNT__ Sleep(SLEEP_TIME); #else usleep(SLEEP_TIME * 1000); #endif } close(sock); } } #define MAX_REQ_SIZE 65536 #define MAX_RES_SIZE 65536 #define IBUFFER_SIZE MAX_RES_SIZE #define WEBC_BUFFER_SIZE MAX_RES_SIZE #define LOGIN_PASSWORD_SIZE_MAX 256 #define ENCODED_LOGIN_SIZE_MAX 256 #define LOGIN_PASSWORD_DELIM ":" #include <errno.h> void wclient(const char *hostname, int port, char *url, char * login, char *password) { wc_log("##############################\n"); wc_log("start checking: web connect for host %s\n", hostname); struct sockaddr_in *dest_sockaddr; if ((dest_sockaddr = wc_resolve(hostname)) == NULL) { wc_log("error: cannot resolve hostname %s\n", hostname); return; } int sock; if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) { wc_log("error: cannot create socket\n"); return; } dest_sockaddr->sin_family = AF_INET; dest_sockaddr->sin_port = htons(port); char *dest_addr_str = inet_ntoa(dest_sockaddr->sin_addr); if (connect(sock, (struct sockaddr *)dest_sockaddr, sizeof(struct sockaddr_in)) < 0) { wc_log("error: cannot create connect to %s port %d : %s\n", dest_addr_str, port, strerror(errno)); wc_close(sock); return; } wc_log("good: connected to %s port %d\n", dest_addr_str, port); char obuffer[WEBC_BUFFER_SIZE]; memset(obuffer, 0, WEBC_BUFFER_SIZE); strcpy(obuffer, "GET "); strcat(obuffer, url); strcat(obuffer, " HTTP/1.1\n"); strcat(obuffer, "Host: "); strcat(obuffer, hostname); strcat(obuffer, "\n"); strcat(obuffer, "User-Agent: WClient/1.0\n"); char login_password[LOGIN_PASSWORD_SIZE_MAX]; strcpy(login_password, login); strcat(login_password, LOGIN_PASSWORD_DELIM); strcat(login_password, password); char *encoded_login = b64_encode((u_char *)login_password, strlen(login_password)); strcat(obuffer, "Authorization: Basic "); strcat(obuffer, encoded_login); strcat(obuffer, "\n"); free(encoded_login); strcat(obuffer, "Accept: */*\n"); strcat(obuffer, "\n"); //printf("debug: web req buffer: \n%s\n", obuffer); int wc; if ((wc = send(sock, obuffer, (int)strlen(obuffer), 0)) < 0) { wc_log("error: cannot write data to %s port %d\n", dest_addr_str, port); wc_close(sock); return; } wc_log("good: wrote %d bytes to %s port %d\n", wc, dest_addr_str, port); int rc; char ibuffer[WEBC_BUFFER_SIZE]; memset(ibuffer, 0, WEBC_BUFFER_SIZE); if ((rc = recv(sock, ibuffer, WEBC_BUFFER_SIZE, 0)) < 0) { wc_log("error: read error from %s port %d\n", dest_addr_str, port); } if (rc > 0) { wc_log("good: read %d bytes from %s port %d\n", rc, dest_addr_str, port); char res[WEBC_BUFFER_SIZE]; memset(res, 0, WEBC_BUFFER_SIZE); memcpy(res, ibuffer, WEBC_BUFFER_SIZE); char *ptr = strtok(res, "\n"); while(ptr != NULL) { if(strstr(ptr, "HTTP/1.1") != NULL) { wc_log("result: http responce code: %s\n", ptr); break; } //if(strlen(ptr) < 2) { // break; //} //wc_log("# %s\n", ptr); ptr = strtok(NULL, "\n"); } } wc_close(sock); return; } #include "libpq-fe.h" #define PG_CONNINFO_SIZE 256 void pgclient(char *hostname, char *port, char *dbname, char* user, char* password) { wc_log("##############################\n"); wc_log("start checking: postgreql connect for host %s\n", hostname); char conninfo[PG_CONNINFO_SIZE]; strcpy(conninfo, "host="); strcat(conninfo, hostname); strcat(conninfo, " port="); strcat(conninfo, port); strcat(conninfo, " dbname="); strcat(conninfo, dbname); strcat(conninfo, " user="); strcat(conninfo, user); strcat(conninfo, " password="); strcat(conninfo, password); //wc_log("debug: pg connect info: %s\n", conninfo); PGconn *conn = PQconnectdb(conninfo); if (PQstatus(conn) != CONNECTION_OK) { wc_log("error: connection to database failed: %s\n", PQerrorMessage(conn)); PQfinish(conn); return; } else { wc_log("good: connection to database is successful\n"); } const char *req = "SELECT project_guid FROM projects5d LIMIT 5"; PGresult *res = PQexec(conn, req); if (PQresultStatus(res) != PGRES_TUPLES_OK) { wc_log("error: request %s failed: %s\n", req, PQerrorMessage(conn)); PQclear(res); PQfinish(conn); return; } else { wc_log("good: request %s is successful\n", req); } int nCols = PQnfields(res); for (int i = 0; i < nCols; i++) { char *name = PQfname(res, i); wc_log("result: column %d have name %s\n", i, name); } int nRows = PQntuples(res); for (int i = 0; i < nRows; i++) { char *sum = PQgetvalue(res, i, 0); wc_log("result: %s\n", sum); } PQclear(res); PQfinish(conn); return; } #ifndef WEBHOST #define WEBHOST "webxxxxxxx" #endif #ifndef WEBPORT #define WEBPORT 80 #endif #ifndef WEBURL #define WEBURL "/xxxxx" #endif #ifndef WEBLOGIN #define WEBLOGIN "xxxxx" #endif #ifndef WEBPASSWORD #define WEBPASSWORD "xxxxxx" #endif #ifndef PGHOST #define PGHOST "xxxxxxx" #endif #ifndef PGPORT #define PGPORT "5432" #endif #ifndef DBNAME #define DBNAME "xxxxxxx" #endif #ifndef PGUSER #define PGUSER "xxxxxx" #endif #ifndef PGPASSWORD #define PGPASSWORD "xxxxxxxx" #endif int main(int argc, char **argv) { wc_log("######## THE BEGIN ########\n"); #ifdef __WINNT__ WSADATA wsaData; #define WSVERSION 0x0202 int iResult = WSAStartup(WSVERSION, &wsaData); if (iResult != 0) { wc_log("error: wsastartup() failed: %d\n", iResult); exit(1); } #endif wping(WEBHOST); wclient(WEBHOST, WEBPORT, WEBURL, WEBLOGIN, WEBPASSWORD); wping(PGHOST); pgclient(PGHOST, PGPORT, DBNAME, PGUSER, PGPASSWORD); wc_log("######## THE END ########\n\n"); #ifdef __WINNT__ WSACleanup(); printf("\nthe programm will sleep 30 sec\n"); Sleep(30 * 1000); #endif }