First commit

This commit is contained in:
Maxime Menault 2024-09-16 20:38:18 +02:00
parent f7b5f773b1
commit f09be2ba12
15 changed files with 759 additions and 0 deletions

View File

@ -0,0 +1,7 @@
#ifndef DAEMON_H
#define DAEMON_H
int create_daemon();
void daemon_work();
#endif

View File

@ -0,0 +1,8 @@
#ifndef DB_SQLITE_H
#define DB_SQLITE_H
int db_connect();
int db_disconnect();
int insert_hourly_report(double mean,double max,double min,int high,int loss,int reached);
#endif

View File

@ -0,0 +1,4 @@
#ifndef PING_REPORT_H
#define PING_REPORT_H
#endif

View File

@ -0,0 +1,8 @@
#ifndef STATS_H
#define STATS_H
/*@null@*/char* get_ping_from_temp_log();
void write_ping_log(char* new_ping);
void set_stats_ping();
#endif

View File

@ -0,0 +1,9 @@
#ifndef UTILS_H
#define UTILS_H
#define STATUS_LOG "/var/log/ping-report/status.log"
void write_pid_file();
void remove_file(char* filename);
#endif

View File

View File

@ -0,0 +1,58 @@
CREATE TABLE HourlyReport(
ping_max FLOAT NOT NULL,
ping_min FLOAT NOT NULL,
ping_mean FLOAT NOT NULL,
nb_ping_high INT NOT NULL,
nb_ping_loss INT NOT NULL,
nb_ping_reached INT NOT NULL,
report_day DATE NOT NULL,
report_hour INT NOT NULL
);
CREATE VIEW DailyReport AS
SELECT
H.report_day,
MAX(H.ping_max) AS daily_worst_ping,
MIN(H.ping_min) AS daily_best_ping,
AVG(H.ping_mean) AS daily_mean_ping,
SUM(H.nb_ping_high) AS daily_high_ping,
SUM(H.nb_ping_loss) AS daily_loss_ping,
SUM(H.nb_ping_reached) AS daily_reached_ping,
(
SELECT
SH.report_hour
FROM
HourlyReport SH
WHERE
SH.ping_mean = (
SELECT
MIN(SSH.ping_mean)
FROM
HourlyReport SSH
WHERE
SSH.report_day = sh.report_day
)
AND
SH.report_day = H.report_day
) daily_best_hour,
(
SELECT
SH.report_hour
FROM
HourlyReport SH
WHERE
SH.ping_mean = (
SELECT
MAX(SSH.ping_mean)
FROM
HourlyReport SSH
WHERE
SSH.report_day = sh.report_day
)
AND
SH.report_day = H.report_day
) daily_worst_hour
FROM
HourlyReport H
GROUP BY
report_day

34
ping-report/res/ping-report.sh Executable file
View File

@ -0,0 +1,34 @@
#!/bin/bash
BIN=/opt/ping-report/bin/ping-report
PID=/var/log/ping-report/pid.log
STATUS=/var/log/ping-report/status.log
case $1 in
start) sudo echo "STARTED" > $STATUS;
sudo $BIN;
echo "ping-report started";;
end) sudo echo "STOP" > $STATUS;
sudo rm $PID;
sleep 2;
sudo echo "ENDED" > $STATUS;
echo "ping-report ended";;
kill) sudo kill `cat $PID`;
sudo rm $PID;
sudo echo "ENDED" > $STATUS;
echo "ping-report killed";;
restart) sudo echo "STOP" > $STATUS;
sleep 2;
sudo rm $PID;
sudo echo "STARTED" > $STATUS;
sudo $BIN;
echo "ping-report restarted";;
status) if test -f "$PID"; then
echo "ping-report is alive";
else
echo "ping-report is not started";
fi;;
*) echo "Usage : ping-report [start | end | kill | restart]";
exit 1;;
esac

218
ping-report/src/daemon.c Normal file
View File

@ -0,0 +1,218 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include "../include/daemon.h"
#include "../include/utils.h"
#include "../include/stats.h"
#include "../include/db-sqlite.h"
/*
-- create_daemon --
Desc :
Function which create a daemon
In-param :
None
Out-param :
None
Return value :
-1 : Error fork
0 : Daemon branch
1 : Parent process branch
*/
int create_daemon(){
/* Variables */
pid_t pid;
int fd;
/* Fork a new process */
pid = (pid_t) fork();
if(pid < 0){
/* Error while forking */
/* todo : add log */
return -1;
}
if(pid > 0){
/* Parent process branch : quit function */
return 1;
}
/* Son process branch */
/* Set file permissions */
(void) umask(0);
/* Change working directory to root directory */
(void) chdir("/");
/* Close all open file descriptors */
for(fd = (int) sysconf(_SC_OPEN_MAX); fd >= 0; fd--){
(void) close(fd);
}
return 0;
}
/*
-- ping_request --
Desc :
Ping the DNS (1.1.1.1) then write the ping in log file
In-param :
None
Out-param :
None
Return value :
None
*/
static void ping_request(){
/* Variables */
char* ping;
static char command[128] = "ping -c 1 1.1.1.1 > /var/log/ping-report/last-ping.log";
/* ping command */
(void) system(command);
/* Get ping value as a string */
ping = get_ping_from_temp_log();
if(ping != NULL) {
/* Write ping in all-ping.log */
write_ping_log(ping);
}
}
/*
-- send_check --
Desc :
Send if send_stats_ping is needed and if so, do it
In-param :
None
Out-param :
None
Return value :
None
*/
static void send_check(){
/* Variables */
time_t t;
struct tm* utc_time;
static int flag = 1;
/* Get time */
t = time(NULL);
utc_time = localtime(&t);
/* Set flag to avoid sending multiple time the same data at HH:00 */
if((utc_time->tm_min != 0)&& (flag == 0)){
flag = 1;
}
/* if time == HH:00, insert stats in db */
if((utc_time->tm_min == 0) && (flag != 0)){
set_stats_ping();
remove_file("/var/log/ping-report/all-ping.log");
flag = 0;
}
}
/*
-- check_keep_working --
Desc :
Check if ping-report need to be ended
In-param :
None
Out-param :
None
Return value :
keep_working : 1 continue, 0 end
*/
static int check_keep_working(){
/* Variables */
FILE* fd;
char read_line[5];
fd = fopen(STATUS_LOG,"r");
if(fd == NULL){
// Error occured while reading status log file, stop ping-report
printf("Err\n");
return 0;
}
/* Read file */
if(fread(read_line,sizeof(char),4,fd) != 0){
(void) fclose(fd);
read_line[4] = '\0';
if(strcmp(read_line,"STOP") == 0){
// stop ping-report
printf("Stop\n");
return 0;
}else{
// continue ping-report
printf("%s : Continue\n",read_line);
return 1;
}
}else{
// Error occured while reading status log file, stop ping-report
printf("Nothing to read\n");
(void) fclose(fd);
return 1;
}
}
/*
-- daemon_work --
Desc :
Function which contain main loop of the daemon
In-param :
None
Out-param :
None
Return value :
None
*/
void daemon_work(){
/* Variables */
int keep_working = 1;
/* Write daemon pid in log file */
write_pid_file();
/* Connect db sqlite */
if(db_connect()){
return;
}
/* Main loop */
while(keep_working != 0){
/* Launch ping command */
ping_request();
/* Send stats if time is correct */
send_check();
/* Check end ping-report */
keep_working = check_keep_working();
/* ping_interval 100 ms */
usleep(100*1000);
}
/* Disconnect sqlite db */
db_disconnect();
}

View File

@ -0,0 +1,66 @@
#include <stdio.h>
#include <sqlite3.h>
#include <time.h>
#include "../include/stats.h"
#include "../include/db-sqlite.h"
/* Globals for this file */
static sqlite3 *db = NULL;
static char db_filename[] = "/srv/ping-report/ping-report.db";
/*
-- db_connect --
Desc :
Connect the sqlite db
In-param :
None
Out-param :
None
Return value :
sqlite3_open rc
*/
int db_connect(){
return sqlite3_open(db_filename,&db);
}
/*
-- db_disconnect --
Desc :
Disconnect the sqlite db
In-param :
None
Out-param :
None
Return value :
sqlite3_close rc
*/
int db_disconnect(){
return sqlite3_close(db);
}
/*
-- insert_hourly_report --
Desc :
Insert ping hourly stats
In-param :
ping value
Out-param :
None
Return value :
sqlite3_exec rc
*/
int insert_hourly_report(double mean, double max, double min, int high, int loss, int reached){
int rc = 0;
char statement[128];
time_t t = time(NULL);
struct tm* tm = localtime(&t);
(void) snprintf(statement,128,"INSERT INTO HourlyReport VALUES (%lf,%lf,%lf,%d,%d,%d,'%d-%d-%d',%d)",
max,min,mean,high,loss,reached,tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour);
rc = sqlite3_exec(db,statement,NULL,NULL,NULL);
return rc;
}

View File

@ -0,0 +1,38 @@
#include "../include/daemon.h"
/*
-- main --
Desc :
Main function
In-param :
argc : argument count
argv : argument list
Out-param :
None
Return value :
0 : Normal end of program
1 : Error while creating daemon
2 : Parent process quit
3 : Unknown error
*/
int main(/*int argc, char** argv*/){
/* Daemon creation */
switch(create_daemon()){
case 0:
/* Daemon execution */
daemon_work();
break;
case -1:
/* Error : quit program */
return 1;
case 1:
/* Parent process : quit program */
return 2;
default:
return 3;
}
return 0;
}

249
ping-report/src/stats.c Normal file
View File

@ -0,0 +1,249 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <regex.h>
#include "../include/utils.h"
#include "../include/stats.h"
#include "../include/db-sqlite.h"
/*
-- get_ping_from_temp_log --
Desc :
Function which get the ping from a temp log containing the last ping did by the program
In-param :
None
Out-param :
None
Return value :
Ping value as a string or NULL if an error occured
*/
/*@null@*/char* get_ping_from_temp_log(){
/* Variables */
FILE* fd = NULL;
char* read_line = NULL;
size_t n = 0;
size_t nmatch = 2;
regex_t *p_reg;
regmatch_t* pmatch;
char* ping = NULL;
int start;
int end;
size_t size_ping;
/* regex struct memory allocation */
p_reg = (regex_t *) malloc(sizeof(*p_reg));
if(p_reg == NULL){
return ping; /* NULL */
}
/* Open ping log file */
fd = fopen("/var/log/ping-report/last-ping.log","r");
if(fd == NULL){
free(p_reg);
return ping; /* NULL */
}
/* Construct regex to get ping from log file */
if(regcomp(p_reg,"time=(.*) ms",REG_EXTENDED) != 0){
if(p_reg != NULL){
free(p_reg);
}
(void) fclose(fd);
return ping; /* NULL */
}
/* match info memory allocation */
pmatch = malloc(sizeof(*pmatch) * nmatch);
if(pmatch == NULL){
(void) fclose(fd);
regfree(p_reg);
free(p_reg);
return ping; /* NULL */
}
/* Read file */
while(getline(&read_line,&n,fd) != -1){
if(read_line == NULL){
break;
}
/* Exec regex to find ping */
if(regexec(p_reg,read_line,nmatch,pmatch,0) == 0){
/* Extract ping position from read line */
start = (int) pmatch[1].rm_so;
end = (int) pmatch[1].rm_eo;
size_ping = (size_t) (end - start);
/* ping string memory allocation */
ping = malloc(sizeof(char) * (size_ping+2));
if(ping == NULL){
free(read_line);
read_line = NULL;
n = 0;
break;
}
/* Create ping string */
(void) strncpy(ping, &read_line[start], size_ping);
ping[size_ping]='\n';
ping[size_ping+1]='\0';
/* Free memory */
free(read_line);
read_line = NULL;
n = 0;
break;
}
free(read_line);
read_line = NULL;
n = 0;
}
/* free allocated memory */
regfree(p_reg);
free(p_reg);
free(pmatch);
if(read_line != NULL){
free(read_line);
}
(void) fclose(fd);
/* ping may be null, then it must mean that the ping request was lost */
return ping;
}
/*
-- write_ping_log --
Desc :
Function which write a given ping in log file
In-param :
new_ping : string value of a ping
Out-param :
None
Return value :
None
*/
void write_ping_log(char* new_ping){
/* Variables */
FILE* fd;
/* Open log file */
fd = fopen("/var/log/ping-report/all-ping.log","a+");
if(fd != NULL){
if(new_ping == NULL){
new_ping = (char *) malloc(5*sizeof(char));
if(new_ping == NULL){
(void) fclose(fd);
return;
}
(void) snprintf(new_ping,5*sizeof(char),"LOSS");
}
(void) fwrite(new_ping, sizeof(char), strlen(new_ping), fd);
(void) fclose(fd);
}else{
perror("write ping : ");
}
free(new_ping);
}
/*
-- set_stats_ping --
Desc :
Function which calculate statistics about ping values, from log file.
In-param :
None
Out-param :
None
Return value :
None
*/
void set_stats_ping(){
/* Variables */
FILE* fd;
/* Open log file */
fd = fopen("/var/log/ping-report/all-ping.log","r");
if(fd != NULL){
/* Stats variables */
double ping = 0.0;
double sum = 0.0;
double max = 0.0;
double min = 100.0;
double mean = 0.0;
int nb_high = 0;
int nb_loss = 0;
int nb_ping = 0;
char* read_line = NULL;
size_t n = 0;
/* Read file */
while(getline(&read_line,&n,fd) != -1){
/* Check getline error */
if(read_line == NULL){
break;
}
/* Check if the ping is flagged as LOSS */
if(strcmp(read_line,"LOSS") == 0){
nb_loss++;
}else{
/* Evaluate the ping as a double */
ping = strtod(read_line,NULL);
/* Test null ping */
if(ping < 0.1){
/* Ignore null ping */
}else{
/* Number of ping readed (for mean calculation) */
nb_ping++;
/* Max ping */
if(ping > max){
max = ping;
}
/* Min ping */
if(ping < min){
min = ping;
}
/* Number of ping above 100 ms */
if(ping > 100.0){
nb_high++;
}
/* Sum (for mean calculation) */
sum += ping;
}
}
free(read_line);
n = 0;
}
/* Mean calculation */
mean = sum / (double) nb_ping;
(void) fclose(fd);
insert_hourly_report(mean,max,min,nb_high,nb_loss,nb_ping);
if(read_line != NULL){
free(read_line);
}
}else{
perror("stats : ");
}
}

60
ping-report/src/utils.c Normal file
View File

@ -0,0 +1,60 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include "../include/utils.h"
/*
-- write_pid_file --
Desc :
write pid in a log file
In-param :
None
Out-param :
None
Return value :
None
*/
void write_pid_file(){
/* Variables */
FILE* fd;
pid_t pid = (pid_t) getpid();
char pid_str[16];
fd = fopen("/var/log/ping-report/pid.log","w+");
if(fd == NULL){
return;
}
(void) snprintf(pid_str,16,"%d",(int) pid);
(void) fwrite(pid_str,strlen(pid_str),1,fd);
(void) fclose(fd);
}
/*
-- remove_file --
Desc :
Remove a file from filesystem
In-param :
filename : the name of the file to remove
Out-param :
None
Return value :
None
*/
void remove_file(char* filename){
/* Variable */
char remove_cmd[128];
/* remove file */
(void) snprintf(remove_cmd, 128, "rm -f %s",filename);
(void) system(remove_cmd);
}