|
|
|
@ -307,8 +307,9 @@ static void stream_unkernelize(struct packet_stream *ps); |
|
|
|
static void __monologue_destroy(struct call_monologue *monologue); |
|
|
|
static struct interface_address *get_interface_from_address(struct local_interface *lif, struct in6_addr *addr); |
|
|
|
static struct interface_address *get_interface_address(struct local_interface *lif, int family); |
|
|
|
static struct local_interface *get_local_interface(struct callmaster *m, str *name); |
|
|
|
static struct local_interface *get_local_interface(struct callmaster *m, const str *name); |
|
|
|
static const GQueue *get_interface_addresses(struct local_interface *lif, int family); |
|
|
|
static struct interface_address *get_any_interface_address(struct local_interface *lif); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -336,14 +337,11 @@ static void stream_fd_closed(int fd, void *p, uintptr_t u) { |
|
|
|
|
|
|
|
|
|
|
|
INLINE void __mp_address_translate(struct mp_address *o, const struct endpoint *ep) { |
|
|
|
if (IN6_IS_ADDR_V4MAPPED(&ep->ip46)) { |
|
|
|
o->family = AF_INET; |
|
|
|
o->family = family_from_address(&ep->ip46); |
|
|
|
if (o->family == AF_INET) |
|
|
|
o->u.ipv4 = in6_to_4(&ep->ip46); |
|
|
|
} |
|
|
|
else { |
|
|
|
o->family = AF_INET6; |
|
|
|
else |
|
|
|
memcpy(o->u.ipv6, &ep->ip46, sizeof(o->u.ipv6)); |
|
|
|
} |
|
|
|
o->port = ep->port; |
|
|
|
} |
|
|
|
|
|
|
|
@ -781,12 +779,12 @@ update_addr: |
|
|
|
char ifa_buf[64]; |
|
|
|
smart_ntop(ifa_buf, dst, sizeof(ifa_buf)); |
|
|
|
ifa = get_interface_from_address(media->interface, dst); |
|
|
|
if (!ifa) |
|
|
|
if (!ifa) { |
|
|
|
ilog(LOG_ERROR, "No matching local interface for destination address %s found", ifa_buf); |
|
|
|
else { |
|
|
|
ilog(LOG_INFO, "Switching local interface to %s", ifa_buf); |
|
|
|
media->local_address = ifa; |
|
|
|
goto drop; |
|
|
|
} |
|
|
|
ilog(LOG_INFO, "Switching local interface to %s", ifa_buf); |
|
|
|
media->local_address = ifa; |
|
|
|
update = 1; |
|
|
|
} |
|
|
|
|
|
|
|
@ -2046,6 +2044,34 @@ static void __tos_change(struct call *call, const struct sdp_ng_flags *flags) { |
|
|
|
__set_all_tos(call); |
|
|
|
} |
|
|
|
|
|
|
|
static void __init_interface(struct call_media *media, const str *ifname) { |
|
|
|
if (!media->interface || !media->local_address) |
|
|
|
goto get; |
|
|
|
if (!ifname || !ifname->s) |
|
|
|
return; |
|
|
|
if (!str_cmp_str(&media->interface->name, ifname)) |
|
|
|
return; |
|
|
|
get: |
|
|
|
media->interface = get_local_interface(media->call->callmaster, ifname); |
|
|
|
if (!media->interface) { |
|
|
|
media->interface = get_local_interface(media->call->callmaster, NULL); |
|
|
|
/* legacy support */ |
|
|
|
if (!str_cmp(ifname, "internal")) |
|
|
|
media->desired_family = AF_INET; |
|
|
|
else if (!str_cmp(ifname, "external")) |
|
|
|
media->desired_family = AF_INET6; |
|
|
|
else |
|
|
|
ilog(LOG_WARNING, "Interface '"STR_FORMAT"' not found, using default", STR_FMT(ifname)); |
|
|
|
} |
|
|
|
media->local_address = get_interface_address(media->interface, media->desired_family); |
|
|
|
if (!media->local_address) { |
|
|
|
ilog(LOG_WARNING, "No usable address in interface '"STR_FORMAT"' found, using default", |
|
|
|
STR_FMT(ifname)); |
|
|
|
media->local_address = get_any_interface_address(media->interface); |
|
|
|
media->desired_family = family_from_address(&media->local_address->addr); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* called with call->master_lock held in W */ |
|
|
|
int monologue_offer_answer(struct call_monologue *other_ml, GQueue *streams, |
|
|
|
const struct sdp_ng_flags *flags) |
|
|
|
@ -2057,10 +2083,8 @@ int monologue_offer_answer(struct call_monologue *other_ml, GQueue *streams, |
|
|
|
struct call_monologue *monologue = other_ml->active_dialogue; |
|
|
|
struct endpoint_map *em; |
|
|
|
struct call *call; |
|
|
|
struct callmaster *cm; |
|
|
|
|
|
|
|
call = monologue->call; |
|
|
|
cm = call->callmaster; |
|
|
|
|
|
|
|
call->last_signal = poller_now; |
|
|
|
call->deleted = 0; |
|
|
|
@ -2145,25 +2169,17 @@ int monologue_offer_answer(struct call_monologue *other_ml, GQueue *streams, |
|
|
|
__generate_crypto(flags, media, other_media); |
|
|
|
|
|
|
|
/* deduct address family from stream parameters received */ |
|
|
|
other_media->desired_family = AF_INET; |
|
|
|
if (!IN6_IS_ADDR_V4MAPPED(&sp->rtp_endpoint.ip46)) |
|
|
|
other_media->desired_family = AF_INET6; |
|
|
|
other_media->desired_family = family_from_address(&sp->rtp_endpoint.ip46); |
|
|
|
/* for outgoing SDP, use "direction"/DF or default to what was offered */ |
|
|
|
if (!media->desired_family) |
|
|
|
media->desired_family = other_media->desired_family; |
|
|
|
if (sp->desired_family) |
|
|
|
media->desired_family = sp->desired_family; |
|
|
|
else if (sp->direction[1] == DIR_EXTERNAL) |
|
|
|
media->desired_family = AF_INET6; |
|
|
|
|
|
|
|
|
|
|
|
/* local interface selection XXX */ |
|
|
|
media->interface = get_local_interface(cm, NULL); |
|
|
|
media->local_address = get_interface_address(media->interface, media->desired_family); |
|
|
|
other_media->interface = get_local_interface(cm, NULL); |
|
|
|
other_media->local_address = get_interface_address(other_media->interface, |
|
|
|
other_media->desired_family); |
|
|
|
|
|
|
|
/* local interface selection */ |
|
|
|
__init_interface(media, &sp->direction[1]); |
|
|
|
__init_interface(other_media, &sp->direction[0]); |
|
|
|
|
|
|
|
|
|
|
|
/* we now know what's being advertised by the other side */ |
|
|
|
@ -2840,10 +2856,10 @@ void callmaster_config_init(struct callmaster *m) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static struct local_interface *get_local_interface(struct callmaster *m, str *name) { |
|
|
|
static struct local_interface *get_local_interface(struct callmaster *m, const str *name) { |
|
|
|
struct local_interface *lif; |
|
|
|
|
|
|
|
if (!name) |
|
|
|
if (!name || !name->s) |
|
|
|
return m->interface_list.head->data; |
|
|
|
|
|
|
|
lif = g_hash_table_lookup(m->interfaces, name); |
|
|
|
@ -2875,6 +2891,17 @@ static struct interface_address *get_interface_address(struct local_interface *l |
|
|
|
return q->head->data; |
|
|
|
} |
|
|
|
|
|
|
|
/* safety fallback */ |
|
|
|
static struct interface_address *get_any_interface_address(struct local_interface *lif) { |
|
|
|
struct interface_address *ifa; |
|
|
|
GQueue q = G_QUEUE_INIT; |
|
|
|
|
|
|
|
get_all_interface_addresses(&q, lif, AF_INET); |
|
|
|
ifa = q.head->data; |
|
|
|
g_queue_clear(&q); |
|
|
|
return ifa; |
|
|
|
} |
|
|
|
|
|
|
|
void get_all_interface_addresses(GQueue *q, struct local_interface *lif, int family) { |
|
|
|
g_queue_append(q, get_interface_addresses(lif, family)); |
|
|
|
if (family == AF_INET) |
|
|
|
|