diff options
author | Alfred E. Heggestad <aeh@db.org> | 2015-10-29 20:12:41 +0100 |
---|---|---|
committer | Alfred E. Heggestad <aeh@db.org> | 2015-10-29 20:12:41 +0100 |
commit | 136f8543e65e29fea1538fa7cd9a4dbdd533a6eb (patch) | |
tree | ce8156399160eb04da2fac020d2ae2ae23afaacc | |
parent | f828b6600d2c21c5b4948e945e0c68523e136039 (diff) |
call: check address-family of incoming SDP offer
this fixes #79
-rw-r--r-- | include/baresip.h | 1 | ||||
-rw-r--r-- | src/call.c | 28 | ||||
-rw-r--r-- | src/ua.c | 23 | ||||
-rw-r--r-- | test/call.c | 35 | ||||
-rw-r--r-- | test/main.c | 1 | ||||
-rw-r--r-- | test/test.h | 1 |
6 files changed, 87 insertions, 2 deletions
diff --git a/include/baresip.h b/include/baresip.h index 7f49e36..2f91d6d 100644 --- a/include/baresip.h +++ b/include/baresip.h @@ -535,6 +535,7 @@ struct account *ua_prm(const struct ua *ua); struct list *ua_calls(const struct ua *ua); enum presence_status ua_presence_status(const struct ua *ua); void ua_presence_status_set(struct ua *ua, const enum presence_status status); +void ua_set_media_af(struct ua *ua, int af_media); /* One instance */ @@ -1217,7 +1217,7 @@ static bool have_common_audio_codecs(const struct call *call) if (!sc) return false; - ac = sc->data; + ac = sc->data; /* note: this will exclude telephone-event */ return ac != NULL; } @@ -1247,6 +1247,8 @@ int call_accept(struct call *call, struct sipsess_sock *sess_sock, } if (got_offer) { + struct sdp_media *m; + const struct sa *raddr; err = sdp_decode(call->sdp, msg->mb, true); if (err) @@ -1254,6 +1256,30 @@ int call_accept(struct call *call, struct sipsess_sock *sess_sock, call->got_offer = true; + /* + * Each media description in the SDP answer MUST + * use the same network type as the corresponding + * media description in the offer. + * + * See RFC 6157 + */ + m = stream_sdpmedia(audio_strm(call->audio)); + raddr = sdp_media_raddr(m); + + if (sa_af(raddr) != call->af) { + info("call: incompatible address-family" + " (local=%s, remote=%s)\n", + net_af2name(call->af), + net_af2name(sa_af(raddr))); + + sip_treply(NULL, uag_sip(), msg, + 488, "Not Acceptable Here"); + + call_event_handler(call, CALL_EVENT_CLOSED, + "Wrong address family"); + return 0; + } + /* Check if we have any common audio codecs, after * the SDP offer has been parsed */ @@ -34,6 +34,7 @@ struct ua { char *cuser; /**< SIP Contact username */ char *pub_gruu; /**< SIP Public GRUU */ int af; /**< Preferred Address Family */ + int af_media; enum presence_status my_status; /**< Presence Status */ }; @@ -428,6 +429,7 @@ static int ua_call_alloc(struct call **callp, struct ua *ua, struct call *xcall, const char *local_uri) { struct call_prm cprm; + int af = AF_UNSPEC; int err; if (*callp) { @@ -435,8 +437,18 @@ static int ua_call_alloc(struct call **callp, struct ua *ua, return EALREADY; } + /* 1. if AF_MEDIA is set, we prefer it + * 2. otherwise fall back to SIP AF + */ + if (ua->af_media) { + af = ua->af_media; + } + else if (ua->af) { + af = ua->af; + } + cprm.vidmode = vidmode; - cprm.af = ua->af; + cprm.af = af; err = call_alloc(callp, conf_config(), &ua->calls, ua->acc->dispname, @@ -1842,3 +1854,12 @@ struct ua *uag_current(void) return uag.ua_cur; } + + +void ua_set_media_af(struct ua *ua, int af_media) +{ + if (!ua) + return; + + ua->af_media = af_media; +} diff --git a/test/call.c b/test/call.c index cad90a6..7c96100 100644 --- a/test/call.c +++ b/test/call.c @@ -234,3 +234,38 @@ int test_call_reject(void) return err; } + + +int test_call_af_mismatch(void) +{ + struct fixture fix, *f = &fix; + int err = 0; + + fixture_init(f); + + ua_set_media_af(f->a.ua, AF_INET6); + ua_set_media_af(f->b.ua, AF_INET); + + /* Make a call from A to B */ + err = ua_connect(f->a.ua, 0, NULL, f->buri, NULL, VIDMODE_OFF); + TEST_ERR(err); + + /* run main-loop with timeout, wait for events */ + err = re_main_timeout(5); + TEST_ERR(err); + TEST_ERR(fix.err); + + ASSERT_EQ(0, fix.a.n_incoming); + ASSERT_EQ(0, fix.a.n_established); + ASSERT_EQ(1, fix.a.n_closed); + ASSERT_EQ(488, fix.a.close_scode); + + ASSERT_EQ(0, fix.b.n_incoming); + ASSERT_EQ(0, fix.b.n_established); + ASSERT_EQ(1, fix.b.n_closed); + + out: + fixture_close(f); + + return err; +} diff --git a/test/main.c b/test/main.c index a959a5e..8215ed4 100644 --- a/test/main.c +++ b/test/main.c @@ -25,6 +25,7 @@ static const struct test tests[] = { TEST(test_cplusplus), TEST(test_call_answer), TEST(test_call_reject), + TEST(test_call_af_mismatch), }; diff --git a/test/test.h b/test/test.h index 2600bd6..8aedc00 100644 --- a/test/test.h +++ b/test/test.h @@ -81,6 +81,7 @@ int test_ua_register(void); int test_call_answer(void); int test_call_reject(void); +int test_call_af_mismatch(void); #ifdef __cplusplus |