void refresh_opt_template(void *hdr, struct template_cache_entry *tpl, struct packet_ptrs *pptrs, u_int16_t tpl_type, u_int32_t sid, u_int8_t version) { struct options_template_hdr_v9 *hdr_v9 = (struct options_template_hdr_v9 *) hdr; struct options_template_hdr_ipfix *hdr_v10 = (struct options_template_hdr_ipfix *) hdr; struct template_cache_entry *next; struct template_field_v9 *field; u_int16_t slen, olen, count, type, port, tid; u_char *ptr; /* NetFlow v9 */ if (tpl_type == 1) { tid = hdr_v9->template_id; slen = ntohs(hdr_v9->scope_len)/sizeof(struct template_field_v9); olen = ntohs(hdr_v9->option_len)/sizeof(struct template_field_v9); } /* IPFIX */ else if (tpl_type == 3) { tid = hdr_v10->template_id; slen = ntohs(hdr_v10->scope_count); olen = ntohs(hdr_v10->option_count)-slen; } next = tpl->next; memset(tpl, 0, sizeof(struct template_cache_entry)); sa_to_addr((struct sockaddr *)pptrs->f_agent, &tpl->agent, &port); tpl->source_id = sid; tpl->template_id = tid; tpl->template_type = 1; tpl->num = olen+slen; tpl->next = next; log_template_header(tpl, pptrs, tpl_type, sid, version); count = tpl->num; ptr = (u_char *) hdr; ptr += NfOptTplHdrV9Sz; field = (struct template_field_v9 *)ptr; while (count) { type = ntohs(field->type); log_opt_template_field(type, tpl->len, ntohs(field->len), version); if (type < NF9_MAX_DEFINED_FIELD) { tpl->tpl[type].off = tpl->len; tpl->tpl[type].len = ntohs(field->len); tpl->len += tpl->tpl[type].len; } else tpl->len += ntohs(field->len); count--; field++; } log_template_footer(tpl->len, version); }
struct template_cache_entry *insert_template(struct template_hdr_v9 *hdr, struct packet_ptrs *pptrs, u_int16_t tpl_type, u_int32_t sid, u_int16_t *pens, u_int8_t version) { struct template_cache_entry *ptr, *prevptr = NULL; struct template_field_v9 *field; u_int16_t modulo = (ntohs(hdr->template_id)%tpl_cache.num), count; u_int16_t num = ntohs(hdr->num), type, port; u_int32_t *pen; u_int8_t ipfix_ebit; u_char *tpl; ptr = tpl_cache.c[modulo]; while (ptr) { prevptr = ptr; ptr = ptr->next; } ptr = malloc(sizeof(struct template_cache_entry)); if (!ptr) { Log(LOG_ERR, "ERROR ( default/core ): Unable to allocate enough memory for a new Template Cache Entry.\n"); return NULL; } memset(ptr, 0, sizeof(struct template_cache_entry)); sa_to_addr((struct sockaddr *)pptrs->f_agent, &ptr->agent, &port); ptr->source_id = sid; ptr->template_id = hdr->template_id; ptr->template_type = 0; ptr->num = num; log_template_header(ptr, pptrs, tpl_type, sid, version); count = 0; tpl = (u_char *) hdr; tpl += NfTplHdrV9Sz; field = (struct template_field_v9 *)tpl; while (count < num) { pen = NULL; ipfix_ebit = FALSE; type = ntohs(field->type); if (type & IPFIX_TPL_EBIT && version == 10) { ipfix_ebit = TRUE; type ^= IPFIX_TPL_EBIT; if (pens) (*pens)++; pen = (u_int32_t *) field; pen++; } log_template_field(ptr->vlen, pen, type, ptr->len, ntohs(field->len), version); /* Let's determine if we use legacy template registry or the new template database (ie. if we have a PEN or high field value, >= 384) */ if (type < NF9_MAX_DEFINED_FIELD && !pen) { ptr->tpl[type].off = ptr->len; ptr->tpl[type].tpl_len = ntohs(field->len); if (ptr->vlen) ptr->tpl[type].off = 0; if (ptr->tpl[type].tpl_len == IPFIX_VARIABLE_LENGTH) { ptr->tpl[type].len = 0; ptr->vlen = TRUE; ptr->len = 0; } else { ptr->tpl[type].len = ptr->tpl[type].tpl_len; if (!ptr->vlen) ptr->len += ptr->tpl[type].len; } ptr->list[count].ptr = (char *) &ptr->tpl[type]; ptr->list[count].type = TPL_TYPE_LEGACY; } else { u_int16_t ie_idx, ext_db_modulo = (type%TPL_EXT_DB_ENTRIES); struct utpl_field *ext_db_ptr = NULL; for (ie_idx = 0; ie_idx < IES_PER_TPL_EXT_DB_ENTRY; ie_idx++) { if (ptr->ext_db[ext_db_modulo].ie[ie_idx].type == 0) { ext_db_ptr = &ptr->ext_db[ext_db_modulo].ie[ie_idx]; break; } } if (ext_db_ptr) { if (pen) ext_db_ptr->pen = ntohl(*pen); ext_db_ptr->type = type; ext_db_ptr->off = ptr->len; ext_db_ptr->tpl_len = ntohs(field->len); if (ptr->vlen) ext_db_ptr->off = 0; if (ext_db_ptr->tpl_len == IPFIX_VARIABLE_LENGTH) { ext_db_ptr->len = 0; ptr->vlen = TRUE; ptr->len = 0; } else { ext_db_ptr->len = ext_db_ptr->tpl_len; if (!ptr->vlen) ptr->len += ext_db_ptr->len; } } ptr->list[count].ptr = (char *) ext_db_ptr; ptr->list[count].type = TPL_TYPE_EXT_DB; } count++; if (ipfix_ebit) field++; /* skip 32-bits ahead */ field++; } if (prevptr) prevptr->next = ptr; else tpl_cache.c[modulo] = ptr; log_template_footer(ptr->len, version); return ptr; }
struct template_cache_entry *insert_opt_template(void *hdr, struct packet_ptrs *pptrs, u_int16_t tpl_type, u_int32_t sid, u_int8_t version) { struct options_template_hdr_v9 *hdr_v9 = (struct options_template_hdr_v9 *) hdr; struct options_template_hdr_ipfix *hdr_v10 = (struct options_template_hdr_ipfix *) hdr; struct template_cache_entry *ptr, *prevptr = NULL; struct template_field_v9 *field; u_int16_t modulo, count, slen, olen, type, port, tid; u_char *tpl; /* NetFlow v9 */ if (tpl_type == 1) { modulo = ntohs(hdr_v9->template_id)%tpl_cache.num; tid = hdr_v9->template_id; slen = ntohs(hdr_v9->scope_len)/sizeof(struct template_field_v9); olen = ntohs(hdr_v9->option_len)/sizeof(struct template_field_v9); } /* IPFIX */ else if (tpl_type == 3) { modulo = ntohs(hdr_v10->template_id)%tpl_cache.num; tid = hdr_v10->template_id; slen = ntohs(hdr_v10->scope_count); olen = ntohs(hdr_v10->option_count)-slen; } ptr = tpl_cache.c[modulo]; while (ptr) { prevptr = ptr; ptr = ptr->next; } ptr = malloc(sizeof(struct template_cache_entry)); if (!ptr) { Log(LOG_ERR, "ERROR ( default/core ): Unable to allocate enough memory for a new Options Template Cache Entry.\n"); return NULL; } memset(ptr, 0, sizeof(struct template_cache_entry)); sa_to_addr((struct sockaddr *)pptrs->f_agent, &ptr->agent, &port); ptr->source_id = sid; ptr->template_id = tid; ptr->template_type = 1; ptr->num = olen+slen; log_template_header(ptr, pptrs, tpl_type, sid, version); count = ptr->num; tpl = (u_char *) hdr; tpl += NfOptTplHdrV9Sz; field = (struct template_field_v9 *)tpl; while (count) { type = ntohs(field->type); log_opt_template_field(type, ptr->len, ntohs(field->len), version); if (type < NF9_MAX_DEFINED_FIELD) { ptr->tpl[type].off = ptr->len; ptr->tpl[type].len = ntohs(field->len); ptr->len += ptr->tpl[type].len; } else ptr->len += ntohs(field->len); count--; field++; } if (prevptr) prevptr->next = ptr; else tpl_cache.c[modulo] = ptr; log_template_footer(ptr->len, version); return ptr; }
void refresh_template(struct template_hdr_v9 *hdr, struct template_cache_entry *tpl, struct packet_ptrs *pptrs, u_int16_t tpl_type, u_int32_t sid, u_int16_t *pens, u_int8_t version) { struct template_cache_entry *next; struct template_field_v9 *field; u_int16_t count, num = ntohs(hdr->num), type, port; u_int32_t *pen; u_int8_t ipfix_ebit; u_char *ptr; next = tpl->next; memset(tpl, 0, sizeof(struct template_cache_entry)); sa_to_addr((struct sockaddr *)pptrs->f_agent, &tpl->agent, &port); tpl->source_id = sid; tpl->template_id = hdr->template_id; tpl->template_type = 0; tpl->num = num; tpl->next = next; log_template_header(tpl, pptrs, tpl_type, sid, version); count = 0; ptr = (u_char *) hdr; ptr += NfTplHdrV9Sz; field = (struct template_field_v9 *)ptr; while (count < num) { pen = NULL; ipfix_ebit = FALSE; type = ntohs(field->type); if (type & IPFIX_TPL_EBIT && version == 10) { ipfix_ebit = TRUE; type ^= IPFIX_TPL_EBIT; if (pens) (*pens)++; pen = (u_int32_t *) field; pen++; } log_template_field(tpl->vlen, pen, type, tpl->len, ntohs(field->len), version); if (type < NF9_MAX_DEFINED_FIELD && !pen) { tpl->tpl[type].off = tpl->len; tpl->tpl[type].tpl_len = ntohs(field->len); if (tpl->vlen) tpl->tpl[type].off = 0; if (tpl->tpl[type].tpl_len == IPFIX_VARIABLE_LENGTH) { tpl->tpl[type].len = 0; tpl->vlen = TRUE; tpl->len = 0; } else { tpl->tpl[type].len = tpl->tpl[type].tpl_len; if (!tpl->vlen) tpl->len += tpl->tpl[type].len; } tpl->list[count].ptr = (char *) &tpl->tpl[type]; tpl->list[count].type = TPL_TYPE_LEGACY; } else { u_int16_t ie_idx, ext_db_modulo = (type%TPL_EXT_DB_ENTRIES); struct utpl_field *ext_db_ptr = NULL; for (ie_idx = 0; ie_idx < IES_PER_TPL_EXT_DB_ENTRY; ie_idx++) { if (tpl->ext_db[ext_db_modulo].ie[ie_idx].type == 0) { ext_db_ptr = &tpl->ext_db[ext_db_modulo].ie[ie_idx]; break; } } if (ext_db_ptr) { if (pen) ext_db_ptr->pen = ntohl(*pen); ext_db_ptr->type = type; ext_db_ptr->off = tpl->len; ext_db_ptr->tpl_len = ntohs(field->len); if (tpl->vlen) ext_db_ptr->off = 0; if (ext_db_ptr->tpl_len == IPFIX_VARIABLE_LENGTH) { ext_db_ptr->len = 0; tpl->vlen = TRUE; tpl->len = 0; } else { ext_db_ptr->len = ext_db_ptr->tpl_len; if (!tpl->vlen) tpl->len += ext_db_ptr->len; } } tpl->list[count].ptr = (char *) ext_db_ptr; tpl->list[count].type = TPL_TYPE_EXT_DB; } count++; if (ipfix_ebit) field++; /* skip 32-bits ahead */ field++; } log_template_footer(tpl->len, version); }
struct template_cache_entry *insert_template(struct template_hdr_v9 *hdr, struct packet_ptrs *pptrs, u_int16_t tpl_type, u_int32_t sid, u_int16_t *pens, u_int8_t version, u_int16_t len) { struct template_cache_entry *ptr, *prevptr = NULL; struct template_field_v9 *field; u_int16_t modulo = (ntohs(hdr->template_id)%tpl_cache.num), count; u_int16_t num = ntohs(hdr->num), type, port, off; u_int32_t *pen; u_int8_t ipfix_ebit; u_char *tpl; ptr = tpl_cache.c[modulo]; while (ptr) { prevptr = ptr; ptr = ptr->next; } ptr = malloc(sizeof(struct template_cache_entry)); if (!ptr) { Log(LOG_ERR, "ERROR ( %s/core ): Unable to allocate enough memory for a new Template Cache Entry.\n", config.name); return NULL; } memset(ptr, 0, sizeof(struct template_cache_entry)); sa_to_addr((struct sockaddr *)pptrs->f_agent, &ptr->agent, &port); ptr->source_id = sid; ptr->template_id = hdr->template_id; ptr->template_type = 0; ptr->num = num; log_template_header(ptr, pptrs, tpl_type, sid, version); count = off = 0; tpl = (u_char *) hdr; tpl += NfTplHdrV9Sz; off += NfTplHdrV9Sz; field = (struct template_field_v9 *)tpl; while (count < num) { if (off >= len) { notify_malf_packet(LOG_INFO, "INFO: unable to read next Template Flowset (malformed template)", (struct sockaddr *) pptrs->f_agent); xflow_tot_bad_datagrams++; free(ptr); return NULL; } pen = NULL; ipfix_ebit = FALSE; type = ntohs(field->type); if (type & IPFIX_TPL_EBIT && version == 10) { ipfix_ebit = TRUE; type ^= IPFIX_TPL_EBIT; if (pens) (*pens)++; pen = (u_int32_t *) field; pen++; } log_template_field(ptr->vlen, pen, type, ptr->len, ntohs(field->len), version); /* Let's determine if we use legacy template registry or the new template database (ie. if we have a PEN or high field value, >= 384) */ if (type < NF9_MAX_DEFINED_FIELD && !pen) { ptr->tpl[type].off = ptr->len; ptr->tpl[type].tpl_len = ntohs(field->len); if (ptr->vlen) ptr->tpl[type].off = 0; if (ptr->tpl[type].tpl_len == IPFIX_VARIABLE_LENGTH) { ptr->tpl[type].len = 0; ptr->vlen = TRUE; ptr->len = 0; } else { ptr->tpl[type].len = ptr->tpl[type].tpl_len; if (!ptr->vlen) ptr->len += ptr->tpl[type].len; } ptr->list[count].ptr = (char *) &ptr->tpl[type]; ptr->list[count].type = TPL_TYPE_LEGACY; } else { struct utpl_field *ext_db_ptr = ext_db_get_next_ie(ptr, type); if (ext_db_ptr) { if (pen) ext_db_ptr->pen = ntohl(*pen); ext_db_ptr->type = type; ext_db_ptr->off = ptr->len; ext_db_ptr->tpl_len = ntohs(field->len); if (ptr->vlen) ext_db_ptr->off = 0; if (ext_db_ptr->tpl_len == IPFIX_VARIABLE_LENGTH) { ext_db_ptr->len = 0; ptr->vlen = TRUE; ptr->len = 0; } else { ext_db_ptr->len = ext_db_ptr->tpl_len; if (!ptr->vlen) ptr->len += ext_db_ptr->len; } } ptr->list[count].ptr = (char *) ext_db_ptr; ptr->list[count].type = TPL_TYPE_EXT_DB; } count++; off += NfTplFieldV9Sz; if (ipfix_ebit) { field++; /* skip 32-bits ahead */ off += sizeof(u_int32_t); } field++; } if (prevptr) prevptr->next = ptr; else tpl_cache.c[modulo] = ptr; log_template_footer(ptr->len, version); return ptr; }
struct template_cache_entry *refresh_opt_template(void *hdr, struct template_cache_entry *tpl, struct packet_ptrs *pptrs, u_int16_t tpl_type, u_int32_t sid, u_int8_t version, u_int16_t len) { struct options_template_hdr_v9 *hdr_v9 = (struct options_template_hdr_v9 *) hdr; struct options_template_hdr_ipfix *hdr_v10 = (struct options_template_hdr_ipfix *) hdr; struct template_cache_entry backup, *next; struct template_field_v9 *field; u_int16_t slen, olen, count, type, port, tid, off; u_char *ptr; /* NetFlow v9 */ if (tpl_type == 1) { tid = hdr_v9->template_id; slen = ntohs(hdr_v9->scope_len)/sizeof(struct template_field_v9); olen = ntohs(hdr_v9->option_len)/sizeof(struct template_field_v9); } /* IPFIX */ else if (tpl_type == 3) { tid = hdr_v10->template_id; slen = ntohs(hdr_v10->scope_count); olen = ntohs(hdr_v10->option_count)-slen; } next = tpl->next; memcpy(&backup, tpl, sizeof(struct template_cache_entry)); memset(tpl, 0, sizeof(struct template_cache_entry)); sa_to_addr((struct sockaddr *)pptrs->f_agent, &tpl->agent, &port); tpl->source_id = sid; tpl->template_id = tid; tpl->template_type = 1; tpl->num = olen+slen; tpl->next = next; log_template_header(tpl, pptrs, tpl_type, sid, version); off = 0; count = tpl->num; ptr = (u_char *) hdr; ptr += NfOptTplHdrV9Sz; off += NfOptTplHdrV9Sz; field = (struct template_field_v9 *)ptr; while (count) { if (off >= len) { notify_malf_packet(LOG_INFO, "INFO: unable to read next Options Template Flowset (malformed template)", (struct sockaddr *) pptrs->f_agent); xflow_tot_bad_datagrams++; memcpy(tpl, &backup, sizeof(struct template_cache_entry)); return NULL; } type = ntohs(field->type); log_opt_template_field(type, tpl->len, ntohs(field->len), version); if (type < NF9_MAX_DEFINED_FIELD) { tpl->tpl[type].off = tpl->len; tpl->tpl[type].len = ntohs(field->len); tpl->len += tpl->tpl[type].len; } else tpl->len += ntohs(field->len); count--; field++; off += NfTplFieldV9Sz; } log_template_footer(tpl->len, version); return tpl; }
struct template_cache_entry *refresh_template(struct template_hdr_v9 *hdr, struct template_cache_entry *tpl, struct packet_ptrs *pptrs, u_int16_t tpl_type, u_int32_t sid, u_int16_t *pens, u_int8_t version, u_int16_t len) { struct template_cache_entry backup, *next; struct template_field_v9 *field; u_int16_t count, num = ntohs(hdr->num), type, port, off; u_int32_t *pen; u_int8_t ipfix_ebit; u_char *ptr; next = tpl->next; memcpy(&backup, tpl, sizeof(struct template_cache_entry)); memset(tpl, 0, sizeof(struct template_cache_entry)); sa_to_addr((struct sockaddr *)pptrs->f_agent, &tpl->agent, &port); tpl->source_id = sid; tpl->template_id = hdr->template_id; tpl->template_type = 0; tpl->num = num; tpl->next = next; log_template_header(tpl, pptrs, tpl_type, sid, version); count = off = 0; ptr = (u_char *) hdr; ptr += NfTplHdrV9Sz; off += NfTplHdrV9Sz; field = (struct template_field_v9 *)ptr; while (count < num) { if (off >= len) { notify_malf_packet(LOG_INFO, "INFO: unable to read next Template Flowset (malformed template)", (struct sockaddr *) pptrs->f_agent); xflow_tot_bad_datagrams++; memcpy(tpl, &backup, sizeof(struct template_cache_entry)); return NULL; } pen = NULL; ipfix_ebit = FALSE; type = ntohs(field->type); if (type & IPFIX_TPL_EBIT && version == 10) { ipfix_ebit = TRUE; type ^= IPFIX_TPL_EBIT; if (pens) (*pens)++; pen = (u_int32_t *) field; pen++; } log_template_field(tpl->vlen, pen, type, tpl->len, ntohs(field->len), version); if (type < NF9_MAX_DEFINED_FIELD && !pen) { tpl->tpl[type].off = tpl->len; tpl->tpl[type].tpl_len = ntohs(field->len); if (tpl->vlen) tpl->tpl[type].off = 0; if (tpl->tpl[type].tpl_len == IPFIX_VARIABLE_LENGTH) { tpl->tpl[type].len = 0; tpl->vlen = TRUE; tpl->len = 0; } else { tpl->tpl[type].len = tpl->tpl[type].tpl_len; if (!tpl->vlen) tpl->len += tpl->tpl[type].len; } tpl->list[count].ptr = (char *) &tpl->tpl[type]; tpl->list[count].type = TPL_TYPE_LEGACY; } else { struct utpl_field *ext_db_ptr = ext_db_get_next_ie(tpl, type); if (ext_db_ptr) { if (pen) ext_db_ptr->pen = ntohl(*pen); ext_db_ptr->type = type; ext_db_ptr->off = tpl->len; ext_db_ptr->tpl_len = ntohs(field->len); if (tpl->vlen) ext_db_ptr->off = 0; if (ext_db_ptr->tpl_len == IPFIX_VARIABLE_LENGTH) { ext_db_ptr->len = 0; tpl->vlen = TRUE; tpl->len = 0; } else { ext_db_ptr->len = ext_db_ptr->tpl_len; if (!tpl->vlen) tpl->len += ext_db_ptr->len; } } tpl->list[count].ptr = (char *) ext_db_ptr; tpl->list[count].type = TPL_TYPE_EXT_DB; } count++; off += NfTplFieldV9Sz; if (ipfix_ebit) { field++; /* skip 32-bits ahead */ off += sizeof(u_int32_t); } field++; } log_template_footer(tpl->len, version); return tpl; }