static int analyzer_docsis_reg_status_update(struct analyzer_docsis_priv *priv, struct analyzer_docsis_cm *cm, enum docsis_mmt_rng_status new_status, struct timeval *ts, struct proto_process_stack *stack, unsigned int stack_index) { if (cm->ranging_status == new_status) return POM_OK; if (event_has_listener(priv->evt_cm_reg_status)) { struct event *evt = event_alloc(priv->evt_cm_reg_status); if (!evt) { pom_mutex_unlock(&priv->lock); return POM_ERR; } struct data *evt_data = evt->data; PTYPE_UINT8_SETVAL(evt_data[analyzer_docsis_cm_reg_status_old].value, cm->ranging_status); data_set(evt_data[analyzer_docsis_cm_reg_status_old]); PTYPE_UINT8_SETVAL(evt_data[analyzer_docsis_cm_reg_status_new].value, new_status); data_set(evt_data[analyzer_docsis_cm_reg_status_new]); PTYPE_MAC_SETADDR(evt_data[analyzer_docsis_cm_reg_status_mac].value, cm->mac); data_set(evt_data[analyzer_docsis_cm_reg_status_mac]); PTYPE_UINT8_SETVAL(evt_data[analyzer_docsis_cm_reg_status_timeout].value, T4_TIMEOUT * cm->t4_multiplier); data_set(evt_data[analyzer_docsis_cm_reg_status_timeout]); PTYPE_TIMESTAMP_SETVAL(evt_data[analyzer_docsis_cm_reg_status_time].value, *ts); data_set(evt_data[analyzer_docsis_cm_reg_status_time]); if (event_process(evt, stack, stack_index) != POM_OK) { pom_mutex_unlock(&priv->lock); return POM_ERR; } } cm->ranging_status = new_status; return POM_OK; }
int registry_config_save(char *config_name) { if (strlen(config_name) >= REGISTRY_CONFIG_NAME_MAX) { pomlog(POMLOG_ERR "Configuration name too long, max %u characters.", REGISTRY_CONFIG_NAME_MAX); return POM_ERR; } struct dataset_query *dsq_config_list = NULL, *dsq_config = NULL; struct datastore *sys_dstore = system_datastore(); if (!sys_dstore) return POM_ERR; struct datastore_connection *dc = datastore_connection_new(sys_dstore); if (!dc) return POM_ERR; dsq_config_list = datastore_dataset_query_open(sys_dstore, REGISTRY_CONFIG_LIST, registry_config_list_dataset_template, dc); if (!dsq_config_list) goto err; if (datastore_dataset_query_set_string_condition(dsq_config_list, 0, PTYPE_OP_EQ, config_name) != POM_OK) goto err; dsq_config = datastore_dataset_query_open(sys_dstore, REGISTRY_CONFIG, registry_config_dataset_template, dc); if (!dsq_config) goto err; if (datastore_transaction_begin(dc) != POM_OK) goto err; // Find out if we already have a config by that name int res = datastore_dataset_read_single(dsq_config_list); if (res == DATASET_QUERY_MORE) { // Delete existing stuff about this config if (datastore_dataset_query_set_uint64_condition(dsq_config, 0, PTYPE_OP_EQ, dsq_config_list->data_id) != POM_OK) goto err; if (datastore_dataset_delete(dsq_config_list) != DATASET_QUERY_OK) goto err; if (datastore_dataset_delete(dsq_config) != DATASET_QUERY_OK) goto err; } if (res < 0) goto err; // Add the config to the config list PTYPE_STRING_SETVAL(dsq_config_list->values[0].value, config_name); PTYPE_TIMESTAMP_SETVAL(dsq_config_list->values[1].value, pom_gettimeofday()); if (datastore_dataset_write(dsq_config_list) != DATASET_QUERY_OK) goto err; PTYPE_UINT64_SETVAL(dsq_config->values[0].value, dsq_config_list->data_id); registry_lock(); struct registry_class *cls; // Browse each class for (cls = registry_head; cls; cls = cls->next) { // Browse each instance of the class struct registry_instance *inst; for (inst = cls->instances; inst; inst = inst->next) { // Don't add the instance if it's not added by the user if (cls->instance_add) { // The system datastore will always exist if (inst == sys_dstore->reg_instance) continue; char *buff = malloc(strlen(cls->name) + 1 + strlen(inst->name) + 1); if (!buff) { pom_oom(strlen(cls->name) + 1 + strlen(inst->name) + 1); goto err_locked; } strcpy(buff, cls->name); strcat(buff, "."); strcat(buff, inst->name); PTYPE_STRING_SETVAL_P(dsq_config->values[1].value, buff); struct registry_param *p; for (p = inst->params; p && strcmp(p->name, "type"); p = p->next); if (p) { dsq_config->values[2].is_null = 0; char *type = PTYPE_STRING_GETVAL(p->value); PTYPE_STRING_SETVAL(dsq_config->values[2].value, type); } else { dsq_config->values[2].is_null = 1; } PTYPE_UINT8_SETVAL(dsq_config->values[3].value, registry_config_instance); if (datastore_dataset_write(dsq_config) != DATASET_QUERY_OK) goto err_locked; } // Browse the parametrers and add the non default ones struct registry_param *param; for (param = inst->params; param; param = param->next) { // Check if the parameter value is not the default one anymore if (param->default_value) { struct ptype *defval = ptype_alloc_from(param->value); if (!defval) goto err_locked; if (ptype_parse_val(defval, param->default_value) != POM_OK) { pomlog(POMLOG_ERR "Unable to parse default value !"); ptype_cleanup(defval); goto err_locked; } if (ptype_compare_val(PTYPE_OP_EQ, param->value, defval)) { // Param still has the default value, do nothing ptype_cleanup(defval); continue; } ptype_cleanup(defval); } char *buff = malloc(strlen(cls->name) + 1 + strlen(inst->name) + 1 + strlen(param->name) + 1); if (!buff) { pom_oom(strlen(cls->name) + 1 + strlen(inst->name) + 1 + strlen(param->name) + 1); goto err_locked; } strcpy(buff, cls->name); strcat(buff, "."); strcat(buff, inst->name); strcat(buff, "."); strcat(buff, param->name); PTYPE_STRING_SETVAL_P(dsq_config->values[1].value, buff); char *value = ptype_print_val_alloc(param->value, NULL); if (!value) goto err_locked; dsq_config->values[2].is_null = 0; PTYPE_STRING_SETVAL_P(dsq_config->values[2].value, value); PTYPE_UINT8_SETVAL(dsq_config->values[3].value, registry_config_instance_param); if (datastore_dataset_write(dsq_config) != DATASET_QUERY_OK) goto err_locked; } } } registry_config_serial++; registry_serial++; xmlrcpcmd_serial_inc(); registry_unlock(); if (datastore_transaction_commit(dc) != POM_OK) goto err; datastore_dataset_query_cleanup(dsq_config_list); datastore_dataset_query_cleanup(dsq_config); datastore_connection_release(dc); pomlog("Registry configuration saved as \"%s\"", config_name); return POM_OK; err_locked: registry_unlock(); err: if (dsq_config_list) datastore_dataset_query_cleanup(dsq_config_list); if (dsq_config) datastore_dataset_query_cleanup(dsq_config); if (dc) { datastore_transaction_rollback(dc); datastore_connection_release(dc); } return POM_ERR; }
static int analyzer_docsis_pkt_process(void *obj, struct packet *p, struct proto_process_stack *stack, unsigned int stack_index) { struct analyzer *analyzer = obj; struct analyzer_docsis_priv *priv = analyzer->priv; struct proto_process_stack *s = &stack[stack_index]; uint8_t *type = PTYPE_UINT8_GETVAL(s->pkt_info->fields_value[proto_docsis_mgmt_field_type]); char *mac_dst = PTYPE_MAC_GETADDR(s->pkt_info->fields_value[proto_docsis_mgmt_field_dst]); // FIXME : improve this filtering at the source // Filter some useless messages we don't care about if (*type == MMT_UCD2 || *type == MMT_UCD3 || *type == MMT_MDD) return POM_OK; if (*type != MMT_RNG_RSP) { pomlog(POMLOG_DEBUG "Unhandled DOCSIS MGMT message type %u for destination mac %02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX", *type, mac_dst[0], mac_dst[1], mac_dst[2], mac_dst[3], mac_dst[4], mac_dst[5]); return POM_OK; } // Use the last bits for the modem ID uint16_t id = ntohs(*(uint16_t*) (mac_dst + 4)) & ANALYZER_DOCSIS_CM_MASK; pom_mutex_lock(&priv->lock); struct analyzer_docsis_cm *cm; for (cm = priv->cms[id]; cm; cm = cm->next) { if (!memcmp(cm->mac, mac_dst, sizeof(cm->mac))) break; } if (!cm) { // Cable modem not found ! cm = malloc(sizeof(struct analyzer_docsis_cm)); if (!cm) { pom_oom(sizeof(struct analyzer_docsis_cm)); return POM_ERR; } memset(cm, 0, sizeof(struct analyzer_docsis_cm)); cm->t = timer_alloc(cm, analyzer_docsis_cm_timeout); if (!cm->t) { free(cm); return POM_ERR; } cm->analyzer = analyzer; memcpy(cm->mac, mac_dst, sizeof(cm->mac)); cm->t4_multiplier = 1; cm->next = priv->cms[id]; if (cm->next) cm->next->prev = cm; priv->cms[id] = cm; // Announce the new CM if (event_has_listener(priv->evt_cm_new)) { struct event *evt = event_alloc(priv->evt_cm_new); if (!evt) { pom_mutex_unlock(&priv->lock); return POM_ERR; } struct data *evt_data = evt->data; PTYPE_MAC_SETADDR(evt_data[analyzer_docsis_cm_new_mac].value, cm->mac); data_set(evt_data[analyzer_docsis_cm_new_mac]); PTYPE_STRING_SETVAL(evt_data[analyzer_docsis_cm_new_input].value, p->input->name); data_set(evt_data[analyzer_docsis_cm_new_input]); PTYPE_TIMESTAMP_SETVAL(evt_data[analyzer_docsis_cm_new_time].value, p->ts); data_set(evt_data[analyzer_docsis_cm_new_time]); if (event_process(evt, stack, stack_index) != POM_OK) { pom_mutex_unlock(&priv->lock); return POM_ERR; } } } switch (*type) { case MMT_RNG_RSP: analyzer_docsis_pkt_parse_rng_rsp(priv, cm, p, stack, stack_index); break; // FIXME If ranging_status is 0 and we receive another msg, probably it's actually registered // and we need to call analyzer_docsis_reg_status_update(); } timer_queue(cm->t, T4_TIMEOUT * cm->t4_multiplier); pom_mutex_unlock(&priv->lock); return POM_OK; }