示例#1
0
文件: sdp.c 项目: krissg/junkie
static enum proto_parse_status sdp_parse(struct parser *parser, struct proto_layer *parent, unsigned way, uint8_t const *packet, size_t cap_len, size_t wire_len, struct timeval const *now, proto_okfn_t *okfn)
{
    struct sdp_parser *sdp_parser = DOWNCAST(parser, parser, sdp_parser);

    static struct sdper_field const fields[] = {
        { 1, "c", sdp_extract_host },
        { 1, "m", sdp_extract_port },
    };

    static struct sdper const sdper = {
        .nb_fields = NB_ELEMS(fields),
        .fields = fields
    };

    SLOG(LOG_DEBUG, "Starting SDP analysis");

    /* Parse */

    struct sdp_proto_info info;
    sdp_proto_info_ctor(&info, wire_len, 0);
    struct proto_layer layer;
    proto_layer_ctor(&layer, parent, parser, &info.info);

    if (0 != sdper_parse(&sdper, &cap_len, packet, cap_len, &info)) return PROTO_PARSE_ERR;

    if (
        (info.set_values & SDP_PORT_SET) &&
        (info.set_values & SDP_HOST_SET)
    ) {
        SLOG(LOG_DEBUG, "SDP@%p, connect info is %s:%"PRIu16, sdp_parser, ip_addr_2_str(&info.host), info.port);

        if (! sdp_parser->host_set) {
            sdp_parser->host_set = true;
            sdp_parser->host = info.host;
            sdp_parser->port = info.port;
            ASSIGN_LAYER_AND_INFO_OPT(ip, parent);
            if (layer_ip) {
                sdp_parser->sender = ip->key.addr[0];
                sdp_parser->sender_set = true;
            } else {
                sdp_parser->sender_set = false;
            }
        } else if (0 != ip_addr_cmp(&sdp_parser->host, &info.host)) {
            // Start conntracking between the advertized hosts
            spawn_subparsers(&sdp_parser->host, sdp_parser->port, &info.host, info.port, parent, now);

            ASSIGN_LAYER_AND_INFO_OPT(ip, parent);
            bool may_use_stun[2] = {
                0 != ip_addr_cmp(&sdp_parser->sender, &sdp_parser->host),
                ip && 0 != ip_addr_cmp(&ip->key.addr[0], &info.host),
            };
            // If the sender IP was different from the advertized host, start conntracking on this socket also
            if (may_use_stun[0]) {
                spawn_subparsers(&sdp_parser->sender, sdp_parser->port, &info.host, info.port, parent, now);
            }
            // If _this_ sender IP is different from this advertized host, start conntracking on this socket as well
            if (may_use_stun[1]) {
                spawn_subparsers(&sdp_parser->host, sdp_parser->port, &ip->key.addr[0], info.port, parent, now);
            }
            // If both senders IP were different from advertized ones then start conntracking between these two senders IP as well
            if (may_use_stun[0] && may_use_stun[1]) {
                spawn_subparsers(&sdp_parser->sender, sdp_parser->port, &ip->key.addr[0], info.port, parent, now);
            }

            // TODO: terminate this parser. meanwhile, reset its state :
            sdp_parser->host_set = false;
            sdp_parser->sender_set = false;
        }
    }

    return proto_parse(NULL, &layer, way, NULL, 0, 0, now, okfn);
}
示例#2
0
static enum proto_parse_status sdp_parse(struct parser *parser, struct proto_info *parent, unsigned way, uint8_t const *packet, size_t cap_len, size_t wire_len, struct timeval const *now, size_t tot_cap_len, uint8_t const *tot_packet)
{
    struct sdp_parser *sdp_parser = DOWNCAST(parser, parser, sdp_parser);

    static struct sdper_field const fields[] = {
        { 1, "c", sdp_extract_host },
        { 1, "m", sdp_extract_port },
    };

    static struct sdper const sdper = {
        .nb_fields = NB_ELEMS(fields),
        .fields = fields
    };

    SLOG(LOG_DEBUG, "Starting SDP analysis");

    /* Parse */

    struct sdp_proto_info info;
    sdp_proto_info_ctor(&info, parser, parent, wire_len, 0);

    if (0 != sdper_parse(&sdper, &cap_len, packet, cap_len, &info)) return PROTO_PARSE_ERR;

    // Start conntracking of RT(C)P streams if we have all required informations
    if (
        (info.set_values & SDP_PORT_SET) &&
        (info.set_values & SDP_HOST_SET)
    ) {
        SLOG(LOG_DEBUG, "SDP@%p, connect info is %s:%"PRIu16, sdp_parser, ip_addr_2_str(&info.host), info.port);

        /* FIXME: store both peers of the SDP tunnel and respawn the RT(C)Ps as soon as
         * one of the end changes. Problem is: we don't know which peer this is! */
        if (! sdp_parser->host_set) {
            sdp_parser->host_set = true;
            sdp_parser->host = info.host;
            sdp_parser->port = info.port;
            ASSIGN_INFO_OPT(ip, parent);
            if (ip) {
                sdp_parser->sender = ip->key.addr[0];
                sdp_parser->sender_set = true;
            } else {
                sdp_parser->sender_set = false;
            }
        } else if (0 != ip_addr_cmp(&sdp_parser->host, &info.host)) {
            /* Start conntracking between the advertized hosts
             * Notice that we request RT(C)P on behalf of our parent! */
            spawn_rtp_subparsers(&sdp_parser->host, sdp_parser->port, &info.host, info.port, now, parent->parser->proto);

            ASSIGN_INFO_OPT(ip, parent);
            bool may_use_stun[2] = {
                0 != ip_addr_cmp(&sdp_parser->sender, &sdp_parser->host),
                ip && 0 != ip_addr_cmp(&ip->key.addr[0], &info.host),
            };
            // If the sender IP was different from the advertized host, start conntracking on this socket too
            if (may_use_stun[0]) {
                spawn_rtp_subparsers(&sdp_parser->sender, sdp_parser->port, &info.host, info.port, now, parent->parser->proto);
            }
            // If _this_ sender IP is different from this advertized host, start conntracking on this socket as well
            if (may_use_stun[1]) {
                spawn_rtp_subparsers(&sdp_parser->host, sdp_parser->port, &ip->key.addr[0], info.port, now, parent->parser->proto);
            }
            // If both senders IP were different from advertized ones then start conntracking between these two senders IP as well
            if (may_use_stun[0] && may_use_stun[1]) {
                spawn_rtp_subparsers(&sdp_parser->sender, sdp_parser->port, &ip->key.addr[0], info.port, now, parent->parser->proto);
            }

            // TODO: terminate this parser. meanwhile, reset its state :
            sdp_parser->host_set = false;
            sdp_parser->sender_set = false;
        }
    }

    return proto_parse(NULL, &info.info, way, NULL, 0, 0, now, tot_cap_len, tot_packet);
}