diff --git a/bin/Makefile.am b/bin/Makefile.am index 06e8af6..d16a40c 100644 --- a/bin/Makefile.am +++ b/bin/Makefile.am @@ -5,6 +5,7 @@ icwmpd_SOURCES = \ ../backupSession.c \ ../config.c \ ../cwmp.c \ + ../ipping.c \ ../digestauth.c \ ../event.c \ ../external.c \ @@ -39,6 +40,7 @@ icwmpd_SOURCES = \ ../dm/dmtree/x_inteno_se_ipacccfg.c \ ../dm/dmtree/x_inteno_se_logincfg.c \ ../dm/dmtree/x_inteno_se_power_mgmt.c \ + ../dm/dmtree/ippingdiagnostics.c \ ../dm/dmtree/x_inteno_se_wifi.c icwmpd_CFLAGS = \ diff --git a/cwmp.c b/cwmp.c index 756c3ca..6cdbd26 100644 --- a/cwmp.c +++ b/cwmp.c @@ -20,7 +20,8 @@ #include "external.h" #include "dmentry.h" #include "ubus.h" - +#include "ipping.h" + struct cwmp cwmp_main = {0}; struct rpc *cwmp_add_session_rpc_acs (struct session *session, int type) @@ -473,6 +474,12 @@ int run_session_end_func (struct session *session) exit(EXIT_SUCCESS); } + if (session->end_session & END_SESSION_IPPING_DIAGNOSTIC) + { + CWMP_LOG (INFO,"Executing ippingdiagnostic: end session request"); + cwmp_ip_ping_diagnostic(); + } + if (session->end_session & END_SESSION_REBOOT) { CWMP_LOG (INFO,"Executing Reboot: end session request"); @@ -551,6 +558,7 @@ int main(int argc, char **argv) { return error; } + init_ipping_diagnostic(); CWMP_LOG(INFO,"STARTING ICWMP"); cwmp->start_time = time(NULL); @@ -612,7 +620,7 @@ int main(int argc, char **argv) pthread_join(scheduleInform_thread, NULL); pthread_join(download_thread, NULL); pthread_join(http_cr_server_thread, NULL); - + exit_ipping_diagnostic(); CWMP_LOG(INFO,"EXIT ICWMP"); return CWMP_OK; } diff --git a/dm/dmcwmp.c b/dm/dmcwmp.c index b313670..a6329aa 100644 --- a/dm/dmcwmp.c +++ b/dm/dmcwmp.c @@ -28,6 +28,7 @@ #include "voice_services.h" #include "layer_3_forwarding.h" #include "layer_2_bridging.h" +#include "ippingdiagnostics.h" static char *get_parameter_notification (char *param); static int remove_parameter_notification(char *param); @@ -97,6 +98,7 @@ struct prefix_method prefix_methods[] = { { DMROOT"X_INTENO_SE_IpAccCfg.", 1, NULL, 0, &entry_method_root_X_INTENO_SE_IpAccCfg }, { DMROOT"X_INTENO_SE_LoginCfg.", 1, NULL, 0, &entry_method_root_X_INTENO_SE_LOGIN_CFG }, { DMROOT"X_INTENO_SE_PowerManagement.", 1, dm_powermgmt_enable_set, 0, &entry_method_root_X_INTENO_SE_PowerManagement }, + { DMROOT"IPPingDiagnostics.", 1, NULL, 0, &entry_method_root_IPPingDiagnostics }, }; int dm_entry_set_prefix_methods_enable(void) diff --git a/dm/dmtree/ippingdiagnostics.c b/dm/dmtree/ippingdiagnostics.c new file mode 100644 index 0000000..0adef4e --- /dev/null +++ b/dm/dmtree/ippingdiagnostics.c @@ -0,0 +1,195 @@ +/* + * 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. + * + * Copyright (C) 2012-2014 PIVA SOFTWARE (www.pivasoftware.com) + * Author: Imen Bhiri + * Author: Feten Besbes + */ + +#include +#include +#include +#include "cwmp.h" +#include "ipping.h" +#include "ubus.h" +#include "dmcwmp.h" +#include "dmuci.h" +#include "dmubus.h" +#include "dmcommon.h" +#include "ippingdiagnostics.h" +#include "ipping.h" + +int get_ipping_diagnostics_state(char *refparam, struct dmctx *ctx, char **value) +{ + *value = ipping_diagnostic.state; + return 0; +} + +int set_ipping_diagnostics_state(char *refparam, struct dmctx *ctx, int action, char *value) +{ + switch (action) { + case VALUECHECK: + return 0; + case VALUESET: + if (strcmp(value, "Requested") == 0) { + ipping_diagnostic.state = set_ping_diagnostic(ipping_diagnostic.state, value); + cwmp_set_end_session(END_SESSION_IPPING_DIAGNOSTIC); + } + return 0; + } + return 0; +} + +int get_ipping_interface(char *refparam, struct dmctx *ctx, char **value) +{ + *value = ipping_diagnostic.interface; + return 0; +} + +int set_ipping_interface(char *refparam, struct dmctx *ctx, int action, char *value) +{ + switch (action) { + case VALUECHECK: + return 0; + case VALUESET: + ipping_diagnostic.interface = set_ping_diagnostic(ipping_diagnostic.interface, value); + return 0; + } + return 0; +} + +int get_ipping_host(char *refparam, struct dmctx *ctx, char **value) +{ + + *value = ipping_diagnostic.host; + return 0; +} + +int set_ipping_host(char *refparam, struct dmctx *ctx, int action, char *value) +{ + switch (action) { + case VALUECHECK: + return 0; + case VALUESET: + TRACE(); + ipping_diagnostic.host = set_ping_diagnostic(ipping_diagnostic.host, value); + TRACE(); + return 0; + } + return 0; +} + +int get_ipping_repetition_number(char *refparam, struct dmctx *ctx, char **value) +{ + *value = ipping_diagnostic.repetition; + return 0; +} + +int set_ipping_repetition_number(char *refparam, struct dmctx *ctx, int action, char *value) +{ + + switch (action) { + case VALUECHECK: + return 0; + case VALUESET: + ipping_diagnostic.repetition = set_ping_diagnostic(ipping_diagnostic.repetition, value); + return 0; + } + return 0; +} + +int get_ipping_timeout(char *refparam, struct dmctx *ctx, char **value) +{ + + *value = ipping_diagnostic.timeout; + return 0; +} + +int set_ipping_timeout(char *refparam, struct dmctx *ctx, int action, char *value) +{ + + switch (action) { + case VALUECHECK: + return 0; + case VALUESET: + ipping_diagnostic.timeout = set_ping_diagnostic(ipping_diagnostic.timeout, value); + return 0; + } + return 0; +} + +int get_ipping_block_size(char *refparam, struct dmctx *ctx, char **value) +{ + *value = ipping_diagnostic.size; + + return 0; +} + +int set_ipping_block_size(char *refparam, struct dmctx *ctx, int action, char *value) +{ + switch (action) { + case VALUECHECK: + return 0; + case VALUESET: + ipping_diagnostic.size = set_ping_diagnostic(ipping_diagnostic.size, value); + } + return 0; +} + +int get_ipping_success_count(char *refparam, struct dmctx *ctx, char **value) +{ + *value = ipping_diagnostic.success_count; + + return 0; +} + +int get_ipping_failure_count(char *refparam, struct dmctx *ctx, char **value) +{ + *value = ipping_diagnostic.failure_count; + + return 0; +} + +int get_ipping_average_response_time(char *refparam, struct dmctx *ctx, char **value) +{ + *value = ipping_diagnostic.average_response_time; + return 0; +} + +int get_ipping_min_response_time(char *refparam, struct dmctx *ctx, char **value) +{ + *value = ipping_diagnostic.minimum_response_time; + + return 0; +} + +int get_ipping_max_response_time(char *refparam, struct dmctx *ctx, char **value) +{ + *value = ipping_diagnostic.maximum_response_time; + + return 0; +} + +int entry_method_root_IPPingDiagnostics(struct dmctx *ctx) +{ + IF_MATCH(ctx, DMROOT"IPPingDiagnostics.") { + DMOBJECT(DMROOT"IPPingDiagnostics.", ctx, "0", 0, NULL, NULL, NULL); + DMPARAM("DiagnosticsState", ctx, "1", get_ipping_diagnostics_state, set_ipping_diagnostics_state, NULL, 0, 1, UNDEF, NULL); + DMPARAM("Interface", ctx, "1", get_ipping_interface, set_ipping_interface, NULL, 0, 1, UNDEF, NULL); + DMPARAM("Host", ctx, "1", get_ipping_host, set_ipping_host, NULL, 0, 1, UNDEF, NULL); + DMPARAM("NumberOfRepetitions", ctx, "1", get_ipping_repetition_number, set_ipping_repetition_number, "xsd:unsignedInt", 0, 1, UNDEF, NULL); + DMPARAM("Timeout", ctx, "1", get_ipping_timeout, set_ipping_timeout, "xsd:unsignedInt", 0, 1, UNDEF, NULL); + DMPARAM("DataBlockSize", ctx, "1", get_ipping_block_size, set_ipping_block_size, "xsd:unsignedInt", 0, 1, UNDEF, NULL); + //DMPARAM("DSCP", ctx, "1", get_ipping_dscp, set_ipping_dscp, "xsd:unsignedInt", 0, 1, UNDEF, NULL); + DMPARAM("SuccessCount", ctx, "0", get_ipping_success_count, NULL, "xsd:unsignedInt", 0, 1, UNDEF, NULL); + DMPARAM("FailureCount", ctx, "0", get_ipping_failure_count, NULL, "xsd:unsignedInt", 0, 1, UNDEF, NULL); + DMPARAM("AverageResponseTime", ctx, "0", get_ipping_average_response_time, NULL, "xsd:unsignedInt", 0, 1, UNDEF, NULL); + DMPARAM("MinimumResponseTime", ctx, "0", get_ipping_min_response_time, NULL, "xsd:unsignedInt", 0, 1, UNDEF, NULL); + DMPARAM("MaximumResponseTime", ctx, "0", get_ipping_max_response_time, NULL, "xsd:unsignedInt", 0, 1, UNDEF, NULL); + return 0; + } + return FAULT_9005; +} \ No newline at end of file diff --git a/dm/dmtree/ippingdiagnostics.h b/dm/dmtree/ippingdiagnostics.h new file mode 100644 index 0000000..c9c349c --- /dev/null +++ b/dm/dmtree/ippingdiagnostics.h @@ -0,0 +1,16 @@ +/* + * 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. + * + * Copyright (C) 2012-2014 PIVA SOFTWARE (www.pivasoftware.com) + * Author: Imen Bhiri + */ +#ifndef __IPPING_DIAGNOSTIC_H +#define __IPPING_DIAGNOSTIC_H + +extern struct ip_ping_diagnostic ipping_diagnostic; +int entry_method_root_IPPingDiagnostics(struct dmctx *ctx); + +#endif \ No newline at end of file diff --git a/event.c b/event.c index e64427e..47c13d2 100644 --- a/event.c +++ b/event.c @@ -204,6 +204,24 @@ void cwmp_add_notification(void) } } +void cwmp_root_cause_event_ipdiagnostic(void) +{ + struct cwmp *cwmp = &cwmp_main; + struct event_container *event_container; + + pthread_mutex_lock (&(cwmp->mutex_session_queue)); + event_container = cwmp_add_event_container (cwmp, EVENT_IDX_8DIAGNOSTICS_COMPLETE, ""); + if (event_container == NULL) + { + pthread_mutex_unlock (&(cwmp->mutex_session_queue)); + return; + } + cwmp_save_event_container(cwmp,event_container); + pthread_mutex_unlock (&(cwmp->mutex_session_queue)); + pthread_cond_signal(&(cwmp->threshold_session_send)); + return; +} + int cwmp_root_cause_event_boot (struct cwmp *cwmp) { struct event_container *event_container; @@ -559,7 +577,7 @@ void connection_request_port_value_change(struct cwmp *cwmp, int port) int cwmp_root_cause_events (struct cwmp *cwmp) { - int error; + int error; if (error = cwmp_root_cause_event_bootstrap(cwmp)) { diff --git a/inc/cwmp.h b/inc/cwmp.h index 5a050be..2c0949c 100644 --- a/inc/cwmp.h +++ b/inc/cwmp.h @@ -60,6 +60,7 @@ enum end_session { END_SESSION_EXTERNAL_ACTION = 1<<1, END_SESSION_RELOAD = 1<<2, END_SESSION_FACTORY_RESET = 1<<3, + END_SESSION_IPPING_DIAGNOSTIC = 1<<4, }; enum cwmp_start { diff --git a/inc/ipping.h b/inc/ipping.h new file mode 100644 index 0000000..5f712cc --- /dev/null +++ b/inc/ipping.h @@ -0,0 +1,33 @@ +/* + * 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. + * + * Copyright (C) 2012-2014 PIVA SOFTWARE (www.pivasoftware.com) + * Author: Imen Bhiri + */ +#ifndef __IPPING__H +#define __IPPING__H + +struct ip_ping_diagnostic { + char *state; + char *interface; + char *host; + char *repetition; + char *timeout; + char *size; + //char *dscp + char *success_count; + char *failure_count; + char *average_response_time; + char *minimum_response_time; + char *maximum_response_time; +}; + +int init_ipping_diagnostic(); +int exit_ipping_diagnostic(); +int cwmp_ip_ping_diagnostic(); +char *set_ping_diagnostic(char *param, char *value); + +#endif \ No newline at end of file diff --git a/ipping.c b/ipping.c new file mode 100644 index 0000000..fbcc616 --- /dev/null +++ b/ipping.c @@ -0,0 +1,155 @@ +/* + * 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. + * + * Copyright (C) 2013 Inteno Broadband Technology AB + * Author Imen Bhiri * + * + */ + +#include +#include +#include +#include "cwmp.h" +#include "backupSession.h" +#include "xml.h" +#include "log.h" +#include "external.h" +#include "dmentry.h" +#include "ubus.h" +#include "ipping.h" + +struct ip_ping_diagnostic ipping_diagnostic = {0}; + +int init_ipping_diagnostic() +{ + ipping_diagnostic.state = strdup("None"); + ipping_diagnostic.interface = NULL; + ipping_diagnostic.host = NULL; + ipping_diagnostic.repetition = strdup("5"); + ipping_diagnostic.timeout = strdup("5"); + ipping_diagnostic.size = strdup("56"); + //char *dscp + ipping_diagnostic.success_count = strdup("0"); + ipping_diagnostic.failure_count = strdup("0"); + ipping_diagnostic.average_response_time = strdup("0"); + ipping_diagnostic.minimum_response_time = strdup("0"); + ipping_diagnostic.maximum_response_time = strdup("0"); + return 0; +} + +int exit_ipping_diagnostic() +{ + free(ipping_diagnostic.state); + free(ipping_diagnostic.interface); + free(ipping_diagnostic.host); + free(ipping_diagnostic.repetition); + free(ipping_diagnostic.timeout); + free(ipping_diagnostic.size); + //char *dscp + free(ipping_diagnostic.success_count); + free(ipping_diagnostic.failure_count); + free(ipping_diagnostic.average_response_time); + free(ipping_diagnostic.minimum_response_time); + free(ipping_diagnostic.maximum_response_time); + return 0; +} + +char *set_ping_diagnostic(char *param, char *value) +{ + free(param); + return strdup(value); //MUST USE STRDUP +} + +int extract_ping_statistics(char *str) +{ + char *val = NULL, *failure, *tmp, *pch = NULL, *pch2, *spch, *spch3, *spch2, *stat, *total; + char delimiter[] = " "; + int i =0; + int success; + val = "packets transmitted"; + pch = strstr(str, val); + if (pch) { + val = "round-trip"; + if (i == 0) { + tmp = strdup(str); + pch2 = strtok_r(tmp, ",", &spch2); + stat = strtok_r(spch2, delimiter, &spch3); + ipping_diagnostic.success_count = set_ping_diagnostic(ipping_diagnostic.success_count, stat); + success = atoi(stat); + total = strtok_r(pch2, delimiter, &spch3); + asprintf(&failure, "%d", atoi(total) - success); + ipping_diagnostic.failure_count = set_ping_diagnostic(ipping_diagnostic.failure_count, failure); + free(failure); + free(tmp); + if (success == 0) { + ipping_diagnostic.state = set_ping_diagnostic(ipping_diagnostic.state, "Error_CannotResolveHostName"); + ipping_diagnostic.minimum_response_time = set_ping_diagnostic(ipping_diagnostic.minimum_response_time, "0"); + ipping_diagnostic.average_response_time = set_ping_diagnostic(ipping_diagnostic.average_response_time, "0"); + ipping_diagnostic.maximum_response_time = set_ping_diagnostic(ipping_diagnostic.maximum_response_time, "0"); + return 0; + } + i++; + pch = strstr(str, val); + } + if (pch && i != 0) { + tmp = strdup(pch); + pch2 = strtok_r(tmp, "=", &spch2); + ipping_diagnostic.state = set_ping_diagnostic(ipping_diagnostic.state, "Complete"); + spch2++; + ipping_diagnostic.minimum_response_time = set_ping_diagnostic(ipping_diagnostic.minimum_response_time, strtok_r(spch2, "/", &spch3)); + spch2 = strtok_r(NULL, "/ ", &spch3); + ipping_diagnostic.average_response_time = set_ping_diagnostic(ipping_diagnostic.average_response_time, spch2); + spch2 = strtok_r(NULL, "/ ", &spch3); + ipping_diagnostic.maximum_response_time = set_ping_diagnostic(ipping_diagnostic.maximum_response_time, spch2); + free(tmp); + } + } + return 0; +} + +int ping_cmd() +{ + int i = 8; + char buf[512], *val = NULL, *pch, *spch = NULL, *pch2, *spch2, *dup = NULL; + int dsl, pp, r; + buf[0] = '\0'; + + if ((ipping_diagnostic.host)[0] == '\0') { + return 0; + } + if (ipping_diagnostic.interface == NULL || (ipping_diagnostic.interface)[0] == '\0') + pp = dmcmd("ping", i, "-q", "-c", ipping_diagnostic.repetition, "-s", ipping_diagnostic.size, "-w", ipping_diagnostic.timeout, ipping_diagnostic.host); + else { + i++; + pp = dmcmd("ping", i, "-q", "-c", ipping_diagnostic.repetition, "-s", ipping_diagnostic.size, "-w", ipping_diagnostic.timeout, "-I", ipping_diagnostic.interface, ipping_diagnostic.host); + } + if (pp) { + r = dmcmd_read(pp, buf, 512); + close(pp); + } + if(buf[0] == '\0' || strstr(buf, "bad address")) { + ipping_diagnostic.state = set_ping_diagnostic(ipping_diagnostic.state, "Complete"); //TO CHECK + ipping_diagnostic.success_count = set_ping_diagnostic(ipping_diagnostic.success_count, "0"); + ipping_diagnostic.failure_count = set_ping_diagnostic(ipping_diagnostic.failure_count, "0"); + ipping_diagnostic.minimum_response_time = set_ping_diagnostic(ipping_diagnostic.minimum_response_time, "0"); + ipping_diagnostic.average_response_time = set_ping_diagnostic(ipping_diagnostic.average_response_time, "0"); + ipping_diagnostic.maximum_response_time = set_ping_diagnostic(ipping_diagnostic.maximum_response_time, "0"); + return 0; + } + for (pch = strtok_r(buf, "\n\r", &spch); pch; pch = strtok_r(NULL, "\n\r", &spch)) { + if(strstr(pch, "ping statistics")) + break; + } + extract_ping_statistics(spch); + return 0; +} + +int cwmp_ip_ping_diagnostic() +{ + ping_cmd(); + cwmp_root_cause_event_ipdiagnostic(&cwmp_main); + return 0; +} \ No newline at end of file