Previously, when creating the expecations, SIP Alg would assume the RTP packets are sent from the same IP address + port which had been announced in the SDP offer + answer. As specified in rfc4961, this might not be the case, as the RTP packets might be sent from different IP addresses and / or port.
This commit adds extra logic, by creating two expectations, one in each direction, to support the "port case", i.e., the RTP packets are sent from a different port than the one the host is listenning on. Signed-off-by: Tiago Lam <tiago...@gmail.com> --- lib/conntrack.c | 76 ++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 25 deletions(-) diff --git a/lib/conntrack.c b/lib/conntrack.c index 65d10dd08..0db3447f2 100644 --- a/lib/conntrack.c +++ b/lib/conntrack.c @@ -2610,32 +2610,31 @@ expectation_lookup(struct hmap *alg_expectations, static void sip_expectation_create(struct conntrack *ct, - const ovs_be32 offer_addr, - const ovs_be32 answer_addr, - const ovs_be16 offer_port, + const ovs_be32 src_addr, + const ovs_be32 dst_addr, + const ovs_be16 dst_port, const long long now, const struct conn *master_conn) { - /* Set src address coming from answer SDP 'c' */ - struct ct_addr src_addr; - memset(&src_addr, 0, sizeof src_addr); - src_addr.ipv4_aligned = answer_addr; - /* Set dst address coming from offer SDP 'c' */ - struct ct_addr dst_addr; - memset(&dst_addr, 0, sizeof dst_addr); - dst_addr.ipv4_aligned = offer_addr; + /* Set src address (from SDP's 'c') */ + struct ct_addr ct_src_addr; + memset(&ct_src_addr, 0, sizeof ct_src_addr); + ct_src_addr.ipv4_aligned = src_addr; + /* Set dst address (from SDP's 'c') */ + struct ct_addr ct_dst_addr; + memset(&ct_dst_addr, 0, sizeof ct_dst_addr); + ct_dst_addr.ipv4_aligned = dst_addr; struct alg_exp_node *alg_exp_node = xzalloc(sizeof *alg_exp_node); alg_exp_node->key.dl_type = master_conn->key.dl_type; - /* nw_proto might won't be the same as SIP, since RTP is over UDP - hence - * set it to UDP explicitly */ + /* RTP is over UDP - hence set nw_proto to UDP explicitly */ alg_exp_node->key.nw_proto = IPPROTO_UDP; alg_exp_node->key.zone = master_conn->key.zone; - alg_exp_node->key.src.addr = src_addr; - alg_exp_node->key.dst.addr = dst_addr; + alg_exp_node->key.src.addr = ct_src_addr; + alg_exp_node->key.dst.addr = ct_dst_addr; alg_exp_node->key.src.port = ALG_WC_SRC_PORT; - alg_exp_node->key.dst.port = offer_port; + alg_exp_node->key.dst.port = dst_port; alg_exp_node->master_mark = master_conn->mark; alg_exp_node->master_label = master_conn->label; alg_exp_node->master_key = master_conn->key; @@ -2664,6 +2663,39 @@ sip_expectation_create(struct conntrack *ct, ct_rwlock_unlock(&ct->resources_lock); } +/* Setups two expectations for the RTP connections, one in each direction. + * Example: If an SDP answer announces it is listenning at IP address 10.0.1. + * 10:6000 and an the SDP offer at 10.0.2.10:6000, then: + * - Sets a UDP expectation going from 10.0.1.10:0 to 10.0.2.10:6000: + * - Sets another UDP expectation going from 10.0.2.10:0 to 10.0.1.10:6000; + * + * Thus, this allows traffic from a different port than the one the host is + * listenning to (the one it announced in the SDP). + * + * XXX According to rfc4961, hosts might send RTP packets from a different IP + * address and / or port (i.e. asymmetrically). Since this function supports + * the sending of packets from a different port, consider supporting the + * sending from a different IP address. + */ +static void +sip_expectations_setup(struct conntrack *ct, + const struct sip_sdp *offer_sdp, + const struct sip_sdp *answer_sdp, + const long long now, + const struct conn *conn) { + ovs_be32 offer_addr = htonl(offer_sdp->conn); + ovs_be16 offer_port = htons(offer_sdp->port); + ovs_be32 answer_addr = htonl(answer_sdp->conn); + ovs_be16 answer_port = htons(answer_sdp->port); + + /* Set expectation from SDP answer -> SDP offer */ + sip_expectation_create(ct, answer_addr, offer_addr, offer_port, now, + conn); + /* Set expectation from SDP offer -> SDP answer */ + sip_expectation_create(ct, offer_addr, answer_addr, answer_port, now, + conn); +} + static void expectation_create(struct conntrack *ct, ovs_be16 dst_port, @@ -3383,9 +3415,6 @@ handle_sip(struct conntrack *ct, /* Check if this SIP reply has an SDP. */ struct sip_sdp *sdp = sip_parse_sdp(msg_bdy, sip_len); - ovs_be32 offer_addr; - ovs_be32 offer_port; - ovs_be32 answer_addr; if (sdp == NULL) { if (conn->sip_state->peer[0].sdp != NULL && conn->sip_state->peer[1].sdp == NULL) { @@ -3400,12 +3429,9 @@ handle_sip(struct conntrack *ct, /* Received a SIP 200 OK from peer, we are now able to set up * the expectations for the data connections, based on the SDP * offer and answer */ - offer_addr = htonl(conn->sip_state->peer[0].sdp->conn); - offer_port = htons(conn->sip_state->peer[0].sdp->port); - answer_addr = htonl(conn->sip_state->peer[1].sdp->conn); - - sip_expectation_create(ct, offer_addr, answer_addr, offer_port, - now, conn); + sip_expectations_setup(ct, conn->sip_state->peer[0].sdp, + conn->sip_state->peer[1].sdp, now, + conn); } } } -- 2.14.3 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev