Skip to content
Snippets Groups Projects
dmcwmp.c 81.8 KiB
Newer Older
  • Learn to ignore specific revisions
  •  *	Copyright (C) 2019 iopsys Software Solutions AB
    
    4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447
     *	  Author MOHAMED Kallel <mohamed.kallel@pivasoftware.com>
     *	  Author Imen Bhiri <imen.bhiri@pivasoftware.com>
     *	  Author Feten Besbes <feten.besbes@pivasoftware.com>
     *	  Author Omar Kallel <omar.kallel@pivasoftware.com>
     *
     */
    
    #include <stdarg.h>
    #include <time.h>
    #include <uci.h>
    #include <ctype.h>
    #include "dmuci.h"
    #include "dmcwmp.h"
    #include "dmmem.h"
    #include "device.h"
    #include "times.h"
    #include "upnp.h"
    #include "deviceinfo.h"
    #include "managementserver.h"
    #include "x_iopsys_eu_igmp.h"
    #include "x_iopsys_eu_ice.h"
    #include "x_iopsys_eu_power_mgmt.h"
    #include "x_iopsys_eu_ipacccfg.h"
    #include "x_iopsys_eu_logincfg.h"
    #include "x_iopsys_eu_syslog.h"
    #include "dmcommon.h"
    #include "wifi.h"
    #include "ethernet.h"
    #include "atm.h"
    #include "ptm.h"
    #include "bridging.h"
    #include "hosts.h"
    #include "dhcpv4.h"
    #include "ip.h"
    #include "ppp.h"
    #include "softwaremodules.h"
    #include "routing.h"
    #include "nat.h"
    #include "xmpp.h"
    #include "dmcwmp.h"
    #include "dmjson.h"
    #ifdef BBF_TR104
    #include "voice_services.h"
    #endif
    
    static char *get_parameter_notification(struct dmctx *ctx, char *param);
    static int remove_parameter_notification(char *param);
    static int set_parameter_notification(struct dmctx *ctx, char *param,char *value);
    static int get_value_obj(DMOBJECT_ARGS);
    static int get_value_param(DMPARAM_ARGS);
    static int mobj_get_value_in_param(DMOBJECT_ARGS);
    static int mparam_get_value_in_param(DMPARAM_ARGS);
    static int mparam_get_name(DMPARAM_ARGS);
    static int mobj_get_name(DMOBJECT_ARGS);
    static int mparam_get_name_in_param(DMPARAM_ARGS);
    static int mobj_get_name_in_param(DMOBJECT_ARGS);
    static int mparam_get_name_in_obj(DMPARAM_ARGS);
    static int mobj_get_name_in_obj(DMOBJECT_ARGS);
    static int inform_check_obj(DMOBJECT_ARGS);
    static int inform_check_param(DMPARAM_ARGS);
    static int mparam_add_object(DMPARAM_ARGS);
    static int mobj_add_object(DMOBJECT_ARGS);
    static int delete_object_obj(DMOBJECT_ARGS);
    static int delete_object_param(DMPARAM_ARGS);
    static int mobj_set_value(DMOBJECT_ARGS);
    static int mparam_set_value(DMPARAM_ARGS);
    static int mobj_get_notification_in_param(DMOBJECT_ARGS);
    static int mobj_get_notification(DMOBJECT_ARGS);
    static int mparam_get_notification(DMPARAM_ARGS);
    static int mparam_get_notification_in_param(DMPARAM_ARGS);
    static int mparam_set_notification_in_obj(DMPARAM_ARGS);
    static int mobj_set_notification_in_param(DMOBJECT_ARGS);
    static int mparam_set_notification_in_param(DMPARAM_ARGS);
    static int mobj_set_notification_in_obj(DMOBJECT_ARGS);
    #ifdef BBF_TR064
    static int mparam_upnp_get_instances(DMPARAM_ARGS);
    static int mobj_upnp_get_instances(DMOBJECT_ARGS);
    static int mparam_upnp_structured_get_value_in_param(DMPARAM_ARGS);
    static int mparam_upnp_get_supportedparams(DMPARAM_ARGS);
    static int mparam_upnp_set_attributes(DMPARAM_ARGS);
    static int mobj_upnp_set_attributes(DMOBJECT_ARGS);
    static int mobj_upnp_get_supportedparams(DMOBJECT_ARGS);
    static int mparam_upnp_get_attributes(DMPARAM_ARGS);
    static int mobj_upnp_get_attributes(DMOBJECT_ARGS);
    static int upnp_get_value_obj(DMOBJECT_ARGS);
    static int upnp_get_value_param(DMPARAM_ARGS);
    static int mobj_upnp_get_value_in_param(DMOBJECT_ARGS);
    static int mparam_upnp_get_value_in_param(DMPARAM_ARGS);
    static int mobj_upnp_set_value(DMOBJECT_ARGS);
    static int mparam_upnp_set_value(DMPARAM_ARGS);
    static int upnp_delete_instance_param(DMPARAM_ARGS);
    static int upnp_delete_instance_obj(DMOBJECT_ARGS);
    static int mparam_upnp_add_instance(DMPARAM_ARGS);
    static int mobj_upnp_add_instance(DMOBJECT_ARGS);
    static int mparam_upnp_get_acldata(DMPARAM_ARGS);
    static int mobj_upnp_get_acldata(DMOBJECT_ARGS);
    static int mparam_upnp_get_instance_numbers(DMPARAM_ARGS);
    static int mobj_upnp_get_instance_numbers(DMOBJECT_ARGS);
    static int enabled_tracked_param_check_obj(DMOBJECT_ARGS);
    static int enabled_tracked_param_check_param(DMPARAM_ARGS);
    #endif
    static int enabled_notify_check_obj(DMOBJECT_ARGS);
    static int enabled_notify_check_param(DMPARAM_ARGS);
    static int enabled_notify_check_value_change_param(DMPARAM_ARGS);
    static int enabled_notify_check_value_change_obj(DMOBJECT_ARGS);
    static int get_linker_check_obj(DMOBJECT_ARGS);
    static int get_linker_check_param(DMPARAM_ARGS);
    static int get_linker_value_check_obj(DMOBJECT_ARGS);
    static int get_linker_value_check_param(DMPARAM_ARGS);
    
    
    LIST_HEAD(list_enabled_notify);
    LIST_HEAD(list_enabled_lw_notify);
    #ifdef BBF_TR064
    LIST_HEAD(list_upnp_enabled_onevent);
    LIST_HEAD(list_upnp_enabled_onalarm);
    LIST_HEAD(list_upnp_enabled_version);
    LIST_HEAD(list_upnp_changed_onevent);
    LIST_HEAD(list_upnp_changed_onalarm);
    LIST_HEAD(list_upnp_changed_version);
    #endif
    
    LIST_HEAD(list_execute_end_session);
    int end_session_flag = 0;
    int ip_version = 4;
    char dm_delim = DMDELIM_CWMP;
    char dmroot[64] = "Device";
    int bbfdatamodel_type = BBFDM_BOTH;
    unsigned int upnp_in_user_mask = DM_SUPERADMIN_MASK;
    
    
    struct notification notifications[] = {
    	[0] = {"0", "disabled"},
    	[1] = {"1", "passive"},
    	[2] = {"2", "active"},
    	[3] = {"3", "passive_lw"},
    	[4] = {"4", "passive_passive_lw"},
    	[5] = {"5", "active_lw"},
    	[6] = {"6", "passive_active_lw"}
    };
    
    struct dm_acl dm_acl[] = {
    	[0] = {DM_PUBLIC_LIST, "public_list"},
    	[1] = {DM_PUBLIC_READ, "public_read"},
    	[2] = {DM_PUBLIC_WRITE, "public_write"},
    	[3] = {DM_BASIC_LIST, "basic_list"},
    	[4] = {DM_BASIC_READ, "basic_read"},
    	[5] = {DM_BASIC_WRITE, "basic_write"},
    	[6] = {DM_XXXADMIN_LIST, "xxxadmin_list"},
    	[7] = {DM_XXXADMIN_READ, "xxxadmin_read"},
    	[8] = {DM_XXXADMIN_WRITE, "xxxadmin_write"},
    };
    
    char *DMT_TYPE[] = {
    [DMT_STRING] = "xsd:string",
    [DMT_UNINT] = "xsd:unsignedInt",
    [DMT_INT] = "xsd:int",
    [DMT_LONG] = "xsd:long",
    [DMT_BOOL] = "xsd:boolean",
    [DMT_TIME] = "xsd:dateTime",
    [DMT_HEXBIN] = "xsd:hexbin",
    };
    
    #ifdef BBF_TR064
    unsigned int UPNP_DMT_TYPE[] = {
    [DMT_STRING] = NODE_DATA_ATTRIBUTE_TYPESTRING,
    [DMT_UNINT] = NODE_DATA_ATTRIBUTE_TYPEINT,
    [DMT_INT] = NODE_DATA_ATTRIBUTE_TYPEINT,
    [DMT_LONG] = NODE_DATA_ATTRIBUTE_TYPELONG,
    [DMT_BOOL] = NODE_DATA_ATTRIBUTE_TYPEBOOL,
    [DMT_TIME] = NODE_DATA_ATTRIBUTE_TYPEDATETIME,
    [DMT_HEXBIN] = NODE_DATA_ATTRIBUTE_TYPEBIN,
    };
    #endif
    
    struct dm_permession_s DMREAD = {"0", NULL};
    struct dm_permession_s DMWRITE = {"1", NULL};
    struct dm_forced_inform_s DMFINFRM = {1, NULL};
    struct dm_notif_s DMNONE = { "0", NULL };
    struct dm_notif_s DMPASSIVE = { "1", NULL };
    struct dm_notif_s DMACTIVE = { "2", NULL };
    
    int plugin_obj_match(DMOBJECT_ARGS)
    {
    	if (node->matched)
    		return 0;
    	if (!dmctx->inparam_isparam && strstr(node->current_object, dmctx->in_param) == node->current_object) {
    		node->matched++;
    		dmctx->findparam = 1;
    		return 0;
    	}
    	if (strstr(dmctx->in_param, node->current_object) == dmctx->in_param) {
    		return 0;
    	}
    	return FAULT_9005;
    }
    
    int plugin_leaf_match(DMOBJECT_ARGS)
    {
    	char *str;
    	if (node->matched)
    		return 0;
    	if (!dmctx->inparam_isparam)
    		return FAULT_9005;
    	str = dmctx->in_param + strlen(node->current_object);
    	if (!strchr(str, dm_delim))
    		return 0;
    	return FAULT_9005;
    }
    
    int plugin_obj_forcedinform_match(DMOBJECT_ARGS)
    {
    	unsigned char fi;
    	if (forced_inform) {
    		if (forced_inform->get_forced_inform)
    			fi = forced_inform->get_forced_inform(node->current_object, dmctx, data, instance);
    		else
    			fi = forced_inform->val;
    		if (fi)
    			return 0;
    	}
    	return FAULT_9005;
    }
    
    int plugin_leaf_onlyobj_match(DMOBJECT_ARGS)
    {
    	return FAULT_9005;
    }
    
    int plugin_obj_nextlevel_match(DMOBJECT_ARGS)
    {
    	if (node->matched > 1)
    		return FAULT_9005;
    	if (node->matched) {
    		node->matched++;
    		return 0;
    	}
    	if (!dmctx->inparam_isparam && strstr(node->current_object, dmctx->in_param) == node->current_object) {
    		node->matched++;
    		dmctx->findparam = 1;
    		return 0;
    	}
    	if (strstr(dmctx->in_param, node->current_object) == dmctx->in_param) {
    		return 0;
    	}
    	return FAULT_9005;
    }
    
    int plugin_leaf_nextlevel_match(DMOBJECT_ARGS)
    {
    	char *str;
    	if (node->matched > 1)
    		return FAULT_9005;
    	if (node->matched)
    		return 0;
    	if (!dmctx->inparam_isparam)
    		return FAULT_9005;
    	str = dmctx->in_param + strlen(node->current_object);
    	if (!strchr(str, dm_delim))
    		return 0;
    	return FAULT_9005;
    }
    
    int dm_browse_leaf(struct dmctx *dmctx, DMNODE *parent_node, DMLEAF *leaf, void *data, char *instance)
    {
    	int err = 0;
    	if (!leaf)
    		return 0;
    
    	for (; leaf->parameter; leaf++) {
    		if (leaf->bbfdm_type != bbfdatamodel_type &&  leaf->bbfdm_type != BBFDM_BOTH)
    			continue;
    		err = dmctx->method_param(dmctx, parent_node, leaf->parameter, leaf->permission, leaf->type, leaf->getvalue, leaf->setvalue, leaf->forced_inform, leaf->notification, data, instance);
    		if (dmctx->stop)
    			return err;
    	}
    	return err;
    }
    
    int dm_browse(struct dmctx *dmctx, DMNODE *parent_node, DMOBJ *entryobj, void *data, char *instance)
    {
    	int err = 0;
    	if (!entryobj)
    		return 0;
    	char *parent_obj = parent_node->current_object;
    	for (; entryobj->obj; entryobj++) {
    		DMNODE node = {0};
    		node.obj = entryobj;
    		node.parent = parent_node;
    		node.instance_level = parent_node->instance_level;
    		node.matched = parent_node->matched;
    		dmasprintf(&(node.current_object), "%s%s%c", parent_obj, entryobj->obj, dm_delim);
    		if (entryobj->bbfdm_type != bbfdatamodel_type &&  entryobj->bbfdm_type != BBFDM_BOTH)
    			continue;
    		if (dmctx->checkobj) {
    			err = dmctx->checkobj(dmctx, &node, entryobj->permission, entryobj->addobj, entryobj->delobj, entryobj->forced_inform, entryobj->notification, entryobj->get_linker, data, instance);
    			if (err)
    				continue;
    		}
    		err = dmctx->method_obj(dmctx, &node, entryobj->permission, entryobj->addobj, entryobj->delobj, entryobj->forced_inform, entryobj->notification, entryobj->get_linker, data, instance);
    		if (dmctx->stop)
    			return err;
    		if (entryobj->checkobj && ((entryobj->checkobj)(dmctx, data) == false) ){
    			continue;
    		}
    		if (entryobj->browseinstobj) {
    			if (dmctx->instance_wildchar) {
    				dm_link_inst_obj(dmctx, &node, data, dmctx->instance_wildchar);
    				continue;
    			}
    			else {
    				entryobj->browseinstobj(dmctx, &node, data, instance);
    				err = dmctx->faultcode;
    				if (dmctx->stop)
    					return err;
    				continue;
    			}
    		}
    		if (entryobj->leaf) {
    			if (dmctx->checkleaf) {
    				err = dmctx->checkleaf(dmctx, &node, entryobj->permission, entryobj->addobj, entryobj->delobj, entryobj->forced_inform, entryobj->notification, entryobj->get_linker, data, instance);
    				if (!err) {
    					err = dm_browse_leaf(dmctx, &node, entryobj->leaf, data, instance);
    					if (dmctx->stop)
    						return err;
    				}
    			} else {
    				err = dm_browse_leaf(dmctx, &node, entryobj->leaf, data, instance);
    				if (dmctx->stop)
    					return err;
    			}
    		}
    		if (entryobj->nextobj) {
    			err = dm_browse(dmctx, &node, entryobj->nextobj, data, instance);
    			if (dmctx->stop)
    				return err;
    		}
    	}
    	return err;
    }
    
    int dm_link_inst_obj(struct dmctx *dmctx, DMNODE *parent_node, void *data, char *instance)
    {
    	int err = 0;
    	char *parent_obj;
    	DMOBJ *prevobj = parent_node->obj;
    	DMOBJ *nextobj = prevobj->nextobj;
    	DMLEAF *nextleaf = prevobj->leaf;
    
    	DMNODE node = {0};
    	node.obj = prevobj;
    	node.parent = parent_node;
    	node.instance_level = parent_node->instance_level + 1;
    	node.is_instanceobj = 1;
    	node.matched = parent_node->matched;
    
    	parent_obj = parent_node->current_object;
    	if (instance == NULL)
    		return -1;
    	dmasprintf(&node.current_object, "%s%s%c", parent_obj, instance, dm_delim);
    	if (dmctx->checkobj) {
    		err = dmctx->checkobj(dmctx, &node, prevobj->permission, prevobj->addobj, prevobj->delobj, prevobj->forced_inform, prevobj->notification, prevobj->get_linker, data, instance);
    		if (err)
    			return err;
    	}
    	err = dmctx->method_obj(dmctx, &node, prevobj->permission, prevobj->addobj, prevobj->delobj, prevobj->forced_inform, prevobj->notification, prevobj->get_linker, data, instance);
    	if (dmctx->stop)
    		return err;
    	if (nextleaf) {
    		if (dmctx->checkleaf) {
    			err = dmctx->checkleaf(dmctx, &node, prevobj->permission, prevobj->addobj, prevobj->delobj, prevobj->forced_inform, prevobj->notification, prevobj->get_linker, data, instance);
    			if (!err) {
    				err = dm_browse_leaf(dmctx, &node, nextleaf, data, instance);
    				if (dmctx->stop)
    					return err;
    			}
    		} else {
    			err = dm_browse_leaf(dmctx, &node, nextleaf, data, instance);
    			if (dmctx->stop)
    				return err;
    		}
    	}
    	if (nextobj) {
    		err = dm_browse(dmctx, &node, nextobj, data, instance);
    		if (dmctx->stop)
    			return err;
    	}
    	return err;
    }
    
    int rootcmp(char *inparam, char *rootobj)
    {
    	int cmp = -1;
    	char buf[32];
    	sprintf(buf, "%s%c", rootobj, dm_delim);
    	cmp = strcmp(inparam, buf);
    	return cmp;
    }
    
    //END//
    /***************************
     * update instance & alias
     ***************************/
    char *handle_update_instance(int instance_ranck, struct dmctx *ctx, char **last_inst, char * (*up_instance)(int action, char **last_inst, void *argv[]), int argc, ...)
    {
    	va_list arg;
    	char *instance, *inst_mode;
    	char *alias;
    	int i = 0;
    	unsigned int pos = instance_ranck - 1;
    	unsigned int alias_resister = 0, max, action;
    	void *argv[argc];
    	char *str;
    
    	va_start(arg, argc);
    	for (i = 0; i < argc; i++) {
    		argv[i] = va_arg(arg, void*);
    	}
    	va_end(arg);
    	if (ctx->amd_version >= AMD_4) {
    		if(pos < ctx->nbrof_instance) {
    			action = (ctx->alias_register & (1 << pos)) ? INSTANCE_UPDATE_ALIAS : INSTANCE_UPDATE_NUMBER;
    		} else {
    			action = (ctx->instance_mode == INSTANCE_MODE_ALIAS) ? INSTANCE_UPDATE_ALIAS : INSTANCE_UPDATE_NUMBER;
    		}
    	} else {
    		action = INSTANCE_UPDATE_NUMBER;
    	}
    
    	instance = up_instance(action, last_inst, argv);
    	if(*last_inst)
    		ctx->inst_buf[pos] = dmstrdup(*last_inst);
    
    	return instance;
    }
    char *update_instance(struct uci_section *s, char *last_inst, char *inst_opt)
    {
    	char *instance;
    	void *argv[3];
    
    	argv[0] = s;
    	argv[1] = inst_opt;
    	argv[2] = "";
    
    
    	instance = update_instance_alias_bbfdm(0, &last_inst, argv);
    
    	return instance;
    }
    
    
    char *update_instance_bbfdm(struct uci_section *s, char *last_inst, char *inst_opt)
    
    {
    	char *instance;
    	void *argv[3];
    
    	argv[0]= s;
    	argv[1]= inst_opt;
    	argv[2]= "";
    
    	instance = update_instance_alias_bbfdm(0, &last_inst, argv);
    
    	return instance;
    }
    
    
    char *update_instance_alias_bbfdm(int action, char **last_inst , void *argv[])
    
    {
    	char *instance;
    	char *alias;
    	char buf[64] = {0};
    	struct uci_section *s = (struct uci_section *) argv[0];
    	char *inst_opt = (char *) argv[1];
    	char *alias_opt = (char *) argv[2];
    	dmuci_get_value_by_section_string(s, inst_opt, &instance);
    	if (instance[0] == '\0') {
    		if (*last_inst == NULL)
    			sprintf(buf, "%d", 1);
    		else
    			sprintf(buf, "%d", atoi(*last_inst)+1);
    
    		instance = DMUCI_SET_VALUE_BY_SECTION(bbfdm, s, inst_opt, buf);
    
    	}
    	*last_inst = instance;
    	if (action == INSTANCE_MODE_ALIAS) {
    		dmuci_get_value_by_section_string(s, alias_opt, &alias);
    		if (alias[0] == '\0') {
    			sprintf(buf, "cpe-%s", instance);
    
    			alias = DMUCI_SET_VALUE_BY_SECTION(bbfdm, s, alias_opt, buf);
    
    		}
    		sprintf(buf, "[%s]", alias);
    		instance = dmstrdup(buf);
    	}
    	return instance;
    }
    
    char *update_instance_alias(int action, char **last_inst, void *argv[])
    {
    	char *instance;
    	char *alias;
    	char buf[64] = {0};
    
    	struct uci_section *s = (struct uci_section *) argv[0];
    	char *inst_opt = (char *) argv[1];
    	char *alias_opt = (char *) argv[2];
    
    	dmuci_get_value_by_section_string(s, inst_opt, &instance);
    	if (instance[0] == '\0') {
    		if (*last_inst == NULL)
    			sprintf(buf, "%d", 1);
    		else
    			sprintf(buf, "%d", atoi(*last_inst) + 1);
    		instance = dmuci_set_value_by_section(s, inst_opt, buf);
    	}
    	*last_inst = instance;
    	if (action == INSTANCE_MODE_ALIAS) {
    		dmuci_get_value_by_section_string(s, alias_opt, &alias);
    		if (alias[0] == '\0') {
    			sprintf(buf, "cpe-%s", instance);
    			alias = dmuci_set_value_by_section(s, alias_opt, buf);
    		}
    		sprintf(buf, "[%s]", alias);
    		instance = dmstrdup(buf);
    	}
    	return instance;
    }
    
    char *update_instance_without_section(int action, char **last_inst, void *argv[])
    {
    	char *instance;
    	char *alias;
    	char buf[64] = {0};
    
    	int instnbr = (int) argv[0];
    
    	if (action == INSTANCE_MODE_ALIAS) {
    		sprintf(buf, "[cpe-%d]", instnbr);
    		instance = dmstrdup(buf);
    	} else {
    		sprintf(buf, "%d", instnbr);
    		instance = dmstrdup(buf);
    	}
    	return instance;
    }
    
    
    char *get_vlan_last_instance_bbfdm(char *package, char *section, char *opt_inst, char *vlan_method)
    
    {
    	struct uci_section *s, *confsect;
    	char *inst = NULL, *last_inst = NULL, *type, *sect_name;
    
    
    	uci_path_foreach_sections(bbfdm, package, section, s) {
    
    		dmuci_get_value_by_section_string(s, "section_name", &sect_name);
    		get_config_section_of_dmmap_section("network", "device", sect_name, &confsect);
    		dmuci_get_value_by_section_string(confsect, "type", &type);
    		if ((strcmp(vlan_method, "2") != 0 && strcmp(vlan_method, "1") != 0) || (strcmp(vlan_method, "1") == 0 && strcmp(type, "untagged") == 0) )
    			continue;
    
    		inst = update_instance_bbfdm(s, last_inst, opt_inst);
    
    		if(last_inst)
    			dmfree(last_inst);
    		last_inst = dmstrdup(inst);
    	}
    	return inst;
    }
    
    
    char *get_last_instance_bbfdm(char *package, char *section, char *opt_inst)
    
    {
    	struct uci_section *s;
    	char *inst = NULL;
    	char *last_inst = NULL;
    
    
    	uci_path_foreach_sections(bbfdm, package, section, s) {
    		inst = update_instance_bbfdm(s, last_inst, opt_inst);
    
    		if(last_inst)
    			dmfree(last_inst);
    		last_inst = dmstrdup(inst);
    	}
    	return inst;
    }
    
    
    char *get_last_instance_bbfdm_without_update(char *package, char *section, char *opt_inst)
    
    {
    	struct uci_section *s;
    	char *inst = NULL;
    	char *last_inst = NULL;
    
    
    	uci_path_foreach_sections(bbfdm, package, section, s) {
    
    		dmuci_get_value_by_section_string(s, opt_inst, &inst);
    		if(last_inst)
    			dmfree(last_inst);
    		last_inst = dmstrdup(inst);
    	}
    	return inst;
    }
    
    char *get_last_instance(char *package, char *section, char *opt_inst)
    {
    	struct uci_section *s;
    	char *inst = NULL;
    	char *last_inst = NULL;
    	if (package == DMMAP)
    	{
    
    		uci_path_foreach_sections(bbfdm, "dmmap", section, s) {
    			inst = update_instance_bbfdm(s, last_inst, opt_inst);
    
    			if(last_inst)
    				dmfree(last_inst);
    			last_inst = dmstrdup(inst);
    		}
    	}
    	else
    	{
    		uci_foreach_sections(package, section, s) {
    			inst = update_instance(s, inst, opt_inst);
    		}
    	}
    	return inst;
    }
    
    
    char *get_last_instance_lev2_bbfdm_dmmap_opt(char* dmmap_package, char *section,  char *opt_inst, char *opt_check, char *value_check)
    
    {
    	struct uci_section *s;
    	char *instance = NULL, *section_name= NULL;
    	char *last_inst = NULL;
    
    
    	uci_path_foreach_option_eq(bbfdm, dmmap_package, section, opt_check, value_check, s) {
    
    		dmuci_get_value_by_section_string(s, "section_name", &section_name);
    
    		instance = update_instance_bbfdm(s, last_inst, opt_inst);
    
    		if(last_inst)
    			dmfree(last_inst);
    		last_inst = dmstrdup(instance);
    	}
    	return instance;
    }
    
    char *get_last_instance_lev2_bbfdm(char *package, char *section, char* dmmap_package, char *opt_inst, char *opt_check, char *value_check)
    
    {
    	struct uci_section *s, *dmmap_section;
    	char *instance = NULL;
    	char *last_inst = NULL, *v= NULL;
    
    	check_create_dmmap_package(dmmap_package);
    	uci_foreach_option_cont(package, section, opt_check, value_check, s) {
    		get_dmmap_section_of_config_section(dmmap_package, section, section_name(s), &dmmap_section);
    		if(dmmap_section == NULL){
    
    			dmuci_add_section_bbfdm(dmmap_package, section, &dmmap_section, &v);
    
    			dmuci_set_value_by_section(dmmap_section, "section_name", section_name(s));
    		}
    
    		instance = update_instance_bbfdm(dmmap_section, last_inst, opt_inst);
    
    		if(last_inst)
    			dmfree(last_inst);
    		last_inst = dmstrdup(instance);
    	}
    	return instance;
    }
    
    char *get_last_instance_lev2(char *package, char *section, char *opt_inst, char *opt_check, char *value_check)
    {
    	struct uci_section *s;
    	char *instance = NULL;
    	char *last_inst = NULL;
    
    	if (package == DMMAP)
    	{
    
    		uci_path_foreach_option_cont(bbfdm, package, section, opt_check, value_check, s) {
    			instance = update_instance_bbfdm(s, last_inst, opt_inst);
    
    			if(last_inst)
    				dmfree(last_inst);
    			last_inst = dmstrdup(instance);
    		}
    	}
    	else
    	{
    		uci_foreach_option_cont(package, section, opt_check, value_check, s) {
    			instance = update_instance(s, instance, opt_inst);
    		}
    	}
    	return instance;
    }
    
    int get_empty(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
    {
    	*value = "";
    	return 0;
    }
    
    void add_list_paramameter(struct dmctx *ctx, char *param_name, char *param_data, char *param_type, char *param_version, unsigned int flags)
    {
    	struct dm_parameter *dm_parameter;
    	struct list_head *ilist;
    	list_for_each(ilist, &ctx->list_parameter)
    	{
    		dm_parameter = list_entry(ilist, struct dm_parameter, list);
    		int cmp = strcmp(dm_parameter->name, param_name);
    		if (cmp == 0) {
    			return;
    		} else if (cmp > 0) {
    			break;
    		}
    	}
    	dm_parameter = dmcalloc(1, sizeof(struct dm_parameter));
    	_list_add(&dm_parameter->list, ilist->prev, ilist);
    	dm_parameter->name = param_name;
    	dm_parameter->data = param_data ? param_data : ""; //allocate memory in function
    	dm_parameter->type = param_type;
    	dm_parameter->version = param_version;
    	dm_parameter->flags = flags;
    }
    
    void del_list_parameter(struct dm_parameter *dm_parameter)
    {
    	list_del(&dm_parameter->list);
    	dmfree(dm_parameter->name);
    	dmfree(dm_parameter);
    }
    
    void free_all_list_parameter(struct dmctx *ctx)
    {
    	struct dm_parameter *dm_parameter;
    	while (ctx->list_parameter.next != &ctx->list_parameter) {
    		dm_parameter = list_entry(ctx->list_parameter.next, struct dm_parameter, list);
    		del_list_parameter(dm_parameter);
    	}
    }
    
    void add_set_list_tmp(struct dmctx *ctx, char *param, char *value, unsigned int flags)
    {
    	struct set_tmp *set_tmp;
    	set_tmp = dmcalloc(1, sizeof(struct set_tmp));
    	list_add_tail(&set_tmp->list, &ctx->set_list_tmp);
    	set_tmp->name = dmstrdup(param);
    	set_tmp->value = value ? dmstrdup(value) : NULL;
    	set_tmp->flags = flags;
    }
    
    void del_set_list_tmp(struct set_tmp *set_tmp)
    {
    	list_del(&set_tmp->list);
    	dmfree(set_tmp->name);
    	dmfree(set_tmp->value);
    	dmfree(set_tmp);
    }
    
    void free_all_set_list_tmp(struct dmctx *ctx)
    {
    	struct set_tmp *set_tmp;
    	while (ctx->set_list_tmp.next != &ctx->set_list_tmp) {
    		set_tmp = list_entry(ctx->set_list_tmp.next, struct set_tmp, list);
    		del_set_list_tmp(set_tmp);
    	}
    }
    
    void add_list_fault_param(struct dmctx *ctx, char *param, int fault)
    {
    	struct param_fault *param_fault;
    	if (param == NULL) param = "";
    
    	param_fault = dmcalloc(1, sizeof(struct param_fault));
    	list_add_tail(&param_fault->list, &ctx->list_fault_param);
    	param_fault->name = dmstrdup(param);
    	param_fault->fault = fault;
    }
    
    void del_list_fault_param(struct param_fault *param_fault)
    {
    	list_del(&param_fault->list);
    	dmfree(param_fault->name);
    	dmfree(param_fault);
    }
    
    void free_all_list_fault_param(struct dmctx *ctx)
    {
    	struct param_fault *param_fault;
    	while (ctx->list_fault_param.next != &ctx->list_fault_param) {
    		param_fault = list_entry(ctx->list_fault_param.next, struct param_fault, list);
    		del_list_fault_param(param_fault);
    	}
    }
    
    void add_list_enabled_lwnotify(struct dmctx *dmctx, char *param, char *notification, char *value)
    {
    	struct dm_enabled_notify *dm_enabled_notify;
    
    	dm_enabled_notify = calloc(1, sizeof(struct dm_enabled_notify)); // Should be calloc and not dmcalloc
    	list_add_tail(&dm_enabled_notify->list, &list_enabled_lw_notify);
    	dm_enabled_notify->name = strdup(param); // Should be strdup and not dmstrdup
    	dm_enabled_notify->value = value ? strdup(value) : strdup(""); // Should be strdup and not dmstrdup
    	dm_enabled_notify->notification = strdup(notification); // Should be strdup and not dmstrdup
    }
    
    void del_list_enabled_notify(struct dm_enabled_notify *dm_enabled_notify)
    {
    	list_del(&dm_enabled_notify->list); // Should be free and not dmfree
    	free(dm_enabled_notify->name);
    	free(dm_enabled_notify->value);
    	free(dm_enabled_notify->notification);
    	free(dm_enabled_notify);
    }
    
    void free_all_list_enabled_lwnotify()
    {
    	struct dm_enabled_notify *dm_enabled_notify;
    	while (list_enabled_lw_notify.next != &list_enabled_lw_notify) {
    		dm_enabled_notify = list_entry(list_enabled_lw_notify.next, struct dm_enabled_notify, list);
    		del_list_enabled_notify(dm_enabled_notify);
    	}
    }
    
    int dm_update_file_enabled_notify(char *param, char *new_value)
    {
    	FILE *fp, *ftmp;
    	char buf[512];
    	char *parameter, *notification, *value, *type, *jval;
    
    	fp = fopen(DM_ENABLED_NOTIFY, "r");
    	if (fp == NULL)
    		return 0;
    
    	ftmp = fopen(DM_ENABLED_NOTIFY_TEMPORARY, "a");
    	if (ftmp == NULL) {
    		fclose(fp);
    		return 0;
    	}
    
    	while (fgets(buf, 512, fp) != NULL) {
    		int len = strlen(buf);
    		if (len)
    			buf[len-1] = '\0';
    		dmjson_parse_init(buf);
    		dmjson_get_var("parameter", &jval);
    		parameter = dmstrdup(jval);
    		dmjson_get_var("value", &jval);
    		value = dmstrdup(jval);
    		dmjson_get_var("notification", &jval);
    		notification = dmstrdup(jval);
    		dmjson_get_var("type", &jval);
    		type = dmstrdup(jval);
    		dmjson_parse_fini();
    		if (strcmp(parameter, param) == 0)
    			dmjson_fprintf(ftmp, 4, DMJSON_ARGS{{"parameter", parameter}, {"notification", notification}, {"value", new_value}, {"type", type}});
    		else
    			dmjson_fprintf(ftmp, 4, DMJSON_ARGS{{"parameter", parameter}, {"notification", notification}, {"value", value}, {"type", type}});
    	}
    	fclose(fp);
    	fclose(ftmp);
    
    	return 0;
    }
    
    void dm_update_enabled_notify(struct dm_enabled_notify *p, char *new_value)
    {
    	free(p->value); // Should be free and not dmfree
    	p->value = strdup(new_value);
    }
    
    void dm_update_enabled_notify_byname(char *name, char *new_value)
    {
    	int iscopy;
    	dm_update_file_enabled_notify(name, new_value);
    	remove(DM_ENABLED_NOTIFY);
    	iscopy = copy_temporary_file_to_original_file(DM_ENABLED_NOTIFY, DM_ENABLED_NOTIFY_TEMPORARY);
    	if(iscopy)
    		remove(DM_ENABLED_NOTIFY_TEMPORARY);
    
    }
    
    int update_param_instance_alias(struct dmctx *ctx, char *param, char **new_param)
    {
    	char *pch, *spch, *p;
    	char buf[512];
    	int i = 0, j = 0;
    	char pat[2] = {0};
    
    	char *dup = dmstrdup(param);
    	*pat = dm_delim;
    	p = buf;
    	for (pch = strtok_r(dup, pat, &spch); pch != NULL; pch = strtok_r(NULL, pat, &spch)) {
    		if (isdigit(pch[0])) {
    			dmstrappendchr(p, dm_delim);
    			dmstrappendstr(p, pch);
    			i++;
    		} else if (pch[0]== '[') {
    			dmstrappendchr(p, dm_delim);
    			dmstrappendstr(p, ctx->inst_buf[i]);
    			i++;
    		} else {
    			if (j > 0) {
    				dmstrappendchr(p, dm_delim);
    				dmstrappendstr(p, pch);
    			}
    			if (j == 0) {
    				dmstrappendstr(p, pch);
    				j++;
    			}
    		}
    	}
    	if (param[strlen(param) - 1] == dm_delim)
    		dmstrappendchr(p, dm_delim);
    	dmstrappendend(p);
    	*new_param = dmstrdup(buf);
    	dmfree(dup);
    	return 0;
    }
    
    static char *get_parameter_notification(struct dmctx *ctx, char *param)
    {
    	int i, maxlen = 0, len;
    	struct uci_list *list_notif;
    	char *pch, *new_param;
    	char *notification = "0";
    	struct uci_element *e;
    
    	update_param_instance_alias(ctx, param, &new_param);
    	for (i = (ARRAY_SIZE(notifications) - 1); i >= 0; i--) {
    		dmuci_get_option_value_list("cwmp", "@notifications[0]", notifications[i].type, &list_notif);
    		if (list_notif) {
    			uci_foreach_element(list_notif, e) {
    				pch = e->name;
    				if (strcmp(pch, new_param) == 0) {
    					notification = notifications[i].value;
    					return notification;
    				}
    				len = strlen(pch);
    				if (pch[len-1] == dm_delim) {
    					if (strstr(new_param, pch)) {
    						if (len > maxlen )
    						{
    							notification = notifications[i].value;
    							maxlen = len;
    						}
    					}
    				}
    			}
    		}
    	}
    	dmfree(new_param);
    	return notification;
    }
    
    static int remove_parameter_notification(char *param)
    {
    	int i;
    	struct uci_list *list_notif;
    	struct uci_element *e, *tmp;
    	char *pch;
    	for (i = (ARRAY_SIZE(notifications) - 1); i >= 0; i--) {
    		if (param[strlen(param)-1] == dm_delim) {
    			dmuci_get_option_value_list("cwmp", "@notifications[0]", notifications[i].type, &list_notif);
    			if (list_notif) {
    				uci_foreach_element_safe(list_notif, e, tmp) {
    					pch = tmp->name;
    					if (strstr(pch, param)) {
    						dmuci_del_list_value("cwmp", "@notifications[0]", notifications[i].type, pch);
    					}
    				}
    			}
    		} else {
    			dmuci_del_list_value("cwmp", "@notifications[0]", notifications[i].type, param);
    		}
    	}
    	return 0;
    }
    
    static int set_parameter_notification(struct dmctx *ctx, char *param, char *value)
    {
    	char *tmp = NULL, *buf = NULL, *pch, *new_param;
    	char *notification = NULL;
    	struct uci_section *s;
    	dmuci_get_section_type("cwmp", "@notifications[0]", &tmp);
    	update_param_instance_alias(ctx, param, &new_param);
    	if (!tmp || tmp[0] == '\0') {
    		dmuci_add_section("cwmp", "notifications", &s, &buf);
    	} else {
    		remove_parameter_notification(new_param);
    	}
    
    	notification = get_parameter_notification(ctx, new_param);
    	if (strcmp(notification, value) == 0) {
    		goto end;
    	}
    	if (strcmp(value, "1") == 0) {
    		dmuci_add_list_value("cwmp", "@notifications[0]", "passive", new_param);
    	} else if (strcmp(value, "2") == 0) {
    		dmuci_add_list_value("cwmp", "@notifications[0]", "active", new_param);
    	} else if (strcmp(value, "3") == 0) {
    		dmuci_add_list_value("cwmp", "@notifications[0]", "passive_lw", new_param);
    	} else if (strcmp(value, "4") == 0) {
    		dmuci_add_list_value("cwmp", "@notifications[0]", "passive_passive_lw", new_param);
    	} else if (strcmp(value, "5") == 0) {
    		dmuci_add_list_value("cwmp", "@notifications[0]", "active_lw", new_param);
    	} else if (strcmp(value, "6") == 0) {
    		dmuci_add_list_value("cwmp", "@notifications[0]", "passive_active_lw", new_param);
    	} else if (strcmp(value, "0") == 0) {
    		struct uci_list *list_notif;
    		struct uci_element *e;
    		int i, len;
    		for (i = (ARRAY_SIZE(notifications) - 1); i >= 1; i--) {
    			dmuci_get_option_value_list("cwmp", "@notifications[0]", notifications[i].type, &list_notif);
    			if (list_notif) {
    				uci_foreach_element(list_notif, e) {
    					pch = e->name;
    					len = strlen(pch);
    					if (pch[len-1] == dm_delim && strstr(new_param, pch)) {
    						dmuci_add_list_value("cwmp", "@notifications[0]", "disabled", new_param);
    						goto end;
    					}
    				}