int analyzer_ppp_pap_finalize(struct analyzer_ppp_pap_priv *apriv, struct analyzer_ppp_pap_ce_priv *cpriv) { if (!cpriv->evt_request) return POM_OK; struct event *evt = NULL; struct data *evt_data = NULL; struct data *evt_req_data = event_get_data(cpriv->evt_request); evt = event_alloc(apriv->evt_auth); if (!evt) return POM_ERR; evt_data = event_get_data(evt); if (ptype_copy(evt_data[analyzer_ppp_pap_auth_peer_id].value, evt_req_data[evt_ppp_pap_request_peer_id].value) != POM_OK) { event_cleanup(evt); return POM_ERR; } data_set(evt_data[analyzer_ppp_pap_auth_peer_id]); if (ptype_copy(evt_data[analyzer_ppp_pap_auth_password].value, evt_req_data[evt_ppp_pap_request_password].value) != POM_OK) { event_cleanup(evt); return POM_ERR; } data_set(evt_data[analyzer_ppp_pap_auth_password]); if (cpriv->client) { evt_data[analyzer_ppp_pap_auth_client].value = cpriv->client; data_set(evt_data[analyzer_ppp_pap_auth_client]); data_do_clean(evt_data[analyzer_ppp_pap_auth_client]); cpriv->client = NULL; } if (cpriv->server) { evt_data[analyzer_ppp_pap_auth_server].value = cpriv->server; data_set(evt_data[analyzer_ppp_pap_auth_server]); data_do_clean(evt_data[analyzer_ppp_pap_auth_server]); cpriv->server = NULL; } if (cpriv->vlan) { evt_data[analyzer_ppp_pap_auth_vlan].value = cpriv->vlan; data_set(evt_data[analyzer_ppp_pap_auth_vlan]); data_do_clean(evt_data[analyzer_ppp_pap_auth_vlan]); cpriv->vlan = NULL; } if (cpriv->top_proto) { PTYPE_STRING_SETVAL(evt_data[analyzer_ppp_pap_auth_top_proto].value, cpriv->top_proto); data_set(evt_data[analyzer_ppp_pap_auth_top_proto]); } if (ptype_copy(evt_data[analyzer_ppp_pap_auth_identifier].value, evt_req_data[evt_ppp_pap_request_identifier].value) != POM_OK) { event_cleanup(evt); return POM_ERR; } data_set(evt_data[analyzer_ppp_pap_auth_identifier]); if (cpriv->evt_ack_nack) { struct data *evt_ack_data = event_get_data(cpriv->evt_ack_nack); uint8_t code = *PTYPE_UINT8_GETVAL(evt_ack_data[evt_ppp_pap_ack_nack_code].value); if (code == 2) { PTYPE_BOOL_SETVAL(evt_data[analyzer_ppp_pap_auth_success].value, 1); } else { PTYPE_BOOL_SETVAL(evt_data[analyzer_ppp_pap_auth_success].value, 0); } data_set(evt_data[analyzer_ppp_pap_auth_success]); event_refcount_dec(cpriv->evt_ack_nack); cpriv->evt_ack_nack = NULL; } ptime ts = event_get_timestamp(cpriv->evt_request); event_refcount_dec(cpriv->evt_request); cpriv->evt_request = NULL; return event_process(evt, NULL, 0, ts); }
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_mutex_unlock(&priv->lock); 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) { pom_mutex_unlock(&priv->lock); 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 = event_get_data(evt); 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]); if (event_process(evt, stack, stack_index, p->ts) != 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_now(cm->t, T4_TIMEOUT * cm->t4_multiplier, p->ts); pom_mutex_unlock(&priv->lock); return POM_OK; }
int registry_config_load(char *config_name) { struct dataset_query *dsq_config_list = NULL, *dsq_config = NULL; struct datastore *sys_dstore = system_datastore(); if (!sys_dstore) { pomlog(POMLOG_ERR "No system datastore declared"); return POM_ERR; } // Find what is the id corresponding to the name given if any dsq_config_list = datastore_dataset_query_open(sys_dstore, REGISTRY_CONFIG_LIST, registry_config_list_dataset_template, NULL); 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; int res = datastore_dataset_read_single(dsq_config_list); if (res < 0) goto err; if (res == DATASET_QUERY_OK) { pomlog(POMLOG_ERR "Configuration \"%s\" not found in the database", config_name); goto err; } uint64_t config_id = dsq_config_list->data_id; datastore_dataset_query_cleanup(dsq_config_list); dsq_config_list = NULL; // Fetch the config dsq_config = datastore_dataset_query_open(sys_dstore, REGISTRY_CONFIG, registry_config_dataset_template, NULL); if (!dsq_config) goto err; if (datastore_dataset_query_set_uint64_condition(dsq_config, 0, PTYPE_OP_EQ, config_id) != POM_OK) goto err; // Fetch the config in a convenient way if (datastore_dataset_query_set_order(dsq_config, 3, DATASET_READ_ORDER_ASC) != POM_OK) goto err; registry_lock(); // Reset the registry if (registry_config_reset() != POM_OK) goto err_locked; while ((res = datastore_dataset_read(dsq_config)) != DATASET_QUERY_OK) { if (res < 0) goto err_locked; if (dsq_config->values[1].is_null || dsq_config->values[3].is_null) { pomlog(POMLOG_ERR "Got NULL values while they were not supposed to be !"); goto err_locked; } enum registry_config_entry_types type = *PTYPE_UINT8_GETVAL(dsq_config->values[3].value); char *entry = PTYPE_STRING_GETVAL(dsq_config->values[1].value); char *value = NULL; if (!dsq_config->values[2].is_null) value = PTYPE_STRING_GETVAL(dsq_config->values[2].value); // Parse the entry char *name1 = strdup(entry); if (!name1) { pom_oom(strlen(entry) + 1); goto err_locked; } char *name2 = strchr(name1, '.'); if (!name2) { pomlog(POMLOG_ERR "Unparseable entry name \"%s\"", entry); free(name1); goto err_locked; } *name2 = 0; name2++; char *name3 = strchr(name2, '.'); if (name3) { *name3 = 0; name3++; } switch (type) { case registry_config_instance: { if (!value) { pomlog(POMLOG_WARN "Instance type not provided for entry %s, skipping", entry); break; } struct registry_class *cls = registry_find_class(name1); if (!cls) { pomlog(POMLOG_WARN "Cannot add instance %s to class %s as this class doesn't exists. skipping", name2, name1); break; } struct registry_instance *inst; for (inst = cls->instances; inst && strcmp(inst->name, name2); inst = inst->next); if (inst) { pomlog(POMLOG_WARN "Cannot add instance %s as it's already in the registry, skipping", entry); break; } if (!cls->instance_add) { pomlog(POMLOG_WARN "Cannot add instances to class %s as it doesn't support it. skipping", name1); break; } if (cls->instance_add(value, name2) != POM_OK) { pomlog(POMLOG_WARN "Unable to add instance %s of type %s, skipping", entry, value); break; } break; } case registry_config_instance_param: { if (!value) { pomlog(POMLOG_WARN "Parameter value not provided for entry %s, skipping", entry); break; } if (!name3) { pomlog(POMLOG_WARN "Parameter name not provided for entry %s, skipping", entry); break; } struct registry_instance *inst = registry_find_instance(name1, name2); if (!inst) { pomlog(POMLOG_WARN "Cannot find instance %s.%s to set parameter, skipping", name1, name2); break; } if (!strcmp(name3, "uid")) { // Special handling for uids if (registry_uid_assign(inst, value) != POM_OK) { pomlog(POMLOG_WARN "Error while setting the uid, skipping"); break; } } else if (!strcmp(name3, "running")) { // For now don't do anything for running } else { registry_set_param(inst, name3, value); } break; } default: pomlog(POMLOG_WARN "Unhandled configuration entry type %u for item %s", entry); } free(name1); } registry_classes_serial_inc(); registry_unlock(); datastore_dataset_query_cleanup(dsq_config); pomlog("Registry configuration \"%s\" loaded", 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); return POM_ERR; }
int analyzer_eap_event_process_begin(struct event *evt, void *obj, struct proto_process_stack *stack, unsigned int stack_index) { struct analyzer *analyzer = obj; struct analyzer_eap_priv *apriv = analyzer->priv; struct proto_process_stack *s = &stack[stack_index]; if (!s->ce) return PROTO_ERR; conntrack_lock(s->ce); struct ptype *src = NULL, *dst = NULL; struct analyzer_eap_ce_priv *cpriv = conntrack_get_priv(s->ce, analyzer); if (!cpriv) { cpriv = malloc(sizeof(struct analyzer_eap_ce_priv)); if (!cpriv) { pom_oom(sizeof(struct analyzer_eap_ce_priv)); goto err; } memset(cpriv, 0, sizeof(struct analyzer_eap_ce_priv)); if (conntrack_add_priv(s->ce, analyzer, cpriv, analyzer_eap_ce_priv_cleanup) != POM_OK) { free(cpriv); goto err; } // Try to find the source and destination unsigned int i = 0; for (i = 1; i <= 4; i++) { struct proto_process_stack *prev_stack = &stack[stack_index - i]; if (!prev_stack->proto) break; struct proto_reg_info *info = proto_get_info(prev_stack->proto); if (!strcmp(info->name, "vlan")) { cpriv->vlan = ptype_alloc_from(prev_stack->pkt_info->fields_value[proto_vlan_field_vid]); if (!cpriv->vlan) return POM_ERR; } unsigned int j; for (j = 0; !src || !dst; j++) { struct proto_reg_info *prev_info = proto_get_info(prev_stack->proto); if (!prev_info->pkt_fields) break; char *name = prev_info->pkt_fields[j].name; if (!name) break; if (!src && !strcmp(name, "src")) src = prev_stack->pkt_info->fields_value[j]; else if (!dst && !strcmp(name, "dst")) dst = prev_stack->pkt_info->fields_value[j]; } if (src || dst) break; } struct proto_process_stack *prev_stack = &stack[stack_index - 2]; if (prev_stack->proto) { struct proto_reg_info *info = proto_get_info(prev_stack->proto); cpriv->top_proto = info->name; } } struct event_reg *evt_reg = event_get_reg(evt); struct data *evt_data = event_get_data(evt); int dir = POM_DIR_UNK; if (evt_reg == apriv->evt_md5_challenge) { uint8_t code = *PTYPE_UINT8_GETVAL(evt_data[evt_eap_common_code].value); if (code == 1) { if (!cpriv->evt_request) { event_refcount_inc(evt); cpriv->evt_request = evt; } dir = POM_DIR_REV; } else if (code == 2) { if (!cpriv->evt_response) { event_refcount_inc(evt); cpriv->evt_response = evt; } dir = POM_DIR_FWD; } } else { if (!cpriv->evt_result) { event_refcount_inc(evt); cpriv->evt_result = evt; } dir = POM_DIR_REV; } if (src && dst && dir != POM_DIR_UNK) { if (dir == POM_DIR_FWD) { cpriv->client = ptype_alloc_from(src); cpriv->server = ptype_alloc_from(dst); } else { cpriv->client = ptype_alloc_from(dst); cpriv->server = ptype_alloc_from(src); } } int res = POM_OK; if (cpriv->evt_request && cpriv->evt_response && cpriv->evt_result) res = analyzer_eap_finalize(apriv, cpriv); conntrack_unlock(s->ce); return res; err: conntrack_unlock(s->ce); return POM_ERR; }