Ejemplo n.º 1
0
static enum proto_parse_status tns_sbuf_parse(struct parser *parser, struct proto_info *parent, unsigned way, uint8_t const *payload, size_t cap_len, size_t wire_len, struct timeval const *now, size_t tot_cap_len, uint8_t const *tot_packet)
{
    struct tns_parser *tns_parser = DOWNCAST(parser, parser, tns_parser);

    // If this is the first time we are called, init c2s_way
    if (tns_parser->c2s_way == UNSET) {
        ASSIGN_INFO_OPT(tcp, parent);
        if (tcp) tns_parser->c2s_way = tcp->to_srv ? way : !way;
        else tns_parser->c2s_way = way;
        SLOG(LOG_DEBUG, "First packet, init c2s_way to %u", tns_parser->c2s_way);
    }

    if (!timeval_is_set(&tns_parser->first_ts)) {
        SLOG(LOG_DEBUG, "Setting first ts to %s", timeval_2_str(now));
        tns_parser->first_ts = *now;
    }

    // Now build the proto_info
    struct sql_proto_info info;
    SLOG(LOG_DEBUG, "Constructing with %zu", wire_len);
    proto_info_ctor(&info.info, parser, parent, wire_len, 0);
    info.is_query = way == tns_parser->c2s_way;
    info.set_values = 0;
    info.msg_type = SQL_UNKNOWN;
    info.first_ts = tns_parser->first_ts;

    // and try to read a TNS PDN
    struct cursor cursor;
    cursor_ctor(&cursor, payload, cap_len);

    uint8_t const *const msg_start = cursor.head;
    size_t pdu_len = 0;
    enum tns_type pdu_type = 0;
    enum proto_parse_status status = cursor_read_tns_hdr(&cursor, &pdu_len, &pdu_type, wire_len);
    if (status == PROTO_PARSE_ERR) {
        SLOG(LOG_DEBUG, "Error while parsing tns header");
        timeval_reset(&tns_parser->first_ts);
        return status;
    }

    bool has_gap = cap_len < wire_len;
    if (status == PROTO_TOO_SHORT && !has_gap) {
        proto_parse(NULL, parent, way, NULL, 0, 0, now, tot_cap_len, tot_packet);
        streambuf_set_restart(&tns_parser->sbuf, way, msg_start, pdu_len > 0 ? pdu_len : 8);
        SLOG(LOG_DEBUG, "Payload too short for parsing message, will restart @ %zu", tns_parser->sbuf.dir->restart_offset);
        return PROTO_OK;
    }
    switch (pdu_type) {
        case TNS_CONNECT:
            info.msg_type = SQL_STARTUP;
            status = tns_parse_connect(tns_parser, &info, &cursor);
            break;
        case TNS_ACCEPT:
            info.msg_type = SQL_STARTUP;
            status = tns_parse_accept(tns_parser, &info, &cursor);
            break;
        case TNS_DATA:
            status = tns_parse_data(tns_parser, &info, &cursor, way);
            break;
        case TNS_RESEND:
            SLOG(LOG_DEBUG, "Got a tns resend");
            break;
        case TNS_REFUSE:
        case TNS_REDIRECT:
        case TNS_ABORT:
        case TNS_MARKER:
        case TNS_ATTENTION:
        case TNS_CONTROL:
        default:    // A type we do not handle, skip the PDU
            break;
    }

    // We advertize the tns pdu even if we don't know how to parse it
    if (status != PROTO_OK) SLOG(LOG_DEBUG, "Error parsing tns packet");
    timeval_reset(&tns_parser->first_ts);
    return proto_parse(NULL, &info.info, way, NULL, 0, 0, now, tot_cap_len, tot_packet);
}
Ejemplo n.º 2
0
static enum proto_parse_status tns_sbuf_parse(struct parser *parser, struct proto_info *parent, unsigned way, uint8_t const *payload, size_t cap_len, size_t wire_len, struct timeval const *now, size_t tot_cap_len, uint8_t const *tot_packet)
{
    struct tns_parser *tns_parser = DOWNCAST(parser, parser, tns_parser);

    // If this is the first time we are called, init c2s_way
    if (tns_parser->c2s_way == UNSET) {
        tns_parser->c2s_way = way;
        SLOG(LOG_DEBUG, "First packet, init c2s_way to %u", tns_parser->c2s_way);
    }

    // Now build the proto_info
    struct sql_proto_info info;
    proto_info_ctor(&info.info, parser, parent, wire_len, 0);
    info.is_query = way == tns_parser->c2s_way;
    info.set_values = 0;
    info.msg_type = SQL_UNKNOWN;

    // and try to read a TNS PDN
    struct cursor cursor;
    cursor_ctor(&cursor, payload, cap_len);

    uint8_t const *const msg_start = cursor.head;
    size_t pdu_len;
    enum tns_type pdu_type;
    enum proto_parse_status status = cursor_read_tns_hdr(&cursor, &pdu_len, &pdu_type);
    if (status == PROTO_PARSE_ERR) return status;
    if (status == PROTO_TOO_SHORT) {
        streambuf_set_restart(&tns_parser->sbuf, way, msg_start, true);
        SLOG(LOG_DEBUG, "Payload too short for parsing message, will restart @ %zu", tns_parser->sbuf.dir->restart_offset);
        return PROTO_OK;
    }
    assert(cursor.cap_len >= pdu_len);  // We have the whole msg ready to be read
    struct cursor msg;
    cursor_ctor(&msg, cursor.head, pdu_len);
    switch (pdu_type) {
        case TNS_CONNECT:
            info.msg_type = SQL_STARTUP;
            status = tns_parse_connect(tns_parser, &info, &msg);
            break;
        case TNS_ACCEPT:
            info.msg_type = SQL_STARTUP;
            status = tns_parse_accept(tns_parser, &info, &msg);
            break;
        case TNS_DATA:
            status = tns_parse_data(tns_parser, &info, &msg, way);
            break;
        case TNS_RESEND:
            SLOG(LOG_DEBUG, "Got a tns resend");
            break;
        case TNS_REFUSE:
        case TNS_REDIRECT:
        case TNS_ABORT:
        case TNS_MARKER:
        case TNS_ATTENTION:
        case TNS_CONTROL:
        default:    // A type we do not handle, skip the PDU
            break;
    }

    // We advertize the tns pdu even if we don't know how to parse it
    if (status != PROTO_OK) SLOG(LOG_DEBUG, "Error parsing tns packet");
    return proto_parse(NULL, &info.info, way, NULL, 0, 0, now, tot_cap_len, tot_packet);
}