void dns_tcp_init(void) { static struct proto_ops const ops = { .parse = dns_tcp_parse, .parser_new = uniq_parser_new, .parser_del = uniq_parser_del, }; uniq_proto_ctor(&uniq_proto_dns_tcp, &ops, "DNS/TCP", PROTO_CODE_DNSoTCP); port_muxer_ctor(&dns_tcp_port_muxer, &tcp_port_muxers, DNS_PORT, DNS_PORT, proto_dns_tcp); port_muxer_ctor(&mdns_tcp_port_muxer, &tcp_port_muxers, MDNS_PORT, MDNS_PORT, proto_dns_tcp); port_muxer_ctor(&nbns_tcp_port_muxer, &tcp_port_muxers, NBNS_PORT, NBNS_PORT, proto_dns_tcp); port_muxer_ctor(&llmnr_tcp_port_muxer, &tcp_port_muxers, LLMNR_PORT, LLMNR_PORT, proto_dns_tcp); }
void mgcp_init(void) { log_category_proto_mgcp_init(); static struct proto_ops const ops = { .parse = mgcp_parse, .parser_new = mgcp_parser_new, .parser_del = mgcp_parser_del, .info_2_str = mgcp_info_2_str, .info_addr = mgcp_info_addr }; proto_ctor(&proto_mgcp_, &ops, "MGCP", PROTO_CODE_MGCP); port_muxer_ctor(&udp_port_muxer_gw, &udp_port_muxers, 2427, 2427, proto_mgcp); port_muxer_ctor(&udp_port_muxer_agent, &udp_port_muxers, 2727, 2727, proto_mgcp); }
void rpc_init(void) { log_category_proto_rpc_init(); static struct proto_ops const ops = { .parse = rpc_parse, .parser_new = uniq_parser_new, .parser_del = uniq_parser_del, .info_2_str = rpc_info_2_str, .info_addr = rpc_info_addr, }; uniq_proto_ctor(&uniq_proto_rpc, &ops, "RPC", PROTO_CODE_RPC); port_muxer_ctor(&nfs_tcp_port_muxer, &tcp_port_muxers, 2049, 2049, proto_rpc); port_muxer_ctor(&nfs_udp_port_muxer, &udp_port_muxers, 2049, 2049, proto_rpc); port_muxer_ctor(&sun_rpc_tcp_port_muxer, &tcp_port_muxers, 111, 111, proto_rpc); port_muxer_ctor(&sun_rpc_udp_port_muxer, &udp_port_muxers, 111, 111, proto_rpc); }
void dns_tcp_init(void) { static struct proto_ops const ops = { .parse = dns_tcp_parse, .parser_new = uniq_parser_new, .parser_del = uniq_parser_del, }; uniq_proto_ctor(&uniq_proto_dns_tcp, &ops, "DNS/TCP"); port_muxer_ctor(&tcp_port_muxer, &tcp_port_muxers, 53, 53, proto_dns_tcp); }
void netbios_init(void) { log_category_proto_netbios_init(); static struct proto_ops const ops = { .parse = netbios_parse, .parser_new = netbios_parser_new, .parser_del = netbios_parser_del, .info_2_str = proto_info_2_str, .info_addr = netbios_info_addr, }; proto_ctor(proto_netbios, &ops, "Netbios", PROTO_CODE_NETBIOS); port_muxer_ctor(&tcp_port_muxer, &tcp_port_muxers, 445, 445, proto_netbios); }
void tns_init(void) { log_category_proto_tns_init(); static struct proto_ops const ops = { .parse = tns_parse, .parser_new = tns_parser_new, .parser_del = tns_parser_del, .info_2_str = sql_info_2_str, .info_addr = sql_info_addr }; proto_ctor(&proto_tns_, &ops, "TNS", PROTO_CODE_TNS); port_muxer_ctor(&tns_tcp_muxer, &tcp_port_muxers, 1521, 1521, proto_tns); }
void dhcp_init(void) { log_category_proto_dhcp_init(); static struct proto_ops const ops = { .parse = dhcp_parse, .parser_new = uniq_parser_new, .parser_del = uniq_parser_del, .info_2_str = dhcp_info_2_str, .info_addr = dhcp_info_addr }; uniq_proto_ctor(&uniq_proto_dhcp, &ops, "DHCP", PROTO_CODE_DHCP); port_muxer_ctor(&dhcp_port_muxer, &udp_port_muxers, BOOTPS_PORT, BOOTPS_PORT, proto_dhcp); }
void skinny_init(void) { log_category_proto_skinny_init(); static struct proto_ops const ops = { .parse = skinny_parse, .parser_new = skinny_parser_new, .parser_del = skinny_parser_del, .info_2_str = skinny_info_2_str, .info_addr = skinny_info_addr }; proto_ctor(&proto_skinny_, &ops, "SKINNY", PROTO_CODE_SKINNY); port_muxer_ctor(&tcp_port_muxer, &tcp_port_muxers, SKINNY_PORT, SKINNY_PORT, proto_skinny); }
void pgsql_init(void) { log_category_proto_pgsql_init(); static struct proto_ops const ops = { .parse = pg_parse, .parser_new = pg_parser_new, .parser_del = pg_parser_del, .info_2_str = sql_info_2_str, .info_addr = sql_info_addr }; proto_ctor(&proto_pgsql_, &ops, "PostgreSQL", PROTO_CODE_PGSQL); port_muxer_ctor(&pg_tcp_muxer, &tcp_port_muxers, 5432, 5432, proto_pgsql); }
static enum proto_parse_status tds_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) { if (cap_len == 0 && wire_len > 0) return PROTO_TOO_SHORT; // We do not know how to handle pure gaps struct tds_parser *tds_parser = DOWNCAST(parser, parser, tds_parser); SLOG(LOG_DEBUG, "Got tds packet, data_left %zu, way %d", tds_parser->data_left, way); bool has_gap = wire_len > cap_len; if (tds_parser->had_gap && tds_parser->data_left > 0) { tds_parser->data_left = wire_len > tds_parser->data_left ? 0 : tds_parser->data_left - wire_len; SLOG(LOG_DEBUG, "Discard tds with gap, data_left %zu...", tds_parser->data_left); timeval_reset(&tds_parser->first_ts); return PROTO_OK; } tds_parser->had_gap = has_gap; struct tds_header tds_header; bool unknown_token = false; struct cursor cursor; enum proto_parse_status status; cursor_ctor(&cursor, payload, cap_len); struct smp_header smp_header = {.length = 0}; if (PROTO_OK != (status = tds_parse_smp_header(&cursor, &smp_header))) return status; if (smp_header.length) { SLOG(LOG_DEBUG, "Smp header: %s", smp_header_2_str(&smp_header)); wire_len -= SMP_PKT_HDR_LEN; cap_len -= SMP_PKT_HDR_LEN; if (smp_header.flags & SMP_ACK) return PROTO_OK; } status = tds_parse_header(&cursor, &tds_header, &unknown_token); if (status != PROTO_OK) { // We have an unknown token if the payload is encrypted after a ssl handshake // It is valid but we don't know how to parse it yet // TODO It would be better if we knew the values of the encryption options exchanged in prelogin messages timeval_reset(&tds_parser->first_ts); if (unknown_token) return PROTO_OK; return status; } // Sanity check on pkt number if (tds_header.pkt_number > 1 && ((tds_parser->pkt_number + 1) != tds_header.pkt_number)) { SLOG(LOG_DEBUG, "Expected pkt number %"PRIu8", got %"PRIu8"", tds_parser->pkt_number + 1, tds_header.pkt_number); tds_parser->pkt_number = 1; timeval_reset(&tds_parser->first_ts); return PROTO_PARSE_ERR; } else if (tds_header.pkt_number <= 1) { SLOG(LOG_DEBUG, "Reset pkt number from %"PRIu8"", tds_parser->pkt_number); tds_parser->pkt_number = 1; } // Sanity check on channels if (tds_parser->channels[way] && (tds_parser->channels[way] != tds_header.channel)) { SLOG(LOG_DEBUG, "Expected channel %"PRIu16", got channel %"PRIu16"", tds_parser->channels[way], tds_header.channel); timeval_reset(&tds_parser->first_ts); return PROTO_PARSE_ERR; } if (wire_len > tds_header.len) { SLOG(LOG_DEBUG, "Wire len %zu unexpected (> %zu), considering a gap", wire_len, tds_header.len); has_gap = true; } tds_parser->data_left = wire_len >= tds_header.len ? 0 : tds_header.len - wire_len; SLOG(LOG_DEBUG, "Data left after wire %zu", tds_parser->data_left); if (tds_parser->data_left > 0 && !has_gap) { SLOG(LOG_DEBUG, "Incomplete tds packet, buffering it"); if (!timeval_is_set(&tds_parser->first_ts)) { SLOG(LOG_DEBUG, "Setting first ts to %s for way %d", timeval_2_str(now), way); tds_parser->first_ts = *now; } proto_parse(NULL, parent, way, NULL, 0, 0, now, tot_cap_len, tot_packet); streambuf_set_restart(&tds_parser->sbuf, way, payload, tds_header.len); return PROTO_OK; } // We have a buffered tds packet at this point if (!timeval_is_set(&tds_parser->first_ts)) { SLOG(LOG_DEBUG, "Setting first ts to %s for way %d since it is not setted", timeval_2_str(now), way); tds_parser->first_ts = *now; } struct tds_proto_info info; proto_info_ctor(&info.info, parser, parent, TDS_PKT_HDR_LEN, tds_header.len - TDS_PKT_HDR_LEN); info.type = tds_header.type; info.status = tds_header.status; info.length = tds_header.len; info.first_ts = tds_parser->first_ts; info.has_gap = has_gap; if (tds_header.channel > 0) { SLOG(LOG_DEBUG, "Saving channel %"PRIu16"", tds_header.channel); tds_parser->channels[way] = tds_header.channel; } SLOG(LOG_DEBUG, "Saving pkt number %"PRIu8"", tds_header.pkt_number); tds_parser->pkt_number = tds_header.pkt_number; SLOG(LOG_DEBUG, "Parsing %s", tds_header_2_str(&tds_header)); if (! tds_parser->msg_parser) { SLOG(LOG_DEBUG, "Building new tds_msg_parser"); tds_parser->msg_parser = proto_tds_msg->ops->parser_new(proto_tds_msg); if (!tds_parser->msg_parser) { SLOG(LOG_INFO, "Could not build tds msg parser"); return PROTO_PARSE_ERR; } } if (tds_header.status & TDS_EOM) { SLOG(LOG_DEBUG, "Reset pkt number from %"PRIu8" since we parsed an EOM", tds_parser->pkt_number); tds_parser->pkt_number = 1; } status = proto_parse(tds_parser->msg_parser, &info.info, way, cursor.head, cursor.cap_len, wire_len - TDS_PKT_HDR_LEN, now, tot_cap_len, tot_packet); if (status != PROTO_OK) { SLOG(LOG_INFO, "Tds msg parse failed, returning %s", proto_parse_status_2_str(status)); return status; } timeval_reset(&tds_parser->first_ts); // Advertise this packet if it was not done already return proto_parse(NULL, &info.info, way, payload, cap_len, wire_len, now, tot_cap_len, tot_packet); } static enum proto_parse_status tds_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 tds_parser *tds_parser = DOWNCAST(parser, parser, tds_parser); enum proto_parse_status const status = streambuf_add(&tds_parser->sbuf, parser, parent, way, payload, cap_len, wire_len, now, tot_cap_len, tot_packet); return status; } /* * Construction/Destruction */ static struct proto proto_tds_; struct proto *proto_tds = &proto_tds_; static struct port_muxer tds_tcp_muxer; void tds_init(void) { log_category_proto_tds_init(); static struct proto_ops const ops = { .parse = tds_parse, .parser_new = tds_parser_new, .parser_del = tds_parser_del, .info_2_str = tds_info_2_str, .info_addr = tds_info_addr }; proto_ctor(&proto_tds_, &ops, "TDS", PROTO_CODE_TDS); port_muxer_ctor(&tds_tcp_muxer, &tcp_port_muxers, 1433, 1433, proto_tds); }