static void __bro_val_free(BroVal *val) { D_ENTER; /* If there is no type in the val, then it's unassigned and * hence there won't be anything to clean up anyway. */ if (val->val_type) { switch (val->val_type->tag) { case BRO_TYPE_STRING: bro_string_cleanup(&val->val_str); break; default: /* Nothing to do */ break; } } __bro_sobject_release((BroSObject *) val->val_type); __bro_object_free((BroObject *) val); D_RETURN; }
static void __bro_mutable_val_free(BroMutableVal *mv) { D_ENTER; __bro_sobject_release((BroSObject *) mv->id); __bro_val_free((BroVal *) mv); D_RETURN; }
void __bro_id_free(BroID *id) { D_ENTER; if (!id) D_RETURN; /* First clean up our stuff */ bro_string_cleanup(&id->name); __bro_sobject_release((BroSObject *) id->type); __bro_sobject_release((BroSObject *) id->attrs); __bro_sobject_release((BroSObject *) id->val); /* Then clean up parent -- will eventually call free() */ __bro_object_free((BroObject *) id); D_RETURN; }
int __bro_vector_set_nth_val(BroVector *vec, int num, BroVal *v) { BroVal *val; if ( ! vec || num < 0 || num >= vec->length || ! v ) return FALSE; __bro_sobject_release((BroSObject*) vec->vector[num]); vec->vector[num] = v; return TRUE; }
void __bro_vector_free(BroVector *vec) { int i; if ( ! vec ) return; for ( i = 0; i < vec->length; ++i ) __bro_sobject_release((BroSObject*) vec->vector[i]); free(vec->vector); free(vec); }
static int io_process_serialization(BroConn *bc) { BroVal vbuf; D_ENTER; if (! __bro_buf_read_char(bc->rx_buf, &vbuf.val_char)) { D(("Couldn't read serialization type\n")); D_RETURN_(FALSE); } switch (vbuf.val_char) { case 'e': { BroEvent *ev; bc->rx_ev_start = (const char*) bro_buf_ptr_get(bc->rx_buf); D(("Processing serialized event.\n")); if (! (ev = __bro_event_unserialize(bc))) { bc->rx_ev_start = bc->rx_ev_end = NULL; D_RETURN_(FALSE); } bc->rx_ev_end = (const char*) bro_buf_ptr_get(bc->rx_buf); __bro_event_reg_dispatch(bc, ev); __bro_event_free(ev); bc->rx_ev_start = bc->rx_ev_end = NULL; } break; case 'i': { BroID *id; D(("Processing serialized ID.\n")); if (! (id = (BroID *) __bro_sobject_unserialize(SER_IS_ID, bc))) D_RETURN_(FALSE); D(("ID read successfully.\n")); /* Except we don't do anything with it yet. :) */ __bro_sobject_release((BroSObject *) id); } break; case 'p': { #ifdef BRO_PCAP_SUPPORT BroPacket *packet; if (! (packet = __bro_packet_unserialize(bc))) D_RETURN_(FALSE); D(("Packet read successfully.\n")); bro_packet_free(packet); #else D_RETURN_(FALSE); #endif } break; default: /* We do not handle anything else yet -- just say * we are happy and return. */ D(("Unknown serialization of type %c\n", vbuf.val_char)); D_RETURN_(FALSE); } /* After a complete unserialization, we enforce the size limit * of the cache. We can't do it on the go as a new object that * is unserialized may still contain references to previously * cached items which we might evict. */ while (__bro_ht_get_size(bc->io_cache) > bc->io_cache_maxsize) __bro_ht_evict_oldest(bc->io_cache); D_RETURN_(TRUE); }
int __bro_id_read(BroID *id, BroConn *bc) { char opt; D_ENTER; if (! id || ! bc) D_RETURN_(FALSE); if (! __bro_object_read((BroObject *) id, bc)) D_RETURN_(FALSE); if (! __bro_buf_read_string(bc->rx_buf, &id->name)) D_RETURN_(FALSE); if (! __bro_buf_read_char(bc->rx_buf, &id->scope)) D_RETURN_(FALSE); if (! __bro_buf_read_char(bc->rx_buf, &id->is_export)) D_RETURN_(FALSE); if (! __bro_buf_read_int(bc->rx_buf, &id->is_const)) D_RETURN_(FALSE); if (! __bro_buf_read_int(bc->rx_buf, &id->is_enum_const)) D_RETURN_(FALSE); if (! __bro_buf_read_int(bc->rx_buf, &id->is_type)) D_RETURN_(FALSE); if (! __bro_buf_read_int(bc->rx_buf, &id->offset)) D_RETURN_(FALSE); if (! __bro_buf_read_char(bc->rx_buf, &id->infer_return_type)) D_RETURN_(FALSE); if (! __bro_buf_read_char(bc->rx_buf, &id->weak_ref)) D_RETURN_(FALSE); if (id->type) __bro_sobject_release((BroSObject*) id->type); if (! (id->type = (BroType *) __bro_sobject_unserialize(SER_IS_TYPE, bc))) D_RETURN_(FALSE); if (! __bro_buf_read_char(bc->rx_buf, &opt)) D_RETURN_(FALSE); if (opt) { if (id->attrs) __bro_sobject_release((BroSObject *) id->attrs); if (! (id->attrs = (BroAttrs *) __bro_sobject_unserialize(SER_ATTRIBUTES, bc))) D_RETURN_(FALSE); } if (! __bro_buf_read_char(bc->rx_buf, &opt)) D_RETURN_(FALSE); if (opt) { if (id->val) __bro_sobject_release((BroSObject *) id->val); if (! (id->val = (BroVal *) __bro_sobject_unserialize(SER_IS_VAL, bc))) D_RETURN_(FALSE); } D_RETURN_(TRUE); }
static int __bro_val_read(BroVal *val, BroConn *bc) { char opt; uint32 tmp; int i; D_ENTER; if (! val || !bc) D_RETURN_(FALSE); if (! __bro_object_read((BroObject *) val, bc)) D_RETURN_(FALSE); /* Read type */ if (val->val_type) { __bro_sobject_release((BroSObject *) val->val_type); val->val_type = NULL; } if (! (val->val_type = (BroType *) __bro_sobject_unserialize(SER_IS_TYPE, bc))) D_RETURN_(FALSE); D(("Type in val has type tags %i/%i\n", val->val_type->tag, val->val_type->internal_tag)); /* Read optional Attributes */ if (val->val_attrs) { __bro_sobject_release((BroSObject *) val->val_attrs); val->val_attrs = NULL; } if (! __bro_buf_read_char(bc->rx_buf, &opt)) D_RETURN_(FALSE); if (opt) { if (! (val->val_attrs = (BroRecordVal *) __bro_sobject_unserialize(SER_RECORD_VAL, bc))) D_RETURN_(FALSE); } switch (val->val_type->internal_tag) { case BRO_INTTYPE_INT: case BRO_INTTYPE_UNSIGNED: /* Hack for ports */ if (val->val_type->tag == BRO_TYPE_PORT) { uint64 tmp; if (! __bro_buf_read_int64(bc->rx_buf, &tmp)) D_RETURN_(FALSE); if ( (tmp & 0xf0000) == 0x10000 ) val->val_port.port_proto = IPPROTO_TCP; else if ( (tmp & 0xf0000) == 0x20000 ) val->val_port.port_proto = IPPROTO_UDP; else if ( (tmp & 0xf0000) == 0x30000 ) val->val_port.port_proto = IPPROTO_ICMP; val->val_port.port_num = (tmp & 0xFFFF); } else { if (! __bro_buf_read_int64(bc->rx_buf, &val->val_int64)) D_RETURN_(FALSE); } break; case BRO_INTTYPE_DOUBLE: if (! __bro_buf_read_double(bc->rx_buf, &val->val_double)) D_RETURN_(FALSE); break; case BRO_INTTYPE_STRING: if (! __bro_buf_read_string(bc->rx_buf, &val->val_str)) D_RETURN_(FALSE); break; case BRO_INTTYPE_IPADDR: if (! __bro_buf_read_int(bc->rx_buf, &tmp)) D_RETURN_(FALSE); if (tmp != 1 && tmp != 4) { D(("Bad IP addresses word length: %d.\n", tmp)); D_RETURN_(FALSE); } if ( tmp == 1 ) { if (! __bro_buf_read_int(bc->rx_buf, &tmp)) D_RETURN_(FALSE); __bro_util_fill_v4_addr(&val->val_addr, ntohl(tmp)); } else { for ( i = 0; i < tmp; ++i ) { if (! __bro_buf_read_int(bc->rx_buf, &val->val_addr.addr[i])) D_RETURN_(FALSE); val->val_addr.addr[i] = ntohl(val->val_addr.addr[i]); } } break; case BRO_INTTYPE_SUBNET: if (! __bro_buf_read_int(bc->rx_buf, &tmp)) D_RETURN_(FALSE); if (tmp != 1 && tmp != 4) { D(("Bad IP addresses word length: %d.\n", tmp)); D_RETURN_(FALSE); } if ( tmp == 1 ) { if (! __bro_buf_read_int(bc->rx_buf, &tmp)) D_RETURN_(FALSE); __bro_util_fill_v4_addr(&val->val_subnet.sn_net, ntohl(tmp)); } else { for ( i = 0; i < tmp; ++i ) { if (! __bro_buf_read_int(bc->rx_buf, &val->val_subnet.sn_net.addr[i])) D_RETURN_(FALSE); val->val_subnet.sn_net.addr[i] = ntohl(val->val_subnet.sn_net.addr[i]); } } if (! __bro_buf_read_int(bc->rx_buf, &val->val_subnet.sn_width)) D_RETURN_(FALSE); break; case BRO_INTTYPE_OTHER: /* See Val.cc around 165 -- these are handled by derived classes. * We only make sure here it's not functions and not files. */ if (val->val_type->tag != BRO_TYPE_FUNC && val->val_type->tag != BRO_TYPE_FILE) break; /* Otherwise fall through to warning. */ default: D(("Unsupported internal type tag: %i\n", val->val_type->internal_tag)); D_RETURN_(FALSE); } D_RETURN_(TRUE); }
int __bro_val_assign(BroVal *val, const void *data) { D_ENTER; if (! val) { D(("Input error: (%p, %p)\n", val, data)); D_RETURN_(FALSE); } if (! data) { if (val->val_type) { __bro_sobject_release((BroSObject *) val->val_type); val->val_type = NULL; } D(("Marked val %p as unassigned.\n", val)); D_RETURN_(TRUE); } /* If we intend to assign data to the val, it must have a type. */ if (! val->val_type) { D(("Cannot assign to val without a type.\n")); D_RETURN_(FALSE); } switch (val->val_type->tag) { case BRO_TYPE_BOOL: { int tmp = *((int *) data); val->val.char_val = (tmp != 0 ? 1 : 0); } break; case BRO_TYPE_INT: case BRO_TYPE_COUNT: case BRO_TYPE_COUNTER: case BRO_TYPE_ENUM: val->val_int64 = *((uint64 *) data); break; case BRO_TYPE_DOUBLE: case BRO_TYPE_TIME: case BRO_TYPE_INTERVAL: val->val_double = *((double *) data); break; case BRO_TYPE_STRING: { BroString *str = (BroString *) data; bro_string_set_data(&val->val_str, str->str_val, str->str_len); } break; case BRO_TYPE_PORT: { BroPort *tmp = (BroPort *) data; if (tmp->port_proto != IPPROTO_TCP && tmp->port_proto != IPPROTO_UDP && tmp->port_proto != IPPROTO_ICMP) { __bro_sobject_release((BroSObject *) data); D_RETURN_(FALSE); } val->val_port = *tmp; } break; case BRO_TYPE_IPADDR: val->val_addr = *((BroAddr *) data); break; case BRO_TYPE_SUBNET: val->val_subnet = *((BroSubnet *) data); break; case BRO_TYPE_RECORD: { BroList *l; BroVal *tmp_val; BroRecordVal *rv = (BroRecordVal *) val; BroRecord *rec = (BroRecord *) data; if (rv->rec) __bro_record_free(rv->rec); rv->rec = __bro_record_copy(rec); /* Record vals also have a record type, copy that: */ for (l = rec->val_list; l; l = __bro_list_next(l)) { char *field; tmp_val = __bro_list_data(l); if (! tmp_val->val_type) { D(("Cannot create record type component from val without type.\n")); D_RETURN_(FALSE); } if (! (field = __bro_sobject_data_get((BroSObject *) tmp_val, "field"))) { D(("Val in record doesn't have field name associated with it.\n")); D_RETURN_(FALSE); } __bro_record_type_add_type((BroRecordType *) val->val_type, field, tmp_val->val_type);; } } break; case BRO_TYPE_TABLE: { BroTableVal *tv = (BroTableVal *) val; BroTable *table = (BroTable *) data; if (tv->table) __bro_table_free(tv->table); tv->table = __bro_table_copy(table); /* XXX need to create the appropriate content in (BroTableType*) val->val_type! */ } break; case BRO_TYPE_PATTERN: case BRO_TYPE_TIMER: case BRO_TYPE_ANY: case BRO_TYPE_UNION: case BRO_TYPE_LIST: case BRO_TYPE_FUNC: case BRO_TYPE_FILE: case BRO_TYPE_VECTOR: case BRO_TYPE_ERROR: D(("Type %i currently unsupported.\n", val->val_type->tag)); D_RETURN_(FALSE); default: D(("Unknown type identifier %i\n", val->val_type->tag)); D_RETURN_(FALSE); } D_RETURN_(TRUE); }
BroSObject * __bro_sobject_unserialize(uint16 type_id_wanted, BroConn *bc) { BroSObject *obj; char full_obj; uint32 perm_id; uint16 type_id; D_ENTER; if (! bc) D_RETURN_(NULL); /* Same special case for types as in __bro_sobject_serialize(). */ if ( (type_id_wanted & SER_TYPE_MASK) == SER_IS_TYPE) { D(("Unserializing a type, checking for name-only format.\n")); if (! __bro_buf_read_char(bc->rx_buf, &full_obj)) D_RETURN_(NULL); if (! full_obj) { BroString tmp; bro_string_init(&tmp); /* We only get the name. */ if (! __bro_buf_read_string(bc->rx_buf, &tmp)) D_RETURN_(FALSE); /* We don't really have a namespace in which we can now * look up the type, so there's not much we can do! */ D(("Received name-only type '%s', reporting failure.\n", bro_string_get_data(&tmp))); D_RETURN_(FALSE); } } if (! __bro_buf_read_char(bc->rx_buf, &full_obj)) D_RETURN_(NULL); if (! __bro_buf_read_int(bc->rx_buf, &perm_id)) D_RETURN_(NULL); if (! full_obj) { #ifdef BRO_DEBUG if (! (bc->conn_flags & BRO_CFLAG_CACHE)) D(("WARNING: no caching requested, yet peer sends cached data.\n")); #endif if (! (obj = __bro_ht_get(bc->io_cache, (void *) perm_id))) { D(("Cache inconsistency: cache should contain object %i\n", perm_id)); D_RETURN_(NULL); } __bro_sobject_ref(obj); D(("Returning object %i/%p from cache.\n", perm_id, obj)); D_RETURN_(obj); } if (! __bro_buf_read_short(bc->rx_buf, &type_id)) D_RETURN_(NULL); /* Now check if the stuff that's arriving is actually an * instance of the type we'd like to see -- we can only do * primitive checking for inherited types (when we want to * know that it's a type, say, but we cannot know what exact * kind of type) -- so we just check whether all the bits set * in both type id's match: */ if ((type_id_wanted & SER_TYPE_MASK) != (type_id & SER_TYPE_MASK)) { D(("Type mismatch in serialization: wanted %04x, got %04x.\n", type_id_wanted, type_id)); D_RETURN_(NULL); } if (! (obj = __bro_sobject_create(type_id))) D_RETURN_(NULL); /* Polymorphism: depending on the constructor of the object, * this call will start from the bottom of the hierarchy and * read members in step by step, so by the time we return * from this function the object is fully unserialized. */ if (! obj->read(obj, bc)) { D(("Reading object %i of type 0x%04x FAILED.\n", perm_id, type_id)); __bro_sobject_release(obj); D_RETURN_(NULL); } /* If we have asked the peer to use caching, * make sure the object is in the cache: */ if ( (bc->conn_flags & BRO_CFLAG_CACHE) && ! __bro_ht_get(bc->io_cache, (void *) perm_id)) { D(("Storing object %i in cache.\n", perm_id)); __bro_ht_add(bc->io_cache, (void *) perm_id, obj); obj->perm_id = perm_id; __bro_sobject_ref(obj); } D(("Object %i of type 0x%04x unserialized successfully.\n", perm_id, type_id)); D_RETURN_(obj); }