fix incorrect source address of STUN binding responses

git.mgm/mediaproxy-ng/origin/mr3.2
Richard Fuchs 12 years ago
parent d63df522d6
commit 1a83499916

@ -500,6 +500,41 @@ dummy:
in->handler = &__sh_noop;
}
void callmaster_msg_mh_src(struct callmaster *cm, struct msghdr *mh) {
struct cmsghdr *ch;
struct in_pktinfo *pi;
struct in6_pktinfo *pi6;
struct sockaddr_in6 *sin6;
sin6 = mh->msg_name;
ch = CMSG_FIRSTHDR(mh);
ZERO(*ch);
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
ch->cmsg_len = CMSG_LEN(sizeof(*pi));
ch->cmsg_level = IPPROTO_IP;
ch->cmsg_type = IP_PKTINFO;
pi = (void *) CMSG_DATA(ch);
ZERO(*pi);
pi->ipi_spec_dst.s_addr = cm->conf.ipv4;
mh->msg_controllen = CMSG_SPACE(sizeof(*pi));
}
else {
ch->cmsg_len = CMSG_LEN(sizeof(*pi6));
ch->cmsg_level = IPPROTO_IPV6;
ch->cmsg_type = IPV6_PKTINFO;
pi6 = (void *) CMSG_DATA(ch);
ZERO(*pi6);
pi6->ipi6_addr = cm->conf.ipv6;
mh->msg_controllen = CMSG_SPACE(sizeof(*pi6));
}
}
/* called with r->up (== cs) locked */
static int stream_packet(struct streamrelay *sr_incoming, str *s, struct sockaddr_in6 *fsin) {
struct streamrelay *sr_outgoing, *sr_out_rtcp, *sr_in_rtcp;
@ -510,9 +545,6 @@ static int stream_packet(struct streamrelay *sr_incoming, str *s, struct sockadd
struct msghdr mh;
struct iovec iov;
unsigned char buf[256];
struct cmsghdr *ch;
struct in_pktinfo *pi;
struct in6_pktinfo *pi6;
struct call *c;
struct callmaster *m;
unsigned char cc;
@ -625,9 +657,6 @@ forward:
mh.msg_control = buf;
mh.msg_controllen = sizeof(buf);
ch = CMSG_FIRSTHDR(&mh);
ZERO(*ch);
ZERO(sin6);
sin6.sin6_family = AF_INET6;
sin6.sin6_addr = sr_incoming->peer.ip46;
@ -635,28 +664,7 @@ forward:
mh.msg_name = &sin6;
mh.msg_namelen = sizeof(sin6);
if (IN6_IS_ADDR_V4MAPPED(&sin6.sin6_addr)) {
ch->cmsg_len = CMSG_LEN(sizeof(*pi));
ch->cmsg_level = IPPROTO_IP;
ch->cmsg_type = IP_PKTINFO;
pi = (void *) CMSG_DATA(ch);
ZERO(*pi);
pi->ipi_spec_dst.s_addr = m->conf.ipv4;
mh.msg_controllen = CMSG_SPACE(sizeof(*pi));
}
else {
ch->cmsg_len = CMSG_LEN(sizeof(*pi6));
ch->cmsg_level = IPPROTO_IPV6;
ch->cmsg_type = IPV6_PKTINFO;
pi6 = (void *) CMSG_DATA(ch);
ZERO(*pi6);
pi6->ipi6_addr = m->conf.ipv6;
mh.msg_controllen = CMSG_SPACE(sizeof(*pi6));
}
callmaster_msg_mh_src(m, &mh);
ZERO(iov);
iov.iov_base = s->s;

@ -183,6 +183,7 @@ struct callmaster *callmaster_new(struct poller *);
void callmaster_config(struct callmaster *m, struct callmaster_config *c);
void callmaster_exclude_port(struct callmaster *m, u_int16_t p);
int callmaster_has_ipv6(struct callmaster *);
void callmaster_msg_mh_src(struct callmaster *, struct msghdr *);
str *call_request_tcp(char **, struct callmaster *);

@ -174,9 +174,14 @@ out:
}
static void output_init(struct msghdr *mh, struct iovec *iov, struct sockaddr_in6 *sin,
struct header *hdr, unsigned short code, u_int32_t *transaction)
struct header *hdr, unsigned short code, u_int32_t *transaction,
unsigned char *buf, int buflen)
{
ZERO(*mh);
mh->msg_control = buf;
mh->msg_controllen = buflen;
mh->msg_name = sin;
mh->msg_namelen = sizeof(*sin);
mh->msg_iov = iov;
@ -222,11 +227,13 @@ static inline void __output_add(struct msghdr *mh, struct tlv *tlv, unsigned int
__output_add(mh, &(attr)->tlv, sizeof(*(attr)), code, data, len)
static void output_finish(struct msghdr *mh) {
static void output_finish(struct msghdr *mh, struct callmaster *cm) {
struct header *hdr;
hdr = mh->msg_iov->iov_base;
hdr->msg_len = htons(hdr->msg_len);
callmaster_msg_mh_src(cm, mh);
}
static void fingerprint(struct msghdr *mh, struct fingerprint *fp) {
@ -278,7 +285,7 @@ static void integrity(struct msghdr *mh, struct msg_integrity *mi, str *pwd) {
static void stun_error_len(int fd, struct sockaddr_in6 *sin, struct header *req,
int code, char *reason, int len, u_int16_t add_attr, void *attr_cont,
int attr_len)
int attr_len, struct callmaster *cm)
{
struct header hdr;
struct error_code ec;
@ -286,8 +293,9 @@ static void stun_error_len(int fd, struct sockaddr_in6 *sin, struct header *req,
struct generic aa;
struct msghdr mh;
struct iovec iov[6]; /* hdr, ec, reason, aa, attr_cont, fp */
unsigned char buf[256];
output_init(&mh, iov, sin, &hdr, STUN_BINDING_ERROR_RESPONSE, req->transaction);
output_init(&mh, iov, sin, &hdr, STUN_BINDING_ERROR_RESPONSE, req->transaction, buf, sizeof(buf));
ec.codes = htonl(((code / 100) << 8) | (code % 100));
output_add_data(&mh, &ec, STUN_ERROR_CODE, reason, len);
@ -296,16 +304,16 @@ static void stun_error_len(int fd, struct sockaddr_in6 *sin, struct header *req,
fingerprint(&mh, &fp);
output_finish(&mh);
output_finish(&mh, cm);
sendmsg(fd, &mh, 0);
}
#define stun_error(fd, sin, str, code, reason) \
#define stun_error(cm, fd, sin, str, code, reason) \
stun_error_len(fd, sin, str, code, reason "\0\0\0", strlen(reason), \
0, NULL, 0)
#define stun_error_attrs(fd, sin, str, code, reason, type, content, len) \
0, NULL, 0, cm)
#define stun_error_attrs(cm, fd, sin, str, code, reason, type, content, len) \
stun_error_len(fd, sin, str, code, reason "\0\0\0", strlen(reason), \
type, content, len)
type, content, len, cm)
@ -367,8 +375,10 @@ static int stun_binding_success(int fd, struct header *req, struct stun_attrs *a
struct fingerprint fp;
struct msghdr mh;
struct iovec iov[4]; /* hdr, xma, mi, fp */
unsigned char buf[256];
struct callmaster *cm = peer->up->call->callmaster;
output_init(&mh, iov, sin, &hdr, STUN_BINDING_SUCCESS_RESPONSE, req->transaction);
output_init(&mh, iov, sin, &hdr, STUN_BINDING_SUCCESS_RESPONSE, req->transaction, buf, sizeof(buf));
xma.port = sin->sin6_port ^ htons(STUN_COOKIE >> 16);
if (IN6_IS_ADDR_V4MAPPED(&sin->sin6_addr)) {
@ -388,7 +398,7 @@ static int stun_binding_success(int fd, struct header *req, struct stun_attrs *a
integrity(&mh, &mi, &peer->ice_pwd);
fingerprint(&mh, &fp);
output_finish(&mh);
output_finish(&mh, cm);
sendmsg(fd, &mh, 0);
return 0;
@ -417,6 +427,7 @@ int stun(str *b, struct streamrelay *sr, struct sockaddr_in6 *sin) {
u_int16_t unknowns[UNKNOWNS_COUNT];
const char *err;
char addr[64];
struct callmaster *cm = sr->up->up->call->callmaster;
smart_ntop_port(addr, sin, sizeof(addr));
@ -442,7 +453,7 @@ int stun(str *b, struct streamrelay *sr, struct sockaddr_in6 *sin) {
goto ignore;
mylog(LOG_WARNING, "STUN packet contained unknown "
"\"comprehension required\" attribute(s)" SLF, SLP);
stun_error_attrs(sr->fd.fd, sin, req, 420, "Unknown attribute",
stun_error_attrs(cm, sr->fd.fd, sin, req, 420, "Unknown attribute",
STUN_UNKNOWN_ATTRIBUTES, unknowns,
u_int16_t_arr_len(unknowns) * 2);
return 0;
@ -474,11 +485,11 @@ int stun(str *b, struct streamrelay *sr, struct sockaddr_in6 *sin) {
bad_req:
mylog(LOG_INFO, "Received invalid STUN packet" SLF ": %s", SLP, err);
stun_error(sr->fd.fd, sin, req, 400, "Bad request");
stun_error(cm, sr->fd.fd, sin, req, 400, "Bad request");
return 0;
unauth:
mylog(LOG_INFO, "STUN authentication mismatch" SLF, SLP);
stun_error(sr->fd.fd, sin, req, 401, "Unauthorized");
stun_error(cm, sr->fd.fd, sin, req, 401, "Unauthorized");
return 0;
ignore:
mylog(LOG_INFO, "Not handling potential STUN packet" SLF ": %s", SLP, err);

Loading…
Cancel
Save