mirror of
https://dev.iopsys.eu/bbf/icwmp.git
synced 2025-12-10 07:44:41 +01:00
910 lines
30 KiB
C
910 lines
30 KiB
C
/*
|
|
* 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-2019 iopsys Software Solutions AB
|
|
* Author Mohamed Kallel <mohamed.kallel@pivasoftware.com>
|
|
* Author Ahmed Zribi <ahmed.zribi@pivasoftware.com>
|
|
*
|
|
*/
|
|
|
|
#include <pthread.h>
|
|
#include <sys/socket.h>
|
|
#include <arpa/inet.h>
|
|
#include <netdb.h>
|
|
#include <openssl/hmac.h>
|
|
#include <openssl/evp.h>
|
|
#include <openssl/engine.h>
|
|
#include "cwmp.h"
|
|
#include "xml.h"
|
|
#include "backupSession.h"
|
|
#include "log.h"
|
|
#include "jshn.h"
|
|
#include "external.h"
|
|
#include "config.h"
|
|
#ifdef TR098
|
|
#include <libtr098/dmtr098.h>
|
|
#include <libtr098/dmcommon.h>
|
|
#include <libtr098/dmentry.h>
|
|
#include <libtr098/deviceinfo.h>
|
|
#include <libtr098/dmjson.h>
|
|
#else
|
|
#include <libbbfdm/dmentry.h>
|
|
#include <libbbfdm/deviceinfo.h>
|
|
#endif
|
|
|
|
LIST_HEAD(list_value_change);
|
|
LIST_HEAD(list_lw_value_change);
|
|
pthread_mutex_t mutex_value_change = PTHREAD_MUTEX_INITIALIZER;
|
|
|
|
const struct EVENT_CONST_STRUCT EVENT_CONST [] = {
|
|
[EVENT_IDX_0BOOTSTRAP] = {"0 BOOTSTRAP", EVENT_TYPE_SINGLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL|EVENT_RETRY_AFTER_REBOOT},
|
|
[EVENT_IDX_1BOOT] = {"1 BOOT", EVENT_TYPE_SINGLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL},
|
|
[EVENT_IDX_2PERIODIC] = {"2 PERIODIC", EVENT_TYPE_SINGLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL|EVENT_RETRY_AFTER_REBOOT},
|
|
[EVENT_IDX_3SCHEDULED] = {"3 SCHEDULED", EVENT_TYPE_SINGLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL|EVENT_RETRY_AFTER_REBOOT},
|
|
[EVENT_IDX_4VALUE_CHANGE] = {"4 VALUE CHANGE", EVENT_TYPE_SINGLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL},
|
|
[EVENT_IDX_5KICKED] = {"5 KICKED", EVENT_TYPE_SINGLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL|EVENT_RETRY_AFTER_REBOOT},
|
|
[EVENT_IDX_6CONNECTION_REQUEST] = {"6 CONNECTION REQUEST", EVENT_TYPE_SINGLE, 0},
|
|
[EVENT_IDX_7TRANSFER_COMPLETE] = {"7 TRANSFER COMPLETE", EVENT_TYPE_SINGLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL|EVENT_RETRY_AFTER_REBOOT},
|
|
[EVENT_IDX_8DIAGNOSTICS_COMPLETE] = {"8 DIAGNOSTICS COMPLETE", EVENT_TYPE_SINGLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL},
|
|
[EVENT_IDX_9REQUEST_DOWNLOAD] = {"9 REQUEST DOWNLOAD", EVENT_TYPE_SINGLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL|EVENT_RETRY_AFTER_REBOOT},
|
|
[EVENT_IDX_10AUTONOMOUS_TRANSFER_COMPLETE] = {"10 AUTONOMOUS TRANSFER COMPLETE", EVENT_TYPE_SINGLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL|EVENT_RETRY_AFTER_REBOOT},
|
|
[EVENT_IDX_11DU_STATE_CHANGE_COMPLETE] = {"11 DU STATE CHANGE COMPLETE", EVENT_TYPE_SINGLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL|EVENT_RETRY_AFTER_REBOOT},
|
|
[EVENT_IDX_M_Reboot] = {"M Reboot", EVENT_TYPE_MULTIPLE,EVENT_RETRY_AFTER_TRANSMIT_FAIL|EVENT_RETRY_AFTER_REBOOT},
|
|
[EVENT_IDX_M_ScheduleInform] = {"M ScheduleInform", EVENT_TYPE_MULTIPLE,EVENT_RETRY_AFTER_TRANSMIT_FAIL|EVENT_RETRY_AFTER_REBOOT},
|
|
[EVENT_IDX_M_Download] = {"M Download", EVENT_TYPE_MULTIPLE,EVENT_RETRY_AFTER_TRANSMIT_FAIL|EVENT_RETRY_AFTER_REBOOT},
|
|
[EVENT_IDX_M_Schedule_Download] = {"M ScheduleDownload", EVENT_TYPE_MULTIPLE,EVENT_RETRY_AFTER_TRANSMIT_FAIL|EVENT_RETRY_AFTER_REBOOT},
|
|
[EVENT_IDX_M_Upload] = {"M Upload", EVENT_TYPE_MULTIPLE,EVENT_RETRY_AFTER_TRANSMIT_FAIL|EVENT_RETRY_AFTER_REBOOT},
|
|
[EVENT_IDX_M_ChangeDUState] = {"M ChangeDUState", EVENT_TYPE_MULTIPLE,EVENT_RETRY_AFTER_TRANSMIT_FAIL|EVENT_RETRY_AFTER_REBOOT}
|
|
};
|
|
|
|
void cwmp_save_event_container (struct cwmp *cwmp,struct event_container *event_container)
|
|
{
|
|
struct list_head *ilist;
|
|
struct dm_parameter *dm_parameter;
|
|
char section[256];
|
|
mxml_node_t *b;
|
|
|
|
if (EVENT_CONST[event_container->code].RETRY & EVENT_RETRY_AFTER_REBOOT)
|
|
{
|
|
b = bkp_session_insert_event(event_container->code, event_container->command_key, event_container->id, "queue");
|
|
|
|
list_for_each(ilist,&(event_container->head_dm_parameter))
|
|
{
|
|
dm_parameter = list_entry(ilist, struct dm_parameter, list);
|
|
bkp_session_insert_parameter(b, dm_parameter->name);
|
|
}
|
|
bkp_session_save();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
struct event_container *cwmp_add_event_container (struct cwmp *cwmp, int event_code, char *command_key)
|
|
{
|
|
static int id;
|
|
struct event_container *event_container;
|
|
struct session *session;
|
|
struct list_head *ilist;
|
|
|
|
if (cwmp->head_event_container == NULL)
|
|
{
|
|
session = cwmp_add_queue_session(cwmp);
|
|
if (session == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
cwmp->head_event_container = &(session->head_event_container);
|
|
}
|
|
session = list_entry (cwmp->head_event_container, struct session,head_event_container);
|
|
list_for_each(ilist, cwmp->head_event_container)
|
|
{
|
|
event_container = list_entry (ilist, struct event_container, list);
|
|
if (event_container->code==event_code &&
|
|
EVENT_CONST[event_code].TYPE==EVENT_TYPE_SINGLE)
|
|
{
|
|
return event_container;
|
|
}
|
|
if(event_container->code > event_code)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
event_container = calloc (1,sizeof(struct event_container));
|
|
if (event_container==NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
INIT_LIST_HEAD (&(event_container->head_dm_parameter));
|
|
list_add (&(event_container->list), ilist->prev);
|
|
event_container->code = event_code;
|
|
event_container->command_key = command_key?strdup(command_key):strdup("");
|
|
if((id<0) || (id>=MAX_INT_ID) )
|
|
{
|
|
id=0;
|
|
}
|
|
id++;
|
|
event_container->id = id;
|
|
return event_container;
|
|
}
|
|
|
|
void add_dm_parameter_tolist(struct list_head *head, char *param_name, char *param_data, char *param_type)
|
|
{
|
|
struct dm_parameter *dm_parameter;
|
|
struct list_head *ilist;
|
|
int cmp;
|
|
list_for_each (ilist, head) {
|
|
dm_parameter = list_entry(ilist, struct dm_parameter, list);
|
|
cmp = strcmp(dm_parameter->name, param_name);
|
|
if (cmp == 0) {
|
|
if (param_data && strcmp(dm_parameter->data, param_data) != 0)
|
|
{
|
|
free(dm_parameter->data);
|
|
dm_parameter->data = strdup(param_data);
|
|
}
|
|
return;
|
|
} else if (cmp > 0) {
|
|
break;
|
|
}
|
|
}
|
|
dm_parameter = calloc(1, sizeof(struct dm_parameter));
|
|
_list_add(&dm_parameter->list, ilist->prev, ilist);
|
|
if (param_name) dm_parameter->name = strdup(param_name);
|
|
if (param_data) dm_parameter->data = strdup(param_data);
|
|
if (param_type) dm_parameter->type = param_type ? param_type : "xsd:string";
|
|
}
|
|
|
|
void delete_dm_parameter_fromlist(struct dm_parameter *dm_parameter)
|
|
{
|
|
list_del(&dm_parameter->list);
|
|
free(dm_parameter->name);
|
|
free(dm_parameter->data);
|
|
free(dm_parameter);
|
|
}
|
|
|
|
void free_dm_parameter_all_fromlist(struct list_head *list)
|
|
{
|
|
struct dm_parameter *dm_parameter;
|
|
while (list->next!=list) {
|
|
dm_parameter = list_entry(list->next, struct dm_parameter, list);
|
|
delete_dm_parameter_fromlist(dm_parameter);
|
|
}
|
|
}
|
|
|
|
void add_list_value_change(char *param_name, char *param_data, char *param_type)
|
|
{
|
|
pthread_mutex_lock(&(mutex_value_change));
|
|
add_dm_parameter_tolist(&list_value_change, param_name, param_data, param_type);
|
|
pthread_mutex_unlock(&(mutex_value_change));
|
|
}
|
|
|
|
void add_lw_list_value_change(char *param_name, char *param_data, char *param_type)
|
|
{
|
|
add_dm_parameter_tolist(&list_lw_value_change, param_name, param_data, param_type);
|
|
|
|
}
|
|
|
|
void udplw_server_param(struct addrinfo **res)
|
|
{
|
|
struct addrinfo hints = {0};
|
|
struct cwmp *cwmp = &cwmp_main;
|
|
struct config *conf;
|
|
char *port;
|
|
conf = &(cwmp->conf);
|
|
hints.ai_family = AF_UNSPEC;
|
|
hints.ai_socktype = SOCK_DGRAM;
|
|
asprintf(&port, "%d", conf->lw_notification_port);
|
|
getaddrinfo(conf->lw_notification_hostname,port,&hints,res);
|
|
//FREE(port);
|
|
}
|
|
|
|
static void message_compute_signature(char *msg_out, char *signature)
|
|
{
|
|
int i;
|
|
int result_len = 20;
|
|
unsigned char *result;
|
|
struct cwmp *cwmp = &cwmp_main;
|
|
struct config *conf;
|
|
conf = &(cwmp->conf);
|
|
result = HMAC(EVP_sha1(), conf->acs_passwd, strlen(conf->acs_passwd),
|
|
msg_out, strlen(msg_out), NULL, NULL);
|
|
for (i = 0; i < result_len; i++) {
|
|
sprintf(&(signature[i * 2]), "%02X", result[i]);
|
|
}
|
|
signature[i * 2 ] = '\0';
|
|
FREE(result);
|
|
}
|
|
|
|
char *calculate_lwnotification_cnonce()
|
|
{
|
|
int i;
|
|
char *cnonce = malloc( 33 * sizeof(char));
|
|
srand((unsigned int) time(NULL));
|
|
for (i = 0; i < 4; i++) {
|
|
sprintf(&(cnonce[i * 8]), "%08x", rand());
|
|
}
|
|
cnonce[i * 8 ] = '\0';
|
|
return cnonce;
|
|
}
|
|
|
|
static void send_udp_message(struct addrinfo *servaddr, char *msg)
|
|
{
|
|
int fd;
|
|
|
|
fd = socket(servaddr->ai_family, SOCK_DGRAM, 0);
|
|
|
|
if ( fd >= 0) {
|
|
sendto(fd, msg, strlen(msg), 0, servaddr->ai_addr, servaddr->ai_addrlen);
|
|
close(fd);
|
|
}
|
|
}
|
|
|
|
void del_list_lw_notify(struct dm_parameter *dm_parameter)
|
|
{
|
|
|
|
list_del(&dm_parameter->list);
|
|
free(dm_parameter->name);
|
|
free(dm_parameter);
|
|
}
|
|
|
|
void free_all_list_lw_notify()
|
|
{
|
|
struct dm_parameter *dm_parameter;
|
|
while (list_lw_value_change.next != &list_lw_value_change) {
|
|
dm_parameter = list_entry(list_lw_value_change.next, struct dm_parameter, list);
|
|
del_list_lw_notify(dm_parameter);
|
|
}
|
|
}
|
|
|
|
void cwmp_lwnotification()
|
|
{
|
|
char *msg, *msg_out;
|
|
char signature[41];
|
|
struct addrinfo *servaddr;
|
|
struct cwmp *cwmp = &cwmp_main;
|
|
struct config *conf;
|
|
conf = &(cwmp->conf);
|
|
|
|
udplw_server_param(&servaddr);
|
|
xml_prepare_lwnotification_message(&msg_out);
|
|
message_compute_signature(msg_out, signature);
|
|
asprintf(&msg, "%s \n %s: %s \n %s: %s \n %s: %d\n %s: %s\n\n%s",
|
|
"POST /HTTPS/1.1",
|
|
"HOST", conf->lw_notification_hostname,
|
|
"Content-Type", "test/xml; charset=utf-8",
|
|
"Content-Lenght", strlen(msg_out),
|
|
"Signature",signature,
|
|
msg_out);
|
|
|
|
send_udp_message(servaddr, msg);
|
|
free_all_list_lw_notify();
|
|
//freeaddrinfo(servaddr); //To check
|
|
FREE(msg);
|
|
FREE(msg_out);
|
|
}
|
|
|
|
void send_active_value_change(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_4VALUE_CHANGE, "");
|
|
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;
|
|
}
|
|
|
|
void cwmp_add_notification(void)
|
|
{
|
|
int fault, iscopy;
|
|
int i = 0;
|
|
FILE *fp;
|
|
char buf[512];
|
|
char *parameter, *notification = NULL, *value = NULL, *jval;
|
|
struct event_container *event_container;
|
|
struct cwmp *cwmp = &cwmp_main;
|
|
struct dm_enabled_notify *p;
|
|
struct dm_parameter *dm_parameter;
|
|
struct dmctx dmctx = {0};
|
|
struct config *conf;
|
|
conf = &(cwmp->conf);
|
|
bool isactive = false;
|
|
bool initiate = false;
|
|
bool lw_isactive = false;
|
|
|
|
pthread_mutex_lock(&(cwmp->mutex_session_send));
|
|
pthread_mutex_lock(&(cwmp->mutex_handle_notify));
|
|
cwmp->count_handle_notify = 0;
|
|
pthread_mutex_unlock(&(cwmp->mutex_handle_notify));
|
|
cwmp_dm_ctx_init(&cwmp_main, &dmctx);
|
|
|
|
fp = fopen(DM_ENABLED_NOTIFY, "r");
|
|
if (fp == NULL)
|
|
return;
|
|
|
|
while (fgets(buf, 512, fp) != NULL) {
|
|
dm_ctx_init_sub(&dmctx, DM_CWMP, cwmp_main.conf.amd_version, cwmp_main.conf.instance_mode);
|
|
initiate = true;
|
|
int len = strlen(buf);
|
|
if (len)
|
|
buf[len-1] = '\0';
|
|
#ifdef TR098
|
|
dmjson_parse_init(buf);
|
|
dmjson_get_var("parameter", &jval);
|
|
parameter = strdup(jval);
|
|
dmjson_get_var("value", &jval);
|
|
value = strdup(jval);
|
|
dmjson_get_var("notification", &jval);
|
|
notification = strdup(jval);
|
|
dmjson_parse_fini();
|
|
#else
|
|
bbfdmjson_parse_init(buf);
|
|
bbfdmjson_get_var("parameter", &jval);
|
|
parameter = strdup(jval);
|
|
bbfdmjson_get_var("value", &jval);
|
|
value = strdup(jval);
|
|
bbfdmjson_get_var("notification", &jval);
|
|
notification = strdup(jval);
|
|
bbfdmjson_parse_fini();
|
|
#endif
|
|
fault = dm_entry_param_method(&dmctx, CMD_GET_VALUE, parameter, NULL, NULL);
|
|
if (!fault && dmctx.list_parameter.next != &dmctx.list_parameter) {
|
|
dm_parameter = list_entry(dmctx.list_parameter.next, struct dm_parameter, list);
|
|
if (strcmp(dm_parameter->data, value) != 0) {
|
|
#ifdef TR098
|
|
dm_update_file_enabled_notify(parameter, dm_parameter->data);
|
|
iscopy = copy_temporary_file_to_original_file(DM_ENABLED_NOTIFY, DM_ENABLED_NOTIFY_TEMPORARY);
|
|
|
|
#else
|
|
bbfdm_update_file_enabled_notify(parameter, dm_parameter->data);
|
|
iscopy = dm_copy_temporary_file_to_original_file(DM_ENABLED_NOTIFY, DM_ENABLED_NOTIFY_TEMPORARY);
|
|
#endif
|
|
if(iscopy)
|
|
remove(DM_ENABLED_NOTIFY_TEMPORARY);
|
|
if (notification[0] == '1' || notification[0] == '2' || notification[0] == '4' || notification[0] == '6' )
|
|
add_list_value_change(parameter, dm_parameter->data, dm_parameter->type);
|
|
if (notification[0] == '2')
|
|
isactive = true;
|
|
}
|
|
}
|
|
FREE(value);
|
|
FREE(notification);
|
|
FREE(parameter);
|
|
}
|
|
fclose(fp);
|
|
|
|
#ifdef TR098
|
|
list_for_each_entry(p, &list_enabled_lw_notify, list) {
|
|
#else
|
|
struct list_head bbf_list_enabled_lw_notify = get_bbf_list_enabled_lw_notify();
|
|
list_for_each_entry(p, &bbf_list_enabled_lw_notify, list) {
|
|
#endif
|
|
if (!initiate || i != 0)
|
|
dm_ctx_init_sub(&dmctx, DM_CWMP, cwmp_main.conf.amd_version, cwmp_main.conf.instance_mode);
|
|
i++;
|
|
if (!conf->lw_notification_enable)
|
|
break;
|
|
fault = dm_entry_param_method(&dmctx, CMD_GET_VALUE, p->name, NULL, NULL);
|
|
if (!fault && dmctx.list_parameter.next != &dmctx.list_parameter) {
|
|
dm_parameter = list_entry(dmctx.list_parameter.next, struct dm_parameter, list);
|
|
if (strcmp(dm_parameter->data, p->value) != 0) {
|
|
#ifdef TR098
|
|
dm_update_enabled_notify(p, dm_parameter->data);
|
|
#else
|
|
bbfdm_update_enabled_notify(p, dm_parameter->data);
|
|
#endif
|
|
if (p->notification[0] >= '3' ) add_lw_list_value_change(p->name, dm_parameter->data, dm_parameter->type);
|
|
if (p->notification[0] == '5' || p->notification[0] == '6') lw_isactive = true;
|
|
}
|
|
}
|
|
dm_ctx_clean_sub(&dmctx);
|
|
}
|
|
cwmp_dm_ctx_clean(cwmp, &dmctx);
|
|
if (lw_isactive) {
|
|
cwmp_lwnotification();
|
|
}
|
|
pthread_mutex_unlock(&(cwmp->mutex_session_send));
|
|
if (isactive)
|
|
send_active_value_change();
|
|
}
|
|
|
|
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;
|
|
if (cwmp->env.boot == CWMP_START_BOOT)
|
|
{
|
|
pthread_mutex_lock (&(cwmp->mutex_session_queue));
|
|
cwmp->env.boot = 0;
|
|
event_container = cwmp_add_event_container (cwmp, EVENT_IDX_1BOOT, "");
|
|
if (event_container == NULL)
|
|
{
|
|
pthread_mutex_unlock (&(cwmp->mutex_session_queue));
|
|
return CWMP_MEM_ERR;
|
|
}
|
|
cwmp_save_event_container (cwmp,event_container);
|
|
pthread_mutex_unlock (&(cwmp->mutex_session_queue));
|
|
}
|
|
return CWMP_OK;
|
|
}
|
|
int event_remove_all_event_container(struct session *session, int rem_from)
|
|
{
|
|
struct event_container *event_container;
|
|
struct dm_parameter *dm_parameter;
|
|
|
|
while (session->head_event_container.next!=&(session->head_event_container))
|
|
{
|
|
event_container = list_entry(session->head_event_container.next, struct event_container, list);
|
|
bkp_session_delete_event(event_container->id, rem_from?"send":"queue");
|
|
if (event_container->code == EVENT_IDX_1BOOT && rem_from == RPC_SEND) {
|
|
remove("/etc/icwmpd/.icwmpd_boot");
|
|
}
|
|
free (event_container->command_key);
|
|
free_dm_parameter_all_fromlist(&(event_container->head_dm_parameter));
|
|
list_del(&(event_container->list));
|
|
free (event_container);
|
|
}
|
|
bkp_session_save();
|
|
return CWMP_OK;
|
|
}
|
|
|
|
int event_remove_noretry_event_container(struct session *session, struct cwmp *cwmp)
|
|
{
|
|
struct event_container *event_container;
|
|
struct dm_parameter *dm_parameter;
|
|
|
|
struct list_head *ilist, *q;
|
|
list_for_each_safe(ilist,q,&(session->head_event_container))
|
|
{
|
|
event_container = list_entry(ilist, struct event_container, list);
|
|
if (EVENT_CONST[event_container->code].RETRY == 0) {
|
|
free (event_container->command_key);
|
|
free_dm_parameter_all_fromlist(&(event_container->head_dm_parameter));
|
|
list_del(&(event_container->list));
|
|
free (event_container);
|
|
}
|
|
if (EVENT_CONST[event_container->code].CODE[0] == '6')
|
|
{
|
|
cwmp->cwmp_cr_event = 1;
|
|
}
|
|
}
|
|
return CWMP_OK;
|
|
}
|
|
|
|
int cwmp_root_cause_event_bootstrap (struct cwmp *cwmp)
|
|
{
|
|
char *acsurl = NULL;
|
|
int error,cmp=0;
|
|
struct event_container *event_container;
|
|
struct session *session;
|
|
|
|
error = cwmp_load_saved_session(cwmp, &acsurl, ACS);
|
|
|
|
if(acsurl == NULL)
|
|
{
|
|
save_acs_bkp_config (cwmp);
|
|
}
|
|
|
|
if (acsurl == NULL || ((acsurl != NULL)&&(cmp = strcmp(cwmp->conf.acsurl,acsurl))))
|
|
{
|
|
pthread_mutex_lock (&(cwmp->mutex_session_queue));
|
|
if (cwmp->head_event_container!=NULL && cwmp->head_session_queue.next!=&(cwmp->head_session_queue))
|
|
{
|
|
session = list_entry(cwmp->head_event_container,struct session, head_event_container);
|
|
event_remove_all_event_container (session,RPC_QUEUE);
|
|
}
|
|
event_container = cwmp_add_event_container (cwmp, EVENT_IDX_0BOOTSTRAP, "");
|
|
FREE(acsurl);
|
|
if (event_container == NULL)
|
|
{
|
|
pthread_mutex_unlock (&(cwmp->mutex_session_queue));
|
|
return CWMP_MEM_ERR;
|
|
}
|
|
cwmp_save_event_container (cwmp,event_container);
|
|
cwmp_scheduleInform_remove_all();
|
|
cwmp_scheduledDownload_remove_all();
|
|
cwmp_scheduled_Download_remove_all();
|
|
cwmp_apply_scheduled_Download_remove_all();
|
|
cwmp_scheduledUpload_remove_all();
|
|
pthread_mutex_unlock (&(cwmp->mutex_session_queue));
|
|
} else {
|
|
FREE(acsurl);
|
|
}
|
|
|
|
if (cmp)
|
|
{
|
|
pthread_mutex_lock (&(cwmp->mutex_session_queue));
|
|
event_container = cwmp_add_event_container (cwmp, EVENT_IDX_4VALUE_CHANGE, "");
|
|
if (event_container == NULL)
|
|
{
|
|
pthread_mutex_unlock (&(cwmp->mutex_session_queue));
|
|
return CWMP_MEM_ERR;
|
|
}
|
|
#ifdef TR098
|
|
char buf[64] = "InternetGatewayDevice.ManagementServer.URL";
|
|
#else
|
|
char buf[64] = "Device.ManagementServer.URL";
|
|
#endif
|
|
add_dm_parameter_tolist(&(event_container->head_dm_parameter), buf, NULL, NULL);
|
|
cwmp_save_event_container (cwmp,event_container);
|
|
save_acs_bkp_config(cwmp);
|
|
cwmp_scheduleInform_remove_all();
|
|
cwmp_scheduledDownload_remove_all();
|
|
cwmp_apply_scheduled_Download_remove_all();
|
|
cwmp_scheduled_Download_remove_all();
|
|
cwmp_scheduledUpload_remove_all();
|
|
pthread_mutex_unlock (&(cwmp->mutex_session_queue));
|
|
}
|
|
|
|
return CWMP_OK;
|
|
}
|
|
|
|
int cwmp_root_cause_TransferComplete (struct cwmp *cwmp, struct transfer_complete *p)
|
|
{
|
|
struct event_container *event_container;
|
|
struct session *session;
|
|
struct rpc *rpc_acs;
|
|
|
|
pthread_mutex_lock (&(cwmp->mutex_session_queue));
|
|
event_container = cwmp_add_event_container (cwmp, EVENT_IDX_7TRANSFER_COMPLETE, "");
|
|
if (event_container == NULL)
|
|
{
|
|
pthread_mutex_unlock (&(cwmp->mutex_session_queue));
|
|
return CWMP_MEM_ERR;
|
|
}
|
|
switch (p->type) {
|
|
case TYPE_DOWNLOAD:
|
|
event_container = cwmp_add_event_container (cwmp, EVENT_IDX_M_Download, p->command_key?p->command_key:"");
|
|
if (event_container == NULL)
|
|
{
|
|
pthread_mutex_unlock (&(cwmp->mutex_session_queue));
|
|
return CWMP_MEM_ERR;
|
|
}
|
|
break;
|
|
case TYPE_UPLOAD:
|
|
event_container = cwmp_add_event_container (cwmp, EVENT_IDX_M_Upload, p->command_key?p->command_key:"");
|
|
if (event_container == NULL)
|
|
{
|
|
pthread_mutex_unlock (&(cwmp->mutex_session_queue));
|
|
return CWMP_MEM_ERR;
|
|
}
|
|
break;
|
|
case TYPE_SCHEDULE_DOWNLOAD:
|
|
event_container = cwmp_add_event_container (cwmp, EVENT_IDX_M_Schedule_Download, p->command_key?p->command_key:"");
|
|
if (event_container == NULL)
|
|
{
|
|
pthread_mutex_unlock (&(cwmp->mutex_session_queue));
|
|
return CWMP_MEM_ERR;
|
|
}
|
|
break;
|
|
}
|
|
session = list_entry (cwmp->head_event_container, struct session,head_event_container);
|
|
if((rpc_acs = cwmp_add_session_rpc_acs(session, RPC_ACS_TRANSFER_COMPLETE)) == NULL)
|
|
{
|
|
pthread_mutex_unlock (&(cwmp->mutex_session_queue));
|
|
return CWMP_MEM_ERR;
|
|
}
|
|
rpc_acs->extra_data = (void *)p;
|
|
pthread_mutex_unlock (&(cwmp->mutex_session_queue));
|
|
return CWMP_OK;
|
|
}
|
|
|
|
int cwmp_root_cause_dustatechangeComplete (struct cwmp *cwmp, struct du_state_change_complete *p)
|
|
{
|
|
struct event_container *event_container;
|
|
struct session *session;
|
|
struct rpc *rpc_acs;
|
|
|
|
pthread_mutex_lock (&(cwmp->mutex_session_queue));
|
|
event_container = cwmp_add_event_container (cwmp, EVENT_IDX_11DU_STATE_CHANGE_COMPLETE, "");
|
|
if (event_container == NULL)
|
|
{
|
|
pthread_mutex_unlock (&(cwmp->mutex_session_queue));
|
|
return CWMP_MEM_ERR;
|
|
}
|
|
|
|
event_container = cwmp_add_event_container (cwmp, EVENT_IDX_M_ChangeDUState, p->command_key?p->command_key:"");
|
|
if (event_container == NULL)
|
|
{
|
|
pthread_mutex_unlock (&(cwmp->mutex_session_queue));
|
|
return CWMP_MEM_ERR;
|
|
}
|
|
session = list_entry (cwmp->head_event_container, struct session,head_event_container);
|
|
if((rpc_acs = cwmp_add_session_rpc_acs(session, RPC_ACS_DU_STATE_CHANGE_COMPLETE)) == NULL)
|
|
{
|
|
pthread_mutex_unlock (&(cwmp->mutex_session_queue));
|
|
return CWMP_MEM_ERR;
|
|
}
|
|
rpc_acs->extra_data = (void *)p;
|
|
pthread_mutex_unlock (&(cwmp->mutex_session_queue));
|
|
return CWMP_OK;
|
|
}
|
|
|
|
int cwmp_root_cause_getRPCMethod (struct cwmp *cwmp)
|
|
{
|
|
char acsurl[256];
|
|
int error,cmp=0;
|
|
struct event_container *event_container;
|
|
struct session *session;
|
|
|
|
if (cwmp->env.periodic == CWMP_START_PERIODIC)
|
|
{
|
|
pthread_mutex_lock (&(cwmp->mutex_session_queue));
|
|
cwmp->env.periodic = 0;
|
|
event_container = cwmp_add_event_container (cwmp, EVENT_IDX_2PERIODIC, "");
|
|
if (event_container == NULL)
|
|
{
|
|
pthread_mutex_unlock (&(cwmp->mutex_session_queue));
|
|
return CWMP_MEM_ERR;
|
|
}
|
|
cwmp_save_event_container (cwmp,event_container);
|
|
session = list_entry (cwmp->head_event_container, struct session,head_event_container);
|
|
if(cwmp_add_session_rpc_acs(session, RPC_ACS_GET_RPC_METHODS) == NULL)
|
|
{
|
|
pthread_mutex_unlock (&(cwmp->mutex_session_queue));
|
|
return CWMP_MEM_ERR;
|
|
}
|
|
pthread_mutex_unlock (&(cwmp->mutex_session_queue));
|
|
}
|
|
|
|
return CWMP_OK;
|
|
}
|
|
|
|
void *thread_handle_notify(void *v)
|
|
{
|
|
struct cwmp *cwmp = (struct cwmp *) v;
|
|
|
|
for(;;)
|
|
{
|
|
pthread_mutex_lock(&(cwmp->mutex_handle_notify));
|
|
pthread_cond_wait(&(cwmp->threshold_handle_notify), &(cwmp->mutex_handle_notify));
|
|
pthread_mutex_unlock(&(cwmp->mutex_handle_notify));
|
|
while(cwmp->count_handle_notify) {
|
|
cwmp_add_notification();
|
|
}
|
|
|
|
}
|
|
return CWMP_OK;
|
|
}
|
|
|
|
void *thread_event_periodic (void *v)
|
|
{
|
|
struct cwmp *cwmp = (struct cwmp *) v;
|
|
struct event_container *event_container;
|
|
static int periodic_interval;
|
|
static bool periodic_enable;
|
|
static time_t periodic_time;
|
|
static struct timespec periodic_timeout = {0, 0};
|
|
time_t current_time;
|
|
long int delta_time;
|
|
|
|
periodic_interval = cwmp->conf.period;
|
|
periodic_enable = cwmp->conf.periodic_enable;
|
|
periodic_time = cwmp->conf.time;
|
|
|
|
for(;;)
|
|
{
|
|
pthread_mutex_lock (&(cwmp->mutex_periodic));
|
|
if (cwmp->conf.periodic_enable)
|
|
{
|
|
current_time = time(NULL);
|
|
if(periodic_time != 0)
|
|
{
|
|
delta_time = (current_time - periodic_time) % periodic_interval;
|
|
if (delta_time >= 0)
|
|
periodic_timeout.tv_sec = current_time + periodic_interval - delta_time;
|
|
else
|
|
periodic_timeout.tv_sec = current_time - delta_time;
|
|
}
|
|
else
|
|
{
|
|
periodic_timeout.tv_sec = current_time + periodic_interval;
|
|
}
|
|
cwmp->session_status.next_periodic = periodic_timeout.tv_sec;
|
|
pthread_cond_timedwait(&(cwmp->threshold_periodic), &(cwmp->mutex_periodic), &periodic_timeout);
|
|
}
|
|
else
|
|
{
|
|
cwmp->session_status.next_periodic = 0;
|
|
pthread_cond_wait(&(cwmp->threshold_periodic), &(cwmp->mutex_periodic));
|
|
}
|
|
pthread_mutex_unlock (&(cwmp->mutex_periodic));
|
|
if (periodic_interval != cwmp->conf.period || periodic_enable != cwmp->conf.periodic_enable || periodic_time != cwmp->conf.time)
|
|
{
|
|
periodic_enable = cwmp->conf.periodic_enable;
|
|
periodic_interval = cwmp->conf.period;
|
|
periodic_time = cwmp->conf.time;
|
|
continue;
|
|
}
|
|
CWMP_LOG(INFO,"Periodic thread: add periodic event in the queue");
|
|
pthread_mutex_lock (&(cwmp->mutex_session_queue));
|
|
event_container = cwmp_add_event_container (cwmp, EVENT_IDX_2PERIODIC, "");
|
|
if (event_container == NULL)
|
|
{
|
|
pthread_mutex_unlock (&(cwmp->mutex_session_queue));
|
|
continue;
|
|
}
|
|
cwmp_save_event_container (cwmp,event_container);
|
|
pthread_mutex_unlock (&(cwmp->mutex_session_queue));
|
|
pthread_cond_signal(&(cwmp->threshold_session_send));
|
|
}
|
|
return CWMP_OK;
|
|
}
|
|
|
|
int cwmp_root_cause_event_periodic (struct cwmp *cwmp)
|
|
{
|
|
static int period = 0;
|
|
static bool periodic_enable = false;
|
|
static time_t periodic_time = 0;
|
|
char local_time[26] = {0};
|
|
struct tm *t_tm;
|
|
|
|
if (period==cwmp->conf.period && periodic_enable==cwmp->conf.periodic_enable && periodic_time==cwmp->conf.time)
|
|
{
|
|
return CWMP_OK;
|
|
}
|
|
pthread_mutex_lock (&(cwmp->mutex_periodic));
|
|
period = cwmp->conf.period;
|
|
periodic_enable = cwmp->conf.periodic_enable;
|
|
periodic_time = cwmp->conf.time;
|
|
CWMP_LOG(INFO,periodic_enable?"Periodic event is enabled. Interval period = %ds":"Periodic event is disabled", period);
|
|
|
|
t_tm = localtime(&periodic_time);
|
|
if (t_tm == NULL)
|
|
return CWMP_GEN_ERR;
|
|
|
|
if(strftime(local_time, sizeof(local_time), "%FT%T%z", t_tm) == 0)
|
|
return CWMP_GEN_ERR;
|
|
|
|
local_time[25] = local_time[24];
|
|
local_time[24] = local_time[23];
|
|
local_time[22] = ':';
|
|
local_time[26] = '\0';
|
|
|
|
CWMP_LOG(INFO,periodic_time?"Periodic time is %s":"Periodic time is Unknown", local_time);
|
|
pthread_mutex_unlock (&(cwmp->mutex_periodic));
|
|
pthread_cond_signal(&(cwmp->threshold_periodic));
|
|
return CWMP_OK;
|
|
}
|
|
|
|
void sotfware_version_value_change(struct cwmp *cwmp, struct transfer_complete *p)
|
|
{
|
|
char *current_software_version = NULL;
|
|
|
|
if (!p->old_software_version || p->old_software_version[0] == 0)
|
|
return;
|
|
|
|
current_software_version = cwmp->deviceid.softwareversion;
|
|
if (p->old_software_version && current_software_version &&
|
|
strcmp(p->old_software_version, current_software_version) != 0) {
|
|
pthread_mutex_lock (&(cwmp->mutex_session_queue));
|
|
cwmp_add_event_container (cwmp, EVENT_IDX_4VALUE_CHANGE, "");
|
|
pthread_mutex_unlock (&(cwmp->mutex_session_queue));
|
|
}
|
|
}
|
|
|
|
void connection_request_ip_value_change(struct cwmp *cwmp, int version)
|
|
{
|
|
char *bip = NULL;
|
|
struct event_container *event_container;
|
|
int error;
|
|
char *ip_version = (version == IPv6) ? strdup("ipv6") : strdup("ip");
|
|
char *ip_value = (version == IPv6) ? strdup(cwmp->conf.ipv6) : strdup(cwmp->conf.ip);
|
|
|
|
error = (version == IPv6) ? cwmp_load_saved_session(cwmp, &bip, CR_IPv6): cwmp_load_saved_session(cwmp, &bip, CR_IP);
|
|
|
|
if(bip == NULL)
|
|
{
|
|
bkp_session_simple_insert_in_parent("connection_request", ip_version, ip_value);
|
|
bkp_session_save();
|
|
FREE(ip_version);
|
|
FREE(ip_value);
|
|
return;
|
|
}
|
|
if (strcmp(bip, ip_value)!=0)
|
|
{
|
|
pthread_mutex_lock (&(cwmp->mutex_session_queue));
|
|
event_container = cwmp_add_event_container (cwmp, EVENT_IDX_4VALUE_CHANGE, "");
|
|
if (event_container == NULL)
|
|
{
|
|
FREE(bip);
|
|
pthread_mutex_unlock (&(cwmp->mutex_session_queue));
|
|
FREE(ip_version);
|
|
FREE(ip_value);
|
|
return;
|
|
}
|
|
cwmp_save_event_container (cwmp,event_container);
|
|
bkp_session_simple_insert_in_parent("connection_request", ip_version, ip_value);
|
|
bkp_session_save();
|
|
pthread_mutex_unlock (&(cwmp->mutex_session_queue));
|
|
pthread_cond_signal(&(cwmp->threshold_session_send));
|
|
}
|
|
FREE(bip);
|
|
FREE(ip_version);
|
|
FREE(ip_value);
|
|
}
|
|
|
|
void connection_request_port_value_change(struct cwmp *cwmp, int port)
|
|
{
|
|
char *bport = NULL;
|
|
struct event_container *event_container;
|
|
int error;
|
|
char bufport[32];
|
|
|
|
sprintf(bufport, "%d", port);
|
|
|
|
error = cwmp_load_saved_session(cwmp, &bport, CR_PORT);
|
|
|
|
if(bport == NULL)
|
|
{
|
|
bkp_session_simple_insert_in_parent("connection_request", "port", bufport);
|
|
bkp_session_save();
|
|
return;
|
|
}
|
|
if (strcmp(bport, bufport)!=0)
|
|
{
|
|
event_container = cwmp_add_event_container (cwmp, EVENT_IDX_4VALUE_CHANGE, "");
|
|
if (event_container == NULL)
|
|
{
|
|
FREE(bport);
|
|
return;
|
|
}
|
|
cwmp_save_event_container (cwmp,event_container);
|
|
bkp_session_simple_insert_in_parent("connection_request", "port", bufport);
|
|
bkp_session_save();
|
|
}
|
|
FREE(bport);
|
|
}
|
|
|
|
int cwmp_root_cause_events (struct cwmp *cwmp)
|
|
{
|
|
int error;
|
|
|
|
if (error = cwmp_root_cause_event_bootstrap(cwmp))
|
|
{
|
|
return error;
|
|
}
|
|
|
|
if (error = cwmp_root_cause_event_boot(cwmp))
|
|
{
|
|
return error;
|
|
}
|
|
|
|
if (error = cwmp_root_cause_getRPCMethod(cwmp))
|
|
{
|
|
return error;
|
|
}
|
|
|
|
if (error = cwmp_root_cause_event_periodic(cwmp))
|
|
{
|
|
return error;
|
|
}
|
|
return CWMP_OK;
|
|
}
|
|
|