int __bro_id_write(BroID *id, BroConn *bc) { D_ENTER; if (! id || ! bc) D_RETURN_(FALSE); if (! __bro_object_write((BroObject *) id, bc)) D_RETURN_(FALSE); if (! __bro_buf_write_string(bc->tx_buf, &id->name)) D_RETURN_(FALSE); if (! __bro_buf_write_char(bc->tx_buf, id->scope)) D_RETURN_(FALSE); if (! __bro_buf_write_char(bc->tx_buf, id->is_export)) D_RETURN_(FALSE); if (! __bro_buf_write_int(bc->tx_buf, id->is_const)) D_RETURN_(FALSE); if (! __bro_buf_write_int(bc->tx_buf, id->is_enum_const)) D_RETURN_(FALSE); if (! __bro_buf_write_int(bc->tx_buf, id->is_type)) D_RETURN_(FALSE); if (! __bro_buf_write_int(bc->tx_buf, id->offset)) D_RETURN_(FALSE); if (! __bro_buf_write_char(bc->tx_buf, id->infer_return_type)) D_RETURN_(FALSE); if (! __bro_buf_write_char(bc->tx_buf, id->weak_ref)) D_RETURN_(FALSE); if (! __bro_sobject_serialize((BroSObject *) id->type, bc)) D_RETURN_(FALSE); if (! __bro_buf_write_char(bc->tx_buf, id->attrs ? 1 : 0)) D_RETURN_(FALSE); if (id->attrs && ! __bro_sobject_serialize((BroSObject *) id->attrs, bc)) D_RETURN_(FALSE); if (! __bro_buf_write_char(bc->tx_buf, id->val ? 1 : 0)) D_RETURN_(FALSE); if (id->attrs && ! __bro_sobject_serialize((BroSObject *) id->val, bc)) D_RETURN_(FALSE); D_RETURN_(TRUE); }
static int __bro_list_val_write(BroListVal *lv, BroConn *bc) { BroList *l; D_ENTER; if (! __bro_val_write((BroVal *) lv, bc)) D_RETURN_(FALSE); if (! __bro_buf_write_char(bc->tx_buf, lv->type_tag)) D_RETURN_(FALSE); if (! __bro_buf_write_int(bc->tx_buf, lv->len)) D_RETURN_(FALSE); for (l = lv->list; l; l = __bro_list_next(l)) { BroVal *val = __bro_list_data(l); if (! __bro_sobject_serialize((BroSObject *) val, bc)) D_RETURN_(FALSE); } D_RETURN_(TRUE); }
int __bro_sobject_serialize(BroSObject *obj, BroConn *bc) { char full_obj; D_ENTER; if (! obj || !bc) D_RETURN_(FALSE); /* Special case for types: they indicate at the very beginning * whether they're transferred in their entirety or just via * their name (in which case we can't do much at the moment). */ if ( (obj->type_id & SER_TYPE_MASK) == SER_IS_TYPE) { BroType *type = (BroType *) obj; D(("Serializing type %X as type\n", obj->type_id)); if (! __bro_buf_write_char(bc->tx_buf, type->is_complete)) D_RETURN_(FALSE); if (! type->is_complete) { if (! __bro_buf_write_string(bc->tx_buf, &type->type_name)) D_RETURN_(FALSE); D(("Type sent by type-name '%s' only.\n", bro_string_get_data(&type->type_name))); D_RETURN_(TRUE); } } /* FIXME: for now we never use the serialization cache when sending. */ full_obj = 1; if (! __bro_buf_write_char(bc->tx_buf, full_obj)) D_RETURN_(FALSE); if (! __bro_buf_write_int(bc->tx_buf, obj->perm_id)) D_RETURN_(FALSE); if (! obj->write(obj, bc)) D_RETURN_(FALSE); D_RETURN_(TRUE); }
static int __bro_record_val_write(BroRecordVal *rv, BroConn *bc) { BroList *l; BroVal *val; int i; D_ENTER; if (! __bro_mutable_val_write((BroMutableVal *) rv, bc)) D_RETURN_(FALSE); if (! __bro_buf_write_int(bc->tx_buf, rv->rec->val_len)) D_RETURN_(FALSE); if (! rv->rec && rv->rec->val_len > 0) D_RETURN_(FALSE); D(("Writing out %i vals in record %p.\n", rv->rec->val_len, rv->rec)); for (i = 0, l = rv->rec->val_list; l; i++, l = __bro_list_next(l)) { val = __bro_list_data(l); D(("Val %i/%p's type: %p\n", i, val, val->val_type)); if (! __bro_buf_write_char(bc->tx_buf, (val->val_type ? 1 :0))) D_RETURN_(FALSE); if (val->val_type) { if (! __bro_sobject_serialize((BroSObject *) val, bc)) D_RETURN_(FALSE); } } D_RETURN_(TRUE); }
static int io_msg_fill_tx(BroConn *bc, BroMsg *msg) { int result = TRUE; D_ENTER; if (!bc || !msg) { D(("Input error.\n")); D_RETURN_(FALSE); } /* Check if anything is still left in the input buffer. In that case, * we don't fill anything in but return right away, so the message * gets queued. */ if (__bro_buf_get_used_size(bc->tx_buf) > 0) { D(("Buffer not empty; not filling!\n")); D_RETURN_(FALSE); } D((">>> Attempting write of %s\n", msg_type_2_str(msg->msg_header.hdr_type))); /* We will collect the message chunk in the connection's tx buffer. * We append stuff to it as we go along and at the end write it out. * When being sent, he buffer has the amount of octets to send at * the beginning, so the reader knows how much is coming. */ __bro_buf_reset(bc->tx_buf); msg->msg_header_size = sizeof(BroMsgHeader); if (! __bro_buf_write_int(bc->tx_buf, msg->msg_header_size)) { __bro_buf_reset(bc->tx_buf); D_RETURN_(FALSE); } /* Hook in the Bro message header */ if (! io_fill_msg_header(bc->tx_buf, &msg->msg_header)) { __bro_buf_reset(bc->tx_buf); D_RETURN_(FALSE); } if (msg->msg_cont_type != BRO_MSG_CONT_NONE) { uint32 msg_size_pos, msg_size_end; /* This starts another chunk of data (in Bro protocol speak), * but here we cannot yet know how big the chunk will be. * We save the offset in the buffer and return to it later, * overwriting the value with the then correct one. */ msg_size_pos = __bro_buf_get_used_size(bc->tx_buf); if (! __bro_buf_write_int(bc->tx_buf, msg->msg_size)) { __bro_buf_reset(bc->tx_buf); D_RETURN_(FALSE); } /* Gather the payload of the message we are about * to send into the buffer BUF. */ switch (msg->msg_cont_type) { case BRO_MSG_CONT_RAW: D(("Filling raw data into buffer\n")); if (! io_fill_raw(bc->tx_buf, msg->msg_cont_raw)) { __bro_buf_reset(bc->tx_buf); D_RETURN_(FALSE); } break; case BRO_MSG_CONT_EVENT: /* Check if the peer actually requested the event, and if not, * drop it silently (i.e., still return success). */ if (! __bro_ht_get(bc->ev_mask, msg->msg_cont_ev->name.str_val)) { D(("Event '%s' not requested by peer -- dropping.\n", msg->msg_cont_ev->name.str_val)); __bro_buf_reset(bc->tx_buf); /* This is not an error but a silent drop, so we * return success. */ D_RETURN_(TRUE); } D(("Filling event into buffer\n")); if (! __bro_event_serialize(msg->msg_cont_ev, bc)) { D(("Error during serialization.\n")); __bro_buf_reset(bc->tx_buf); D_RETURN_(FALSE); } break; case BRO_MSG_CONT_REQUEST: D(("Filling request into buffer\n")); if (! io_fill_request(bc->tx_buf, msg->msg_cont_req)) { __bro_buf_reset(bc->tx_buf); D_RETURN_(FALSE); } break; #ifdef BRO_PCAP_SUPPORT case BRO_MSG_CONT_PACKET: if (! __bro_packet_serialize(msg->msg_cont_packet, bc)) { __bro_buf_reset(bc->tx_buf); D_RETURN_(FALSE); } break; #endif default: D(("ERROR -- invalid message content code %i\n", msg->msg_cont_type)); break; } /* Now calculate length of entire transmission -- * we know where we wrote the uint32 containing the * size of the chunk, and we know where we are now, * so the length is their difference, minus the uint32 * itself. */ msg_size_end = __bro_buf_get_used_size(bc->tx_buf); msg->msg_size = msg_size_end - msg_size_pos - sizeof(uint32); D(("Serialized message sized %i bytes.\n", msg->msg_size)); if (! __bro_buf_ptr_seek(bc->tx_buf, msg_size_pos, SEEK_SET)) { D(("Cannot seek to position %u -- we're screwed.\n", msg_size_pos)); __bro_buf_reset(bc->tx_buf); D_RETURN_(FALSE); } if (! __bro_buf_write_int(bc->tx_buf, msg->msg_size)) { __bro_buf_reset(bc->tx_buf); D_RETURN_(FALSE); } } D_RETURN_(result); }
static int __bro_val_write(BroVal *val, BroConn *bc) { BroType *type; BroSObject *obj; int i; D_ENTER; if (! val || !bc) D_RETURN_(FALSE); /* We need to make sure that the BroSObject at the root has the * correct type_id (a SER_xxx value). This depends on the type object * so map the type tag of that object to a SER_xxx value: */ if (! val->val_type) { D(("Val %p doesn't have a type.\n", val)); D_RETURN_(FALSE); } type = (BroType *) val->val_type; obj = (BroSObject *) val; switch (type->tag) { case BRO_TYPE_BOOL: case BRO_TYPE_INT: case BRO_TYPE_COUNT: case BRO_TYPE_COUNTER: case BRO_TYPE_STRING: case BRO_TYPE_DOUBLE: case BRO_TYPE_TIME: obj->type_id = SER_VAL; break; case BRO_TYPE_ENUM: obj->type_id = SER_ENUM_VAL; break; case BRO_TYPE_PORT: obj->type_id = SER_PORT_VAL; break; case BRO_TYPE_INTERVAL: obj->type_id = SER_INTERVAL_VAL; break; case BRO_TYPE_IPADDR: obj->type_id = SER_ADDR_VAL; break; case BRO_TYPE_SUBNET: obj->type_id = SER_SUBNET_VAL; break; case BRO_TYPE_RECORD: obj->type_id = SER_RECORD_VAL; break; default: D(("Val %p's type unhandled: type tag is %i.\n", val, type->tag)); D_RETURN_(FALSE); } if (! __bro_object_write((BroObject *) val, bc)) D_RETURN_(FALSE); if (! __bro_sobject_serialize((BroSObject *) val->val_type, bc)) D_RETURN_(FALSE); if (! __bro_buf_write_char(bc->tx_buf, val->val_attrs ? 1 : 0)) D_RETURN_(FALSE); if (val->val_attrs && ! __bro_sobject_serialize((BroSObject *) val->val_attrs, 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 = val->val_port.port_num; if (val->val_port.port_proto == IPPROTO_TCP) tmp |= 0x10000; else if (val->val_port.port_proto == IPPROTO_UDP) tmp |= 0x20000; else if (val->val_port.port_proto == IPPROTO_ICMP) tmp |= 0x30000; if (! __bro_buf_write_int64(bc->tx_buf, tmp)) D_RETURN_(FALSE); } else { if (! __bro_buf_write_int64(bc->tx_buf, val->val_int64)) D_RETURN_(FALSE); } break; case BRO_INTTYPE_DOUBLE: if (! __bro_buf_write_double(bc->tx_buf, val->val_double)) D_RETURN_(FALSE); break; case BRO_INTTYPE_STRING: if (! __bro_buf_write_string(bc->tx_buf, &val->val_str)) D_RETURN_(FALSE); break; case BRO_INTTYPE_IPADDR: if ( __bro_util_is_v4_addr(&val->val_addr) ) i = 1; else i = 4; if (! __bro_buf_write_int(bc->tx_buf, i)) D_RETURN_(FALSE); for ( i = 4 - i; i < 4; ++i ) if (! __bro_buf_write_int(bc->tx_buf, htonl(val->val_addr.addr[i]))) D_RETURN_(FALSE); break; case BRO_INTTYPE_SUBNET: if ( __bro_util_is_v4_addr(&val->val_subnet.sn_net) ) i = 1; else i = 4; if (! __bro_buf_write_int(bc->tx_buf, i)) D_RETURN_(FALSE); for ( i = 4 - i; i < 4; ++i ) if (! __bro_buf_write_int(bc->tx_buf, htonl(val->val_subnet.sn_net.addr[i]))) D_RETURN_(FALSE); if (! __bro_buf_write_int(bc->tx_buf, val->val_subnet.sn_width)) D_RETURN_(FALSE); break; case BRO_INTTYPE_OTHER: /* That's fine, will be handled in derived classes * like __bro_record_val_write(). */ break; default: D(("Unknown internal type tag: %i\n", val->val_type->internal_tag)); D_RETURN_(FALSE); } D_RETURN_(TRUE); }