Commit f73f9b5c authored by Kai Vehmanen's avatar Kai Vehmanen

Convert indentation from tabs to spaces.

darcs-hash:20070918150713-77cd4-7bdd3f21524c846c1bf0c2c8cb96eb6104c96ad8.gz
parent d3e16af2
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
struct stun_bind_s struct stun_bind_s
{ {
stun_trans_t trans; stun_trans_t trans;
}; };
...@@ -81,37 +81,37 @@ static int ...@@ -81,37 +81,37 @@ static int
stun_bind_alloc (stun_bind_t **restrict context, int fd, stun_bind_alloc (stun_bind_t **restrict context, int fd,
const struct sockaddr *restrict srv, socklen_t srvlen) const struct sockaddr *restrict srv, socklen_t srvlen)
{ {
int val; int val;
stun_bind_t *ctx = malloc (sizeof (*ctx)); stun_bind_t *ctx = malloc (sizeof (*ctx));
if (ctx == NULL) if (ctx == NULL)
return ENOMEM; return ENOMEM;
memset (ctx, 0, sizeof (*ctx)); memset (ctx, 0, sizeof (*ctx));
*context = ctx; *context = ctx;
val = (fd != -1) val = (fd != -1)
? stun_trans_init (&ctx->trans, fd, srv, srvlen) ? stun_trans_init (&ctx->trans, fd, srv, srvlen)
: stun_trans_create (&ctx->trans, SOCK_DGRAM, 0, srv, srvlen); : stun_trans_create (&ctx->trans, SOCK_DGRAM, 0, srv, srvlen);
if (val) if (val)
{ {
free (ctx); free (ctx);
return val; return val;
} }
stun_init_request (ctx->trans.msg.buf, STUN_BINDING); stun_init_request (ctx->trans.msg.buf, STUN_BINDING);
return 0; return 0;
} }
static int static int
stun_bind_launch (stun_bind_t *ctx) stun_bind_launch (stun_bind_t *ctx)
{ {
int val = stun_trans_start (&ctx->trans); int val = stun_trans_start (&ctx->trans);
if (val) if (val)
stun_bind_cancel (ctx); stun_bind_cancel (ctx);
return val; return val;
} }
...@@ -119,30 +119,30 @@ int stun_bind_start (stun_bind_t **restrict context, int fd, ...@@ -119,30 +119,30 @@ int stun_bind_start (stun_bind_t **restrict context, int fd,
const struct sockaddr *restrict srv, const struct sockaddr *restrict srv,
socklen_t srvlen) socklen_t srvlen)
{ {
stun_bind_t *ctx; stun_bind_t *ctx;
int val = stun_bind_alloc (context, fd, srv, srvlen); int val = stun_bind_alloc (context, fd, srv, srvlen);
if (val) if (val)
return val; return val;
ctx = *context; ctx = *context;
ctx->trans.msg.length = sizeof (ctx->trans.msg.buf); ctx->trans.msg.length = sizeof (ctx->trans.msg.buf);
val = stun_finish (ctx->trans.msg.buf, &ctx->trans.msg.length); val = stun_finish (ctx->trans.msg.buf, &ctx->trans.msg.length);
if (val) if (val)
{ {
stun_bind_cancel (ctx); stun_bind_cancel (ctx);
return val; return val;
} }
return stun_bind_launch (ctx); return stun_bind_launch (ctx);
} }
void stun_bind_cancel (stun_bind_t *context) void stun_bind_cancel (stun_bind_t *context)
{ {
stun_trans_deinit (&context->trans); stun_trans_deinit (&context->trans);
free (context); free (context);
} }
...@@ -150,17 +150,17 @@ void stun_bind_cancel (stun_bind_t *context) ...@@ -150,17 +150,17 @@ void stun_bind_cancel (stun_bind_t *context)
unsigned stun_bind_timeout (const stun_bind_t *context) unsigned stun_bind_timeout (const stun_bind_t *context)
{ {
assert (context != NULL); assert (context != NULL);
return stun_trans_timeout (&context->trans); return stun_trans_timeout (&context->trans);
} }
int stun_bind_elapse (stun_bind_t *context) int stun_bind_elapse (stun_bind_t *context)
{ {
int val = stun_trans_tick (&context->trans); int val = stun_trans_tick (&context->trans);
if (val != EAGAIN) if (val != EAGAIN)
stun_bind_cancel (context); stun_bind_cancel (context);
return val; return val;
} }
...@@ -170,40 +170,40 @@ int stun_bind_process (stun_bind_t *restrict ctx, ...@@ -170,40 +170,40 @@ int stun_bind_process (stun_bind_t *restrict ctx,
const void *restrict buf, size_t len, const void *restrict buf, size_t len,
struct sockaddr *restrict addr, socklen_t *addrlen) struct sockaddr *restrict addr, socklen_t *addrlen)
{ {
int val, code; int val, code;
assert (ctx != NULL); assert (ctx != NULL);
val = stun_trans_preprocess (&ctx->trans, &code, buf, len); val = stun_trans_preprocess (&ctx->trans, &code, buf, len);
switch (val) switch (val)
{ {
case EAGAIN: case EAGAIN:
return EAGAIN; return EAGAIN;
case 0: case 0:
break; break;
default: default:
if (code == STUN_ROLE_CONFLICT) if (code == STUN_ROLE_CONFLICT)
val = ECONNRESET; val = ECONNRESET;
stun_bind_cancel (ctx); stun_bind_cancel (ctx);
return val; return val;
} }
val = stun_find_xor_addr (buf, STUN_XOR_MAPPED_ADDRESS, addr, addrlen); val = stun_find_xor_addr (buf, STUN_XOR_MAPPED_ADDRESS, addr, addrlen);
if (val) if (val)
{ {
DBG (" No XOR-MAPPED-ADDRESS: %s\n", strerror (val)); DBG (" No XOR-MAPPED-ADDRESS: %s\n", strerror (val));
val = stun_find_addr (buf, STUN_MAPPED_ADDRESS, addr, addrlen); val = stun_find_addr (buf, STUN_MAPPED_ADDRESS, addr, addrlen);
if (val) if (val)
{ {
DBG (" No MAPPED-ADDRESS: %s\n", strerror (val)); DBG (" No MAPPED-ADDRESS: %s\n", strerror (val));
stun_bind_cancel (ctx); stun_bind_cancel (ctx);
return val; return val;
} }
} }
DBG (" Mapped address found!\n"); DBG (" Mapped address found!\n");
stun_bind_cancel (ctx); stun_bind_cancel (ctx);
return 0; return 0;
} }
...@@ -213,28 +213,28 @@ int stun_bind_run (int fd, ...@@ -213,28 +213,28 @@ int stun_bind_run (int fd,
const struct sockaddr *restrict srv, socklen_t srvlen, const struct sockaddr *restrict srv, socklen_t srvlen,
struct sockaddr *restrict addr, socklen_t *addrlen) struct sockaddr *restrict addr, socklen_t *addrlen)
{ {
stun_bind_t *ctx; stun_bind_t *ctx;
uint8_t buf[STUN_MAXMSG]; uint8_t buf[STUN_MAXMSG];
ssize_t val; ssize_t val;
val = stun_bind_start (&ctx, fd, srv, srvlen); val = stun_bind_start (&ctx, fd, srv, srvlen);
if (val) if (val)
return val; return val;
do do
{ {
val = stun_trans_recv (&ctx->trans, buf, sizeof (buf)); val = stun_trans_recv (&ctx->trans, buf, sizeof (buf));
if (val == -1) if (val == -1)
{ {
val = errno; val = errno;
continue; continue;
} }
val = stun_bind_process (ctx, buf, val, addr, addrlen); val = stun_bind_process (ctx, buf, val, addr, addrlen);
} }
while (val == EAGAIN); while (val == EAGAIN);
return val; return val;
} }
...@@ -244,19 +244,19 @@ int ...@@ -244,19 +244,19 @@ int
stun_bind_keepalive (int fd, const struct sockaddr *restrict srv, stun_bind_keepalive (int fd, const struct sockaddr *restrict srv,
socklen_t srvlen) socklen_t srvlen)
{ {
uint8_t buf[28]; uint8_t buf[28];
size_t len = sizeof (buf); size_t len = sizeof (buf);
int val; int val;
stun_init_indication (buf, STUN_BINDING); stun_init_indication (buf, STUN_BINDING);
val = stun_finish (buf, &len); val = stun_finish (buf, &len);
assert (val == 0); assert (val == 0);
(void)val; (void)val;
/* NOTE: hopefully, this is only needed for non-stream sockets */ /* NOTE: hopefully, this is only needed for non-stream sockets */
if (stun_sendto (fd, buf, len, srv, srvlen) == -1) if (stun_sendto (fd, buf, len, srv, srvlen) == -1)
return errno; return errno;
return 0; return 0;
} }
...@@ -270,58 +270,58 @@ stun_conncheck_start (stun_bind_t **restrict context, int fd, ...@@ -270,58 +270,58 @@ stun_conncheck_start (stun_bind_t **restrict context, int fd,
bool cand_use, bool controlling, uint32_t priority, bool cand_use, bool controlling, uint32_t priority,
uint64_t tie) uint64_t tie)
{ {
int val; int val;
stun_bind_t *ctx; stun_bind_t *ctx;
assert (username != NULL); assert (username != NULL);
assert (password != NULL); assert (password != NULL);
val = stun_bind_alloc (&ctx, fd, srv, srvlen); val = stun_bind_alloc (&ctx, fd, srv, srvlen);
if (val) if (val)
return val; return val;
ctx->trans.key.length = strlen (password); ctx->trans.key.length = strlen (password);
ctx->trans.key.value = malloc (ctx->trans.key.length); ctx->trans.key.value = malloc (ctx->trans.key.length);
if (ctx->trans.key.value == NULL) if (ctx->trans.key.value == NULL)
{ {
val = ENOMEM; val = ENOMEM;
goto error; goto error;
} }
*context = ctx; *context = ctx;
memcpy (ctx->trans.key.value, password, ctx->trans.key.length); memcpy (ctx->trans.key.value, password, ctx->trans.key.length);
if (cand_use) if (cand_use)
{ {
val = stun_append_flag (ctx->trans.msg.buf, val = stun_append_flag (ctx->trans.msg.buf,
sizeof (ctx->trans.msg.buf), sizeof (ctx->trans.msg.buf),
STUN_USE_CANDIDATE); STUN_USE_CANDIDATE);
if (val) if (val)
goto error; goto error;
} }
val = stun_append32 (ctx->trans.msg.buf, sizeof (ctx->trans.msg.buf), val = stun_append32 (ctx->trans.msg.buf, sizeof (ctx->trans.msg.buf),
STUN_PRIORITY, priority); STUN_PRIORITY, priority);
if (val) if (val)
goto error; goto error;
val = stun_append64 (ctx->trans.msg.buf, sizeof (ctx->trans.msg.buf), val = stun_append64 (ctx->trans.msg.buf, sizeof (ctx->trans.msg.buf),
controlling ? STUN_ICE_CONTROLLING controlling ? STUN_ICE_CONTROLLING
: STUN_ICE_CONTROLLED, tie); : STUN_ICE_CONTROLLED, tie);
if (val) if (val)
goto error; goto error;
ctx->trans.msg.length = sizeof (ctx->trans.msg.buf); ctx->trans.msg.length = sizeof (ctx->trans.msg.buf);
val = stun_finish_short (ctx->trans.msg.buf, &ctx->trans.msg.length, val = stun_finish_short (ctx->trans.msg.buf, &ctx->trans.msg.length,
username, password, NULL); username, password, NULL);
if (val) if (val)
goto error; goto error;
return stun_bind_launch (ctx); return stun_bind_launch (ctx);
error: error:
stun_bind_cancel (*context); stun_bind_cancel (*context);
return val; return val;
} }
...@@ -52,20 +52,20 @@ static inline uint32_t crc32 (const struct iovec *iov, size_t size); ...@@ -52,20 +52,20 @@ static inline uint32_t crc32 (const struct iovec *iov, size_t size);
uint32_t stun_fingerprint (const uint8_t *msg, size_t len) uint32_t stun_fingerprint (const uint8_t *msg, size_t len)
{ {
struct iovec iov[3]; struct iovec iov[3];
uint16_t fakelen = htons (len - 20u); uint16_t fakelen = htons (len - 20u);
assert (len >= 28u); assert (len >= 28u);
iov[0].iov_base = (void *)msg; iov[0].iov_base = (void *)msg;
iov[0].iov_len = 2; iov[0].iov_len = 2;
iov[1].iov_base = &fakelen; iov[1].iov_base = &fakelen;
iov[1].iov_len = 2; iov[1].iov_len = 2;
iov[2].iov_base = (void *)(msg + 4); iov[2].iov_base = (void *)(msg + 4);
/* first 4 bytes done, last 8 bytes not summed */ /* first 4 bytes done, last 8 bytes not summed */
iov[2].iov_len = len - 12u; iov[2].iov_len = len - 12u;
return crc32 (iov, sizeof (iov) / sizeof (iov[0])) ^ 0x5354554e; return crc32 (iov, sizeof (iov) / sizeof (iov[0])) ^ 0x5354554e;
} }
/*- /*-
...@@ -165,17 +165,17 @@ static const uint32_t crc32_tab[] = { ...@@ -165,17 +165,17 @@ static const uint32_t crc32_tab[] = {
static inline static inline
uint32_t crc32 (const struct iovec *iov, size_t n) uint32_t crc32 (const struct iovec *iov, size_t n)
{ {
size_t i; size_t i;
uint32_t crc = 0xffffffff; uint32_t crc = 0xffffffff;
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
{ {
const uint8_t *p = iov[i].iov_base; const uint8_t *p = iov[i].iov_base;
size_t size = iov[i].iov_len; size_t size = iov[i].iov_len;
while (size--) while (size--)
crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
} }
return crc ^ 0xffffffff; return crc ^ 0xffffffff;
} }
...@@ -53,71 +53,71 @@ ...@@ -53,71 +53,71 @@
void stun_sha1 (const uint8_t *msg, size_t len, uint8_t *sha, void stun_sha1 (const uint8_t *msg, size_t len, uint8_t *sha,
const void *restrict key, size_t keylen) const void *restrict key, size_t keylen)
{ {
HMAC_CTX ctx; HMAC_CTX ctx;
uint16_t fakelen = htons (len - 20u); uint16_t fakelen = htons (len - 20u);
assert (len >= 44u); assert (len >= 44u);
HMAC_CTX_init (&ctx); HMAC_CTX_init (&ctx);
HMAC_Init_ex (&ctx, key, keylen, EVP_sha1 (), NULL); HMAC_Init_ex (&ctx, key, keylen, EVP_sha1 (), NULL);
HMAC_Update (&ctx, msg, 2); HMAC_Update (&ctx, msg, 2);
HMAC_Update (&ctx, (const uint8_t *)&fakelen, 2); HMAC_Update (&ctx, (const uint8_t *)&fakelen, 2);
/* first 4 bytes done, last 24 bytes not summed */ /* first 4 bytes done, last 24 bytes not summed */
HMAC_Update (&ctx, msg + 4, len - 28u); HMAC_Update (&ctx, msg + 4, len - 28u);
HMAC_Final (&ctx, sha, NULL); HMAC_Final (&ctx, sha, NULL);
HMAC_CTX_cleanup (&ctx); HMAC_CTX_cleanup (&ctx);
} }
void stun_hash_creds (const char *realm, const char *login, const char *pw, void stun_hash_creds (const char *realm, const char *login, const char *pw,
unsigned char md5[16]) unsigned char md5[16])
{ {
EVP_MD_CTX ctx; EVP_MD_CTX ctx;
assert (realm && login && pw && md5); assert (realm && login && pw && md5);
EVP_MD_CTX_init (&ctx); EVP_MD_CTX_init (&ctx);
EVP_DigestInit_ex (&ctx, EVP_md5 (), NULL); EVP_DigestInit_ex (&ctx, EVP_md5 (), NULL);
EVP_DigestUpdate (&ctx, realm, strlen (realm)); EVP_DigestUpdate (&ctx, realm, strlen (realm));
EVP_DigestUpdate (&ctx, ":", 1); EVP_DigestUpdate (&ctx, ":", 1);
EVP_DigestUpdate (&ctx, login, strlen (login)); EVP_DigestUpdate (&ctx, login, strlen (login));
EVP_DigestUpdate (&ctx, ":", 1); EVP_DigestUpdate (&ctx, ":", 1);
EVP_DigestUpdate (&ctx, pw, strlen (pw)); EVP_DigestUpdate (&ctx, pw, strlen (pw));
EVP_DigestFinal (&ctx, md5, NULL); EVP_DigestFinal (&ctx, md5, NULL);
} }
void stun_make_transid (stun_transid_t id) void stun_make_transid (stun_transid_t id)
{ {
/* /*
* transid = (HMAC_SHA1 (secret, counter) >> 64) * transid = (HMAC_SHA1 (secret, counter) >> 64)
* This consumes sizeof (secret) bytes of entropy every 2^64 messages. * This consumes sizeof (secret) bytes of entropy every 2^64 messages.
*/ */
static struct static struct
{ {
pthread_mutex_t lock; pthread_mutex_t lock;
uint64_t counter; uint64_t counter;
uint8_t secret[16]; uint8_t secret[16];
} store = { PTHREAD_MUTEX_INITIALIZER, 0, "" }; } store = { PTHREAD_MUTEX_INITIALIZER, 0, "" };
union union
{ {
uint64_t value; uint64_t value;
uint8_t bytes[1]; uint8_t bytes[1];
} counter; } counter;
uint8_t key[16], sha[20]; uint8_t key[16], sha[20];
pthread_mutex_lock (&store.lock); pthread_mutex_lock (&store.lock);
counter.value = store.counter++; counter.value = store.counter++;
if (counter.value == 0) if (counter.value == 0)
RAND_pseudo_bytes (store.secret, sizeof (store.secret)); RAND_pseudo_bytes (store.secret, sizeof (store.secret));
memcpy (key, store.secret, sizeof (key)); memcpy (key, store.secret, sizeof (key));
pthread_mutex_unlock (&store.lock); pthread_mutex_unlock (&store.lock);
/* Computes hash out of contentious area */ /* Computes hash out of contentious area */
HMAC (EVP_sha1 (), key, sizeof (key), counter.bytes, sizeof (counter), HMAC (EVP_sha1 (), key, sizeof (key), counter.bytes, sizeof (counter),
sha, NULL); sha, NULL);
memcpy (id, sha, 12); memcpy (id, sha, 12);
} }
...@@ -48,7 +48,7 @@ static uint8_t unique_id[UNIQUE_SIZE]; ...@@ -48,7 +48,7 @@ static uint8_t unique_id[UNIQUE_SIZE];
static void generate_unique_id (void) static void generate_unique_id (void)
{ {
RAND_pseudo_bytes (unique_id, sizeof (unique_id)); RAND_pseudo_bytes (unique_id, sizeof (unique_id));
} }
...@@ -56,45 +56,45 @@ static void ...@@ -56,45 +56,45 @@ static void
stun_generate_nonce (uint8_t *nonce, time_t now, stun_generate_nonce (uint8_t *nonce, time_t now,
const struct sockaddr_storage *restrict addr) const struct sockaddr_storage *restrict addr)
{ {
static pthread_once_t once = PTHREAD_ONCE_INIT; static pthread_once_t once = PTHREAD_ONCE_INIT;
HMAC_CTX ctx; HMAC_CTX ctx;
uint32_t stamp = now; uint32_t stamp = now;
pthread_once (&once, generate_unique_id); pthread_once (&once, generate_unique_id);
/* /*
* Nonce are generated from the current time and the client address and * Nonce are generated from the current time and the client address and
* port number, keyed with a pseudo-random secret. * port number, keyed with a pseudo-random secret.
*/ */
HMAC_CTX_init (&ctx); HMAC_CTX_init (&ctx);
HMAC_Init_ex (&ctx, unique_id, sizeof (unique_id), EVP_sha1 (), NULL); HMAC_Init_ex (&ctx, unique_id, sizeof (unique_id), EVP_sha1 (), NULL);
HMAC_Update (&ctx, &stamp, 4); HMAC_Update (&ctx, &stamp, 4);
HMAC_Update (&ctx, &ss->family, sizeof (ss->family)); HMAC_Update (&ctx, &ss->family, sizeof (ss->family));
switch (addr->ss_family) switch (addr->ss_family)
{ {
case AF_INET: case AF_INET:
{ {
const struct sockaddr_in *ip4 = (const struct sockaddr_in *)addr; const struct sockaddr_in *ip4 = (const struct sockaddr_in *)addr;
HMAC_Update (&ctx, &ip4->sin_addr, 4); HMAC_Update (&ctx, &ip4->sin_addr, 4);
HMAC_Update (&ctx, &ip4->sin_port, 2); HMAC_Update (&ctx, &ip4->sin_port, 2);
break; break;
} }
case AF_INET6: case AF_INET6:
{ {
const struct sockaddr_in6*ip6 = (const struct sockaddr_in6*)addr; const struct sockaddr_in6*ip6 = (const struct sockaddr_in6*)addr;
HMAC_Update (&ctx, &ip6->sin6_addr, 16); HMAC_Update (&ctx, &ip6->sin6_addr, 16);
HMAC_Update (&ctx, &ip6->sin6_port, 2); HMAC_Update (&ctx, &ip6->sin6_port, 2);
if (IN6_IS_ADDR_LINK_LOCAL (&ip6->sin6_addr)) if (IN6_IS_ADDR_LINK_LOCAL (&ip6->sin6_addr))
HMAC_Update (&ctx, &ip6->sin6_scope_id HMAC_Update (&ctx, &ip6->sin6_scope_id
sizeof (ip6->sin6_scope_id)); sizeof (ip6->sin6_scope_id));
break; break;
} }
} }
HMAC_Final (&ctx, nonce, NULL); HMAC_Final (&ctx, nonce, NULL);
HMAC_CTX_cleanup (&ctx); HMAC_CTX_cleanup (&ctx);
memcpy (nonce + 20, &stamp, 4); memcpy (nonce + 20, &stamp, 4);
} }
...@@ -102,9 +102,9 @@ static int ...@@ -102,9 +102,9 @@ static int
stun_append_nonce (uint8_t *buf, size_t buflen, stun_append_nonce (uint8_t *buf, size_t buflen,
const struct sockaddr_storage *restrict addr) const struct sockaddr_storage *restrict addr)
{ {
uint8_t nonce[NONCE_SIZE]; uint8_t nonce[NONCE_SIZE];
stun_generate_nonce (nonce, time (NULL), addr); stun_generate_nonce (nonce, time (NULL), addr);
return stun_append_bytes (buf, buflen, STUN_NONCE, nonce, sizeof (nonce)); return stun_append_bytes (buf, buflen, STUN_NONCE, nonce, sizeof (nonce));
} }
...@@ -112,7 +112,7 @@ static int ...@@ -112,7 +112,7 @@ static int
stun_verify_nonce (const uint8_t *buf, unsigned valid_time, stun_verify_nonce (const uint8_t *buf, unsigned valid_time,
const struct sockaddr_storage *restrict addr) const struct sockaddr_storage *restrict addr)
{ {
const uint8_t * const uint8_t *
stun_generate_nonce (nonce, time (NULL), addr); stun_generate_nonce (nonce, time (NULL), addr);
return stun_append_bytes (buf, buflen, STUN_NONCE, nonce, sizeof (nonce)); return stun_append_bytes (buf, buflen, STUN_NONCE, nonce, sizeof (nonce));
} }
...@@ -54,24 +54,24 @@ static int ...@@ -54,24 +54,24 @@ static int
stun_bind_error (uint8_t *buf, size_t *plen, const uint8_t *req, stun_bind_error (uint8_t *buf, size_t *plen, const uint8_t *req,
stun_error_t code, const char *pass) stun_error_t code, const char *pass)
{ {
size_t len = *plen; size_t len = *plen;
int val; int val;
*plen = 0; *plen = 0;
DBG ("STUN Error Reply (buffer size: %u)...\n", (unsigned)len); DBG ("STUN Error Reply (buffer size: %u)...\n", (unsigned)len);
val = stun_init_error (buf, len, req, code); val = stun_init_error (buf, len, req, code);
if (val) if (val)
return val; return val;
val = stun_finish_short (buf, &len, NULL, pass, NULL); val = stun_finish_short (buf, &len, NULL, pass, NULL);
if (val) if (val)
return val; return val;
*plen = len; *plen = len;
DBG (" Error response (%u) of %u bytes\n", (unsigned)code, DBG (" Error response (%u) of %u bytes\n", (unsigned)code,
(unsigned)*plen); (unsigned)*plen);
return 0; return 0;
} }
...@@ -80,125 +80,125 @@ stun_conncheck_reply (uint8_t *buf, size_t *restrict plen, const uint8_t *msg, ...@@ -80,125 +80,125 @@ stun_conncheck_reply (uint8_t *buf, size_t *restrict plen, const uint8_t *msg,
const struct sockaddr *restrict src, socklen_t srclen, const struct sockaddr *restrict src, socklen_t srclen,
const char *pass, bool *restrict control, uint64_t tie) const char *pass, bool *restrict control, uint64_t tie)
{ {
size_t len = *plen; size_t len = *plen;
uint64_t q; uint64_t q;
int val, ret = 0; int val, ret = 0;
#define err( code ) \ #define err( code ) \
stun_bind_error (buf, &len, msg, code, pass); \ stun_bind_error (buf, &len, msg, code, pass); \
*plen = len *plen = len
*plen = 0; *plen = 0;
DBG ("STUN Reply (buffer size = %u)...\n", (unsigned)len); DBG ("STUN Reply (buffer size = %u)...\n", (unsigned)len);
if (stun_get_class (msg) != STUN_REQUEST) if (stun_get_class (msg) != STUN_REQUEST)
{ {
DBG (" Unhandled non-request (class %u) message.\n", DBG (" Unhandled non-request (class %u) message.\n",
stun_get_class (msg)); stun_get_class (msg));
return EINVAL; return EINVAL;
} }
if (!stun_demux (msg)) if (!stun_demux (msg))
{ {
DBG (" Incorrectly multiplexed STUN message ignored.\n"); DBG (" Incorrectly multiplexed STUN message ignored.\n");
return EINVAL; return EINVAL;
} }
if (stun_has_unknown (msg)) if (stun_has_unknown (msg))
{ {
DBG (" Unknown mandatory attributes in message.\n"); DBG (" Unknown mandatory attributes in message.\n");
val = stun_init_error_unknown (buf, len, msg); val = stun_init_error_unknown (buf, len, msg);
if (!val) if (!val)
val = stun_finish_short (buf, &len, NULL, pass, NULL); val = stun_finish_short (buf, &len, NULL, pass, NULL);
if (val) if (val)
goto failure; goto failure;
*plen = len; *plen = len;
return EPROTO; return EPROTO;
} }
/* Short term credentials checking */ /* Short term credentials checking */
val = 0; val = 0;
if (!stun_present (msg, STUN_MESSAGE_INTEGRITY) // FIXME: wrong! if (!stun_present (msg, STUN_MESSAGE_INTEGRITY) // FIXME: wrong!
|| !stun_present (msg, STUN_USERNAME)) || !stun_present (msg, STUN_USERNAME))
{ {
DBG (" Missing USERNAME or MESSAGE-INTEGRITY.\n"); DBG (" Missing USERNAME or MESSAGE-INTEGRITY.\n");
val = STUN_BAD_REQUEST; val = STUN_BAD_REQUEST;
} }
else else
/* FIXME: verify USERNAME, return STUN_UNAUTHORIZED if wrong */ /* FIXME: verify USERNAME, return STUN_UNAUTHORIZED if wrong */
if (stun_verify_password (msg, pass)) if (stun_verify_password (msg, pass))
{ {
DBG (" Integrity check failed.\n"); DBG (" Integrity check failed.\n");
val = STUN_UNAUTHORIZED; val = STUN_UNAUTHORIZED;
} }
if (val) if (val)
{ {
stun_bind_error (buf, &len, msg, val, NULL); stun_bind_error (buf, &len, msg, val, NULL);
*plen = len; *plen = len;
return EPERM; return EPERM;
} }
if (stun_get_method (msg) != STUN_BINDING) if (stun_get_method (msg) != STUN_BINDING)
{ {
DBG (" Bad request (method %u) message.\n", DBG (" Bad request (method %u) message.\n",
stun_get_method (msg)); stun_get_method (msg));
err (STUN_BAD_REQUEST); err (STUN_BAD_REQUEST);
return EPROTO; return EPROTO;
} }
/* Role conflict handling */ /* Role conflict handling */
assert (control != NULL); assert (control != NULL);
if (!stun_find64 (msg, *control ? STUN_ICE_CONTROLLING if (!stun_find64 (msg, *control ? STUN_ICE_CONTROLLING
: STUN_ICE_CONTROLLED, &q)) : STUN_ICE_CONTROLLED, &q))
{ {
DBG ("STUN Role Conflict detected:\n"); DBG ("STUN Role Conflict detected:\n");
if (tie < q) if (tie < q)
{ {
DBG (" switching role from \"controll%s\" to \"controll%s\"\n", DBG (" switching role from \"controll%s\" to \"controll%s\"\n",
*control ? "ing" : "ed", *control ? "ed" : "ing"); *control ? "ing" : "ed", *control ? "ed" : "ing");
*control = !*control; *control = !*control;
ret = EACCES; ret = EACCES;
} }
else else
{ {
DBG (" staying \"controll%s\" (sending error)\n", DBG (" staying \"controll%s\" (sending error)\n",
*control ? "ing" : "ed"); *control ? "ing" : "ed");
*plen = len; *plen = len;
err (STUN_ROLE_CONFLICT); err (STUN_ROLE_CONFLICT);
return 0; return 0;
} }
} }
#ifndef NDEBUG #ifndef NDEBUG
else else
if (stun_find64 (msg, *control ? STUN_ICE_CONTROLLED if (stun_find64 (msg, *control ? STUN_ICE_CONTROLLED
: STUN_ICE_CONTROLLING, &q)) : STUN_ICE_CONTROLLING, &q))
DBG ("STUN Role not specified by peer!\n"); DBG ("STUN Role not specified by peer!\n");
#endif #endif
stun_init_response (buf, len, msg); stun_init_response (buf, len, msg);
val = stun_append_xor_addr (buf, len, STUN_XOR_MAPPED_ADDRESS, val = stun_append_xor_addr (buf, len, STUN_XOR_MAPPED_ADDRESS,
src, srclen); src, srclen);
if (val) if (val)
{ {
DBG (" Mapped address problem: %s\n", strerror (val)); DBG (" Mapped address problem: %s\n", strerror (val));
goto failure; goto failure;
} }
val = stun_finish_short (buf, &len, NULL, pass, NULL); val = stun_finish_short (buf, &len, NULL, pass, NULL);
if (val) if (val)
goto failure; goto failure;
*plen = len; *plen = len;
DBG (" All done (response size: %u)\n", (unsigned)len); DBG (" All done (response size: %u)\n", (unsigned)len);
return ret; return ret;
failure: failure:
assert (*plen == 0); assert (*plen == 0);
DBG (" Fatal error formatting Response: %s\n", strerror (val)); DBG (" Fatal error formatting Response: %s\n", strerror (val));
return val; return val;
} }
#undef err #undef err
...@@ -207,38 +207,38 @@ failure: ...@@ -207,38 +207,38 @@ failure:
char *stun_conncheck_username (const uint8_t *restrict msg, char *stun_conncheck_username (const uint8_t *restrict msg,
char *restrict buf, size_t buflen) char *restrict buf, size_t buflen)
{ {
size_t i; size_t i;
if ((buflen == 0) if ((buflen == 0)
|| stun_find_string (msg, STUN_USERNAME, buf, (buflen - 1) / 6)) || stun_find_string (msg, STUN_USERNAME, buf, (buflen - 1) / 6))
return NULL; return NULL;
for (i = 0; buf[i]; i++) for (i = 0; buf[i]; i++)
{ {
char c = buf[i]; char c = buf[i];
/* ref ICE sect 7.1.1.4. (ID-16) */ /* ref ICE sect 7.1.1.4. (ID-16) */
if (((c >= '/') && (c <= '9')) || ((c >= 'A') && (c <= 'Z')) if (((c >= '/') && (c <= '9')) || ((c >= 'A') && (c <= 'Z'))
|| ((c >= 'a') && (c <= 'z')) || (c == '+') || (c == ':')) || ((c >= 'a') && (c <= 'z')) || (c == '+') || (c == ':'))
continue; continue;
return NULL; return NULL;
} }
return buf; return buf;
} }
uint32_t stun_conncheck_priority (const uint8_t *msg) uint32_t stun_conncheck_priority (const uint8_t *msg)
{ {
uint32_t value; uint32_t value;
if (stun_find32 (msg, STUN_PRIORITY, &value)) if (stun_find32 (msg, STUN_PRIORITY, &value))
return 0; return 0;
return value; return value;
} }
bool stun_conncheck_use_candidate (const uint8_t *msg) bool stun_conncheck_use_candidate (const uint8_t *msg)
{ {
return !stun_find_flag (msg, STUN_USE_CANDIDATE); return !stun_find_flag (msg, STUN_USE_CANDIDATE);
} }
This diff is collapsed.
...@@ -53,120 +53,120 @@ ...@@ -53,120 +53,120 @@
static void static void
printaddr (const char *str, const struct sockaddr *addr, socklen_t addrlen) printaddr (const char *str, const struct sockaddr *addr, socklen_t addrlen)
{ {
char hostbuf[NI_MAXHOST], servbuf[NI_MAXSERV]; char hostbuf[NI_MAXHOST], servbuf[NI_MAXSERV];
int val = getnameinfo (addr, addrlen, hostbuf, sizeof (hostbuf), int val = getnameinfo (addr, addrlen, hostbuf, sizeof (hostbuf),
servbuf, sizeof (servbuf), servbuf, sizeof (servbuf),
NI_NUMERICHOST | NI_NUMERICSERV); NI_NUMERICHOST | NI_NUMERICSERV);
if (val) if (val)
printf ("%s: %s\n", str, gai_strerror (val)); printf ("%s: %s\n", str, gai_strerror (val));
else else
printf ("%s: %s port %s\n", str, hostbuf, servbuf); printf ("%s: %s port %s\n", str, hostbuf, servbuf);
} }
static int run (int family, const char *hostname, const char *service) static int run (int family, const char *hostname, const char *service)
{ {
struct addrinfo hints, *res; struct addrinfo hints, *res;
const struct addrinfo *ptr; const struct addrinfo *ptr;
int ret = -1; int ret = -1;
memset (&hints, 0, sizeof (hints)); memset (&hints, 0, sizeof (hints));
hints.ai_family = family; hints.ai_family = family;
hints.ai_socktype = SOCK_DGRAM; hints.ai_socktype = SOCK_DGRAM;
if (service == NULL) if (service == NULL)
service = "3478"; service = "3478";
ret = getaddrinfo (hostname, service, &hints, &res); ret = getaddrinfo (hostname, service, &hints, &res);
if (ret) if (ret)
{ {
fprintf (stderr, "%s (port %s): %s\n", hostname, service, fprintf (stderr, "%s (port %s): %s\n", hostname, service,
gai_strerror (ret)); gai_strerror (ret));
return -1; return -1;
} }
for (ptr = res; ptr != NULL; ptr = ptr->ai_next) for (ptr = res; ptr != NULL; ptr = ptr->ai_next)
{ {
struct sockaddr_storage addr; struct sockaddr_storage addr;
socklen_t addrlen = sizeof (addr); socklen_t addrlen = sizeof (addr);
int val; int val;
printaddr ("Server address", ptr->ai_addr, ptr->ai_addrlen); printaddr ("Server address", ptr->ai_addr, ptr->ai_addrlen);
val = stun_bind_run (-1, ptr->ai_addr, ptr->ai_addrlen, val = stun_bind_run (-1, ptr->ai_addr, ptr->ai_addrlen,
(struct sockaddr *)&addr, &addrlen); (struct sockaddr *)&addr, &addrlen);
if (val) if (val)
fprintf (stderr, "%s\n", strerror (val)); fprintf (stderr, "%s\n", strerror (val));
else else
{ {
printaddr ("Mapped address", (struct sockaddr *)&addr, addrlen); printaddr ("Mapped address", (struct sockaddr *)&addr, addrlen);
ret = 0; ret = 0;
} }
} }
freeaddrinfo (res); freeaddrinfo (res);
return ret; return ret;
} }
int main (int argc, char *argv[]) int main (int argc, char *argv[])
{ {
static const struct option opts[] = static const struct option opts[] =
{ {
{ "ipv4", no_argument, NULL, '4' }, { "ipv4", no_argument, NULL, '4' },
{ "ipv6", no_argument, NULL, '6' }, { "ipv6", no_argument, NULL, '6' },
{ "help", no_argument, NULL, 'h' }, { "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' }, { "version", no_argument, NULL, 'V' },
{ NULL, 0, NULL, 0 } { NULL, 0, NULL, 0 }
}; };
const char *server = NULL, *port = NULL; const char *server = NULL, *port = NULL;
int family = AF_UNSPEC; int family = AF_UNSPEC;
for (;;) for (;;)
{ {
int val = getopt_long (argc, argv, "46hV", opts, NULL); int val = getopt_long (argc, argv, "46hV", opts, NULL);
if (val == EOF) if (val == EOF)
break; break;
switch (val) switch (val)
{ {
case '4': case '4':
family = AF_INET; family = AF_INET;
break; break;
case '6': case '6':
family = AF_INET6; family = AF_INET6;
break; break;
case 'h': case 'h':
printf ("Usage: %s [-4|-6] <server> [port number]\n" printf ("Usage: %s [-4|-6] <server> [port number]\n"
"Performs STUN Binding Discovery\n" "Performs STUN Binding Discovery\n"
"\n" "\n"
" -4, --ipv4 Force IP version 4\n" " -4, --ipv4 Force IP version 4\n"
" -6, --ipv6 Force IP version 6\n" " -6, --ipv6 Force IP version 6\n"
"\n", argv[0]); "\n", argv[0]);
return 0; return 0;
case 'V': case 'V':
printf ("stunbcd: STUN Binding Discovery client (%s v%s)\n", printf ("stunbcd: STUN Binding Discovery client (%s v%s)\n",
PACKAGE, VERSION); PACKAGE, VERSION);
return 0; return 0;
default: default:
return 2; return 2;
} }
} }
if (optind < argc) if (optind < argc)
server = argv[optind++]; server = argv[optind++];
if (optind < argc) if (optind < argc)
port = argv[optind++]; port = argv[optind++];
if (optind < argc) if (optind < argc)
{ {
fprintf (stderr, "%s: extra parameter `%s'\n", argv[0], argv[optind]); fprintf (stderr, "%s: extra parameter `%s'\n", argv[0], argv[optind]);
return 2; return 2;
} }
return run (family, server, port) ? 1 : 0; return run (family, server, port) ? 1 : 0;
} }
...@@ -70,77 +70,77 @@ ...@@ -70,77 +70,77 @@
*/ */
int listen_socket (int fam, int type, int proto, uint16_t port) int listen_socket (int fam, int type, int proto, uint16_t port)
{ {
int yes = 1; int yes = 1;
int fd = socket (fam, type, proto); int fd = socket (fam, type, proto);
if (fd == -1) if (fd == -1)
{ {
perror ("Error opening IP port"); perror ("Error opening IP port");
return -1; return -1;
} }
if (fd < 3) if (fd < 3)
goto error; goto error;
struct sockaddr_storage addr; struct sockaddr_storage addr;
memset (&addr, 0, sizeof (addr)); memset (&addr, 0, sizeof (addr));
addr.ss_family = fam; addr.ss_family = fam;
#ifdef HAVE_SA_LEN #ifdef HAVE_SA_LEN
addr.ss_len = sizeof (addr); addr.ss_len = sizeof (addr);
#endif #endif
switch (fam) switch (fam)
{ {
case AF_INET: case AF_INET:
((struct sockaddr_in *)&addr)->sin_port = port; ((struct sockaddr_in *)&addr)->sin_port = port;
break; break;
case AF_INET6: case AF_INET6:
#ifdef IPV6_V6ONLY #ifdef IPV6_V6ONLY
setsockopt (fd, SOL_IPV6, IPV6_V6ONLY, &yes, sizeof (yes)); setsockopt (fd, SOL_IPV6, IPV6_V6ONLY, &yes, sizeof (yes));
#endif #endif
((struct sockaddr_in6 *)&addr)->sin6_port = port; ((struct sockaddr_in6 *)&addr)->sin6_port = port;
break; break;
} }
if (bind (fd, (struct sockaddr *)&addr, sizeof (addr))) if (bind (fd, (struct sockaddr *)&addr, sizeof (addr)))
{ {
perror ("Error opening IP port"); perror ("Error opening IP port");
goto error; goto error;
} }
if ((type == SOCK_DGRAM) || (type == SOCK_RAW)) if ((type == SOCK_DGRAM) || (type == SOCK_RAW))
{ {
switch (fam) switch (fam)
{ {
case AF_INET: case AF_INET:
setsockopt (fd, SOL_IP, IP_PKTINFO, &yes, sizeof (yes)); setsockopt (fd, SOL_IP, IP_PKTINFO, &yes, sizeof (yes));
#ifdef IP_RECVERR #ifdef IP_RECVERR
setsockopt (fd, SOL_IP, IP_RECVERR, &yes, sizeof (yes)); setsockopt (fd, SOL_IP, IP_RECVERR, &yes, sizeof (yes));
#endif #endif
break; break;
case AF_INET6: case AF_INET6:
setsockopt (fd, SOL_IPV6, IPV6_RECVPKTINFO, &yes, setsockopt (fd, SOL_IPV6, IPV6_RECVPKTINFO, &yes,
sizeof (yes)); sizeof (yes));
#ifdef IPV6_RECVERR #ifdef IPV6_RECVERR
setsockopt (fd, SOL_IPV6, IPV6_RECVERR, &yes, sizeof (yes)); setsockopt (fd, SOL_IPV6, IPV6_RECVERR, &yes, sizeof (yes));
#endif #endif
break; break;
} }
} }
else else
{ {
if (listen (fd, INT_MAX)) if (listen (fd, INT_MAX))
{ {
perror ("Error opening IP port"); perror ("Error opening IP port");
goto error; goto error;
} }
} }
return fd; return fd;
error: error:
close (fd); close (fd);
return -1; return -1;
} }
...@@ -148,9 +148,9 @@ error: ...@@ -148,9 +148,9 @@ error:
static int recv_err (int fd) static int recv_err (int fd)
{ {
#ifdef MSG_ERRQUEUE #ifdef MSG_ERRQUEUE
struct msghdr hdr; struct msghdr hdr;
memset (&hdr, 0, sizeof (hdr)); memset (&hdr, 0, sizeof (hdr));
return recvmsg (fd, &hdr, MSG_ERRQUEUE) >= 0; return recvmsg (fd, &hdr, MSG_ERRQUEUE) >= 0;
#endif #endif
} }
...@@ -158,104 +158,99 @@ static int recv_err (int fd) ...@@ -158,104 +158,99 @@ static int recv_err (int fd)
/** Receives a message or dequeues an error from a socket */ /** Receives a message or dequeues an error from a socket */
ssize_t recv_safe (int fd, struct msghdr *msg) ssize_t recv_safe (int fd, struct msghdr *msg)
{ {
ssize_t len = recvmsg (fd, msg, 0); ssize_t len = recvmsg (fd, msg, 0);
if (len == -1) if (len == -1)
recv_err (fd); recv_err (fd);
else else
if (msg->msg_flags & MSG_TRUNC) if (msg->msg_flags & MSG_TRUNC)
{ {
errno = EMSGSIZE; errno = EMSGSIZE;
return -1; return -1;
} }
return len; return len;
} }
/** Sends a message through a socket */ /** Sends a message through a socket */
ssize_t send_safe (int fd, const struct msghdr *msg) ssize_t send_safe (int fd, const struct msghdr *msg)
{ {
ssize_t len; ssize_t len;
do do
len = sendmsg (fd, msg, 0); len = sendmsg (fd, msg, 0);
while ((len == -1) && (recv_err (fd) == 0)); while ((len == -1) && (recv_err (fd) == 0));
return len; return len;
} }
static int dgram_process (int sock) static int dgram_process (int sock)
{ {
struct sockaddr_storage addr; struct sockaddr_storage addr;
uint8_t buf[STUN_MAXMSG]; uint8_t buf[STUN_MAXMSG];
char ctlbuf[CMSG_SPACE (sizeof (struct in6_pktinfo))]; char ctlbuf[CMSG_SPACE (sizeof (struct in6_pktinfo))];
struct iovec iov = { buf, sizeof (buf) }; struct iovec iov = { buf, sizeof (buf) };
struct msghdr mh = struct msghdr mh =
{ {
.msg_name = (struct sockaddr *)&addr, .msg_name = (struct sockaddr *)&addr,
.msg_namelen = sizeof (addr), .msg_namelen = sizeof (addr),
.msg_iov = &iov, .msg_iov = &iov,
.msg_iovlen = 1, .msg_iovlen = 1,
.msg_control = ctlbuf, .msg_control = ctlbuf,
.msg_controllen = sizeof (ctlbuf) .msg_controllen = sizeof (ctlbuf)
}; };
size_t len = recv_safe (sock, &mh); size_t len = recv_safe (sock, &mh);
if (len == (size_t)-1) if (len == (size_t)-1)
return -1; return -1;
/* Mal-formatted packets */ /* Mal-formatted packets */
if ((stun_validate (buf, len) <= 0) if ((stun_validate (buf, len) <= 0)
|| (stun_get_class (buf) != STUN_REQUEST)) || (stun_get_class (buf) != STUN_REQUEST))
return -1; return -1;
/* Unknown attributes */ /* Unknown attributes */
if (stun_has_unknown (buf)) if (stun_has_unknown (buf))
{ {
stun_init_error_unknown (buf, sizeof (buf), buf); stun_init_error_unknown (buf, sizeof (buf), buf);
goto finish; goto finish;
} }
switch (stun_get_method (buf)) switch (stun_get_method (buf))
{ {
case STUN_BINDING: case STUN_BINDING:
stun_init_response (buf, sizeof (buf), buf); stun_init_response (buf, sizeof (buf), buf);
if (stun_has_cookie (buf)) if (stun_has_cookie (buf))
stun_append_xor_addr (buf, sizeof (buf), stun_append_xor_addr (buf, sizeof (buf),
STUN_XOR_MAPPED_ADDRESS, STUN_XOR_MAPPED_ADDRESS,
mh.msg_name, mh.msg_namelen); mh.msg_name, mh.msg_namelen);
else else
stun_append_addr (buf, sizeof (buf), STUN_MAPPED_ADDRESS, stun_append_addr (buf, sizeof (buf), STUN_MAPPED_ADDRESS,
mh.msg_name, mh.msg_namelen); mh.msg_name, mh.msg_namelen);
break; break;
case STUN_ALLOCATE: default:
case STUN_CONNECT: stun_init_error (buf, sizeof (buf), buf, STUN_BAD_REQUEST);
case STUN_SET_ACTIVE_DST: }
goto send;
default:
stun_init_error (buf, sizeof (buf), buf, STUN_BAD_REQUEST);
}
finish: finish:
stun_finish (buf, &iov.iov_len); stun_finish (buf, &iov.iov_len);
send: send:
len = send_safe (sock, &mh); len = send_safe (sock, &mh);
return (len < iov.iov_len) ? -1 : 0; return (len < iov.iov_len) ? -1 : 0;
} }
static int run (int family, int protocol, unsigned port) static int run (int family, int protocol, unsigned port)
{ {
int sock = listen_socket (family, SOCK_DGRAM, protocol, htons (port)); int sock = listen_socket (family, SOCK_DGRAM, protocol, htons (port));
if (sock == -1) if (sock == -1)
return -1; return -1;
for (;;) for (;;)
dgram_process (sock); dgram_process (sock);
} }
...@@ -263,38 +258,38 @@ static int run (int family, int protocol, unsigned port) ...@@ -263,38 +258,38 @@ static int run (int family, int protocol, unsigned port)
* But calling exit() is needed for gcov to work properly. */ * But calling exit() is needed for gcov to work properly. */
static void exit_handler (int signum) static void exit_handler (int signum)
{ {
(void)signum; (void)signum;
exit (0); exit (0);
} }
int main (int argc, char *argv[]) int main (int argc, char *argv[])
{ {
int family = AF_INET; int family = AF_INET;
unsigned port = IPPORT_STUN; unsigned port = IPPORT_STUN;
for (;;) for (;;)
{ {
int c = getopt (argc, argv, "46"); int c = getopt (argc, argv, "46");
if (c == EOF) if (c == EOF)
break; break;
switch (c) switch (c)
{ {
case '4': case '4':
family = AF_INET; family = AF_INET;
break; break;
case '6': case '6':
family = AF_INET6; family = AF_INET6;
break; break;
} }
} }
if (optind < argc) if (optind < argc)
port = atoi (argv[optind++]); port = atoi (argv[optind++]);
signal (SIGINT, exit_handler); signal (SIGINT, exit_handler);
signal (SIGTERM, exit_handler); signal (SIGTERM, exit_handler);
return run (family, IPPROTO_UDP, port) ? EXIT_FAILURE : EXIT_SUCCESS; return run (family, IPPROTO_UDP, port) ? EXIT_FAILURE : EXIT_SUCCESS;
} }
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -55,45 +55,45 @@ ...@@ -55,45 +55,45 @@
int main (void) int main (void)
{ {
struct sockaddr_in ip4; struct sockaddr_in ip4;
stun_msg_t buf; stun_msg_t buf;
ssize_t val; ssize_t val;
size_t len; size_t len;
static const uint8_t req[] = static const uint8_t req[] =
"\x00\x01" "\x00\x00" "\x00\x01" "\x00\x00"
"\x00\x01\x02\x03\x04\x05\x06\x07" "\x00\x01\x02\x03\x04\x05\x06\x07"
"\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"; "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F";
memset (&ip4, 0, sizeof (ip4)); memset (&ip4, 0, sizeof (ip4));
ip4.sin_family = AF_INET; ip4.sin_family = AF_INET;
#ifdef HAVE_SA_LEN #ifdef HAVE_SA_LEN
ip4.sin_len = sizeof (addr); ip4.sin_len = sizeof (addr);
#endif #endif
ip4.sin_port = htons (12345); ip4.sin_port = htons (12345);
ip4.sin_addr.s_addr = htonl (0x7f000001); ip4.sin_addr.s_addr = htonl (0x7f000001);
/* Same with too small response buffer */ /* Same with too small response buffer */
stun_init_request (buf, STUN_BINDING); stun_init_request (buf, STUN_BINDING);
len = sizeof (buf); len = sizeof (buf);
stun_finish (buf, &len); stun_finish (buf, &len);
len = 20 + 12 + 4 + stun_align (strlen (PACKAGE_STRING)) + 7; len = 20 + 12 + 4 + stun_align (strlen (PACKAGE_STRING)) + 7;
val = stun_bind_reply (buf, &len, buf, val = stun_bind_reply (buf, &len, buf,
(struct sockaddr *)&ip4, sizeof (ip4), false); (struct sockaddr *)&ip4, sizeof (ip4), false);
assert (val == ENOBUFS); assert (val == ENOBUFS);
assert (len == 0); assert (len == 0);
/* Same with too small response buffer */ /* Same with too small response buffer */
stun_init_request (buf, STUN_BINDING); stun_init_request (buf, STUN_BINDING);
stun_append_string (buf, sizeof (buf), 0x666, "Unknown attribute!"); stun_append_string (buf, sizeof (buf), 0x666, "Unknown attribute!");
len = sizeof (buf); len = sizeof (buf);
stun_finish (buf, &len); stun_finish (buf, &len);
len = 20 + 4 + stun_align (strlen (PACKAGE_STRING)) + 7; len = 20 + 4 + stun_align (strlen (PACKAGE_STRING)) + 7;
val = stun_bind_reply (buf, &len, buf, val = stun_bind_reply (buf, &len, buf,
(struct sockaddr *)&ip4, sizeof (ip4), false); (struct sockaddr *)&ip4, sizeof (ip4), false);
assert (val == ENOBUFS); assert (val == ENOBUFS);
assert (len == 0); assert (len == 0);
return 0; return 0;
} }
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -63,80 +63,80 @@ ...@@ -63,80 +63,80 @@
static void stun_gettime (struct timespec *restrict now) static void stun_gettime (struct timespec *restrict now)
{ {
#if (_POSIX_MONOTONIC_CLOCK - 0) >= 0 #if (_POSIX_MONOTONIC_CLOCK - 0) >= 0
if (clock_gettime (CLOCK_MONOTONIC, now)) if (clock_gettime (CLOCK_MONOTONIC, now))
#endif #endif
{ // fallback to wall clock { // fallback to wall clock
struct timeval tv; struct timeval tv;
gettimeofday (&tv, NULL); gettimeofday (&tv, NULL);
now->tv_sec = tv.tv_sec; now->tv_sec = tv.tv_sec;
now->tv_nsec = tv.tv_usec * 1000; now->tv_nsec = tv.tv_usec * 1000;
} }
} }
static inline void add_delay (struct timespec *ts, unsigned delay) static inline void add_delay (struct timespec *ts, unsigned delay)
{ {
div_t d = div (delay, 1000); div_t d = div (delay, 1000);
ts->tv_sec += d.quot; ts->tv_sec += d.quot;
ts->tv_nsec += d.rem * 1000000; ts->tv_nsec += d.rem * 1000000;
while (ts->tv_nsec > 1000000000) while (ts->tv_nsec > 1000000000)
{ {
ts->tv_nsec -= 1000000000; ts->tv_nsec -= 1000000000;
ts->tv_sec++; ts->tv_sec++;
} }
} }
void stun_timer_start (stun_timer_t *timer) void stun_timer_start (stun_timer_t *timer)
{ {
stun_gettime (&timer->deadline); stun_gettime (&timer->deadline);
add_delay (&timer->deadline, timer->delay = STUN_INIT_TIMEOUT); add_delay (&timer->deadline, timer->delay = STUN_INIT_TIMEOUT);
} }
void stun_timer_start_reliable (stun_timer_t *timer) void stun_timer_start_reliable (stun_timer_t *timer)
{ {
stun_gettime (&timer->deadline); stun_gettime (&timer->deadline);
add_delay (&timer->deadline, timer->delay = STUN_RELIABLE_TIMEOUT); add_delay (&timer->deadline, timer->delay = STUN_RELIABLE_TIMEOUT);
} }
unsigned stun_timer_remainder (const stun_timer_t *timer) unsigned stun_timer_remainder (const stun_timer_t *timer)
{ {
unsigned delay; unsigned delay;
struct timespec now; struct timespec now;
stun_gettime (&now); stun_gettime (&now);
if (now.tv_sec > timer->deadline.tv_sec) if (now.tv_sec > timer->deadline.tv_sec)
return 0; return 0;
delay = timer->deadline.tv_sec - now.tv_sec; delay = timer->deadline.tv_sec - now.tv_sec;
if ((delay == 0) && (now.tv_nsec >= timer->deadline.tv_nsec)) if ((delay == 0) && (now.tv_nsec >= timer->deadline.tv_nsec))
return 0; return 0;
delay *= 1000; delay *= 1000;
delay += ((signed)(timer->deadline.tv_nsec - now.tv_nsec)) / 1000000; delay += ((signed)(timer->deadline.tv_nsec - now.tv_nsec)) / 1000000;
return delay; return delay;
} }
int stun_timer_refresh (stun_timer_t *timer) int stun_timer_refresh (stun_timer_t *timer)
{ {
unsigned delay = stun_timer_remainder (timer); unsigned delay = stun_timer_remainder (timer);
if (delay == 0) if (delay == 0)
{ {
#if STUN_RELIABLE_TIMEOUT < STUN_END_TIMEOUT #if STUN_RELIABLE_TIMEOUT < STUN_END_TIMEOUT
/* Reliable timeout MUST be bigger (or equal) to end timeout, so that /* Reliable timeout MUST be bigger (or equal) to end timeout, so that
* retransmissions never happen with reliable transports. */ * retransmissions never happen with reliable transports. */
# error Inconsistent STUN timeout values! # error Inconsistent STUN timeout values!
#endif #endif
if (timer->delay >= STUN_END_TIMEOUT) if (timer->delay >= STUN_END_TIMEOUT)
return -1; return -1;
add_delay (&timer->deadline, timer->delay *= 2); add_delay (&timer->deadline, timer->delay *= 2);
} }
return delay; return delay;
} }
...@@ -46,8 +46,8 @@ ...@@ -46,8 +46,8 @@
typedef struct stun_timer_s typedef struct stun_timer_s
{ {
struct timespec deadline; struct timespec deadline;
unsigned delay; unsigned delay;
} stun_timer_t; } stun_timer_t;
......
This diff is collapsed.
...@@ -48,27 +48,27 @@ ...@@ -48,27 +48,27 @@
typedef struct stun_trans_s typedef struct stun_trans_s
{ {
stun_timer_t timer; stun_timer_t timer;
unsigned flags; unsigned flags;
struct struct
{ {
size_t length, offset; size_t length, offset;
uint8_t buf[STUN_MAXMSG]; uint8_t buf[STUN_MAXMSG];
} msg; } msg;
struct struct
{ {
int fd; int fd;
socklen_t dstlen; socklen_t dstlen;
struct sockaddr_storage dst; struct sockaddr_storage dst;
} sock; } sock;
struct struct
{ {
size_t length; size_t length;
uint8_t *value; uint8_t *value;
} key; } key;
} stun_trans_t; } stun_trans_t;
...@@ -171,12 +171,12 @@ ssize_t stun_recvfrom (int fd, uint8_t *buf, size_t maxlen, ...@@ -171,12 +171,12 @@ ssize_t stun_recvfrom (int fd, uint8_t *buf, size_t maxlen,
static inline ssize_t stun_send (int fd, const uint8_t *buf, size_t len) static inline ssize_t stun_send (int fd, const uint8_t *buf, size_t len)
{ {
return stun_sendto (fd, buf, len, NULL, 0); return stun_sendto (fd, buf, len, NULL, 0);
} }
static inline ssize_t stun_recv (int fd, uint8_t *buf, size_t maxlen) static inline ssize_t stun_recv (int fd, uint8_t *buf, size_t maxlen)
{ {
return stun_recvfrom (fd, buf, maxlen, NULL, NULL); return stun_recvfrom (fd, buf, maxlen, NULL, NULL);
} }
# ifdef __cplusplus # ifdef __cplusplus
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment