2006-12-21 06:30:28 +00:00
|
|
|
/*
|
|
|
|
* This file is part of the Sofia-SIP package
|
|
|
|
*
|
|
|
|
* Copyright (C) 2005 Nokia Corporation.
|
|
|
|
*
|
|
|
|
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2.1 of
|
|
|
|
* the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
|
|
|
* 02110-1301 USA
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
Sync to current darcs tree:
Mon Sep 17 14:50:04 EDT 2007 Pekka.Pessi@nokia.com
* sofia-sip/sip_util.h: updated documentation
Mon Sep 17 14:50:18 EDT 2007 Pekka.Pessi@nokia.com
* sofia-sip/tport_tag.h: updated documentation
Mon Sep 17 14:50:28 EDT 2007 Pekka.Pessi@nokia.com
* soa_tag.c: updated documentation
Wed Sep 19 12:50:01 EDT 2007 Pekka.Pessi@nokia.com
* msg: updated documentation
Wed Sep 19 13:29:50 EDT 2007 Pekka.Pessi@nokia.com
* url: updated documentation
Wed Sep 19 13:32:14 EDT 2007 Pekka.Pessi@nokia.com
* nth: updated documentation
Wed Sep 19 13:32:27 EDT 2007 Pekka.Pessi@nokia.com
* nea: updated documentation
Wed Sep 19 13:33:36 EDT 2007 Pekka.Pessi@nokia.com
* http: updated documentation
Wed Sep 19 13:36:58 EDT 2007 Pekka.Pessi@nokia.com
* bnf: updated documentation
Wed Sep 19 13:38:58 EDT 2007 Pekka.Pessi@nokia.com
* nua: updated nua_stack_init_handle() prototype
Wed Sep 19 18:45:56 EDT 2007 Pekka.Pessi@nokia.com
* sip: added sip_name_addr_xtra(), sip_name_addr_dup()
Wed Sep 19 19:00:19 EDT 2007 Pekka.Pessi@nokia.com
* sip_basic.c: cleaned old crud
Thu Sep 20 13:34:04 EDT 2007 Pekka.Pessi@nokia.com
* iptsec: updated documentation
Thu Sep 20 13:36:22 EDT 2007 Pekka.Pessi@nokia.com
* tport: updated documentation
Thu Sep 20 13:36:56 EDT 2007 Pekka.Pessi@nokia.com
* su: updated documentation
Removed internal files from doxygen-generated documentation.
Thu Sep 20 13:38:29 EDT 2007 Pekka.Pessi@nokia.com
* soa: fixed documentation
Thu Sep 20 13:39:56 EDT 2007 Pekka.Pessi@nokia.com
* sdp: updated documentation
Thu Sep 20 13:40:16 EDT 2007 Pekka.Pessi@nokia.com
* ipt: updated documentation
Thu Sep 20 14:24:20 EDT 2007 Pekka.Pessi@nokia.com
* nta: updated documentation
Thu Sep 20 14:41:04 EDT 2007 Pekka.Pessi@nokia.com
* nua: updated documentation
Updated tag documentation.
Moved doxygen doc entries from sofia-sip/nua_tag.h to nua_tag.c.
Removed internal datatypes and files from the generated documents.
Wed Sep 19 13:34:20 EDT 2007 Pekka.Pessi@nokia.com
* docs: updated the generation of documentation. Updated links to header files.
Thu Sep 20 08:45:32 EDT 2007 Pekka.Pessi@nokia.com
* sip/Makefile.am: added tags to <sofia-sip/sip_extra.h>
Added check for extra tags in torture_sip.c.
Thu Sep 20 14:45:22 EDT 2007 Pekka.Pessi@nokia.com
* stun: updated documentation
Wed Jul 4 18:55:20 EDT 2007 Pekka.Pessi@nokia.com
* torture_heap.c: added tests for ##sort() and su_smoothsort()
Wed Jul 4 18:56:59 EDT 2007 Pekka.Pessi@nokia.com
* Makefile.am: added smoothsort.c
Fri Jul 13 12:38:44 EDT 2007 Pekka.Pessi@nokia.com
* sofia-sip/heap.h: heap_remove() now set()s index to 0 on removed item
Mon Jul 23 11:14:22 EDT 2007 Pekka.Pessi@nokia.com
* sofia-sip/heap.h: fixed bug in heap##remove()
If left kid was in heap but right was not, left kid was ignored.
Wed Jul 4 18:51:08 EDT 2007 Pekka.Pessi@nokia.com
* smoothsort.c: added
Wed Jul 4 18:51:34 EDT 2007 Pekka.Pessi@nokia.com
* heap.h: using su_smoothsort()
Fri Jul 6 10:20:27 EDT 2007 Pekka.Pessi@nokia.com
* smoothsort.c: added
Wed Sep 19 17:40:30 EDT 2007 Pekka.Pessi@nokia.com
* msg_parser.awk: generate two parser tables, default and extended
Wed Sep 19 18:39:45 EDT 2007 Pekka.Pessi@nokia.com
* msg_parser.awk: just generate list of extra headers
Allocate extended parser dynamically.
Wed Sep 19 18:59:59 EDT 2007 Pekka.Pessi@nokia.com
* sip: added Remote-Party-ID, P-Asserted-Identity, P-Preferred-Identity
Added functions sip_update_default_mclass() and sip_extend_mclass()
for handling the extended parser. Note that Reply-To and Alert-Info are only
available with the extended parser.
Wed Sep 19 19:05:44 EDT 2007 Pekka.Pessi@nokia.com
* RELEASE: updated
Thu Sep 20 13:38:59 EDT 2007 Pekka.Pessi@nokia.com
* sip: updated documentation
Thu Sep 20 14:17:28 EDT 2007 Pekka.Pessi@nokia.com
* docs/conformance.docs: updated
Mon Oct 1 10:11:14 EDT 2007 Pekka.Pessi@nokia.com
* tport_tag.c: re-enabled tptag_trusted
Thu Oct 4 09:21:07 EDT 2007 Pekka.Pessi@nokia.com
* su_osx_runloop.c: moved virtual function table after struct definition
Preparing for su_port_vtable_t refactoring.
Thu Oct 4 10:22:03 EDT 2007 Pekka.Pessi@nokia.com
* su_source.c: refactored initialization/deinitialization
Fri Oct 5 04:58:18 EDT 2007 Pekka Pessi <Pekka.Pessi@nokia.com>
* sip_extra.c: fixed prototypes with isize_t
Fri Oct 5 04:58:45 EDT 2007 Pekka Pessi <Pekka.Pessi@nokia.com>
* test_nta_api.c: removed warnings about signedness
Fri Oct 5 04:59:02 EDT 2007 Pekka Pessi <Pekka.Pessi@nokia.com>
* test_nua_params.c: removed warnings about constness
Fri Oct 5 07:20:26 EDT 2007 Pekka Pessi <first.lastname@nokia.com>
* su_port.h, su_root.c: cleaned argument checking
The su_root_*() and su_port_*() functions now check their arguments once
and do not assert() with NULL arguments. The sur_task->sut_port should
always be valid while su_root_t is alive.
Fri Oct 5 07:22:09 EDT 2007 Pekka Pessi <first.lastname@nokia.com>
* su: added su_root_obtain(), su_root_release() and su_root_has_thread()
When root is created with su_root_create() or cloned with su_clone_start(),
the resulting root is obtained by the calling or created thread,
respectively.
The root can be released with su_root_release() and another thread can
obtain it.
The function su_root_has_thread() can be used to check if a thread has
obtained or released the root.
Implementation upgraded the su_port_own_thread() method as su_port_thread().
Fri Oct 5 07:28:10 EDT 2007 Pekka Pessi <first.lastname@nokia.com>
* su_port.h: removed su_port_threadsafe() and su_port_yield() methods
su_port_wait_events() replaces su_port_yield().
Fri Oct 5 13:26:04 EDT 2007 Pekka Pessi <Pekka.Pessi@nokia.com>
* msg_parser.awk: not extending header structure unless needed.
Removed gawk-ish /* comments */.
Fri Oct 5 14:32:25 EDT 2007 Pekka Pessi <Pekka.Pessi@nokia.com>
* run_test_su: removed GNUisms
Fri Oct 5 14:32:47 EDT 2007 Pekka Pessi <Pekka.Pessi@nokia.com>
* Makefile.am: removed implicit check target test_urlmap
Fri Oct 5 14:22:32 EDT 2007 Pekka Pessi <first.lastname@nokia.com>
* torture_sresolv.c: use CLOCK_REALTIME if no CLOCK_PROCESS_CPUTIME_ID available
Casting timespec tv_sec to unsigned long.
Fri Oct * nua_s added handling nua_prack()
Thanks to Fabio Margarido for the patch.
Mon Oct 8 10:24:35 EDT 2007 Pekka.Pessi@nokia.com
* test_nua: added test for sf.net bug #1803686
Mon Oct 8 08:15:23 EDT 2007 Pekka.Pessi@nokia.com
* RELEASE: updated.
Mon Oct 8 09:30:36 EDT 2007 Pekka.Pessi@nokia.com
* nua_stack: added handling nua_prack()
Thanks to Fabio Margarido for the patch.
Mon Oct 8 10:24:35 EDT 2007 Pekka.Pessi@nokia.com
* test_nua: added test for sf.net bug #1803686
Mon Oct 8 10:26:31 EDT 2007 Pekka.Pessi@nokia.com
* nua: added test for nua_prack() (sf.net bug #1804248)
Avoid sending nua_i_state after nua_prack() if no SDP O/A is happening, too.
Mon Oct 8 10:32:04 EDT 2007 Mikhail Zabaluev <mikhail.zabaluev@nokia.com>
* su_source.c: don t leak the wait arrays
Mon Oct 8 10:37:11 EDT 2007 Pekka.Pessi@nokia.com
* RELEASE: updated
Wed Oct 10 11:55:21 EDT 2007 Pekka.Pessi@nokia.com
* sip_parser.c: silenced warning about extra const in sip_extend_mclass()
Wed Oct 10 11:57:08 EDT 2007 Pekka.Pessi@nokia.com
* nta_tag.c: updated tag documentation
Wed Oct 10 13:16:40 EDT 2007 Pekka.Pessi@nokia.com
* nua: fix logging crash if outbound used with application contact
Silenced warnings.
Wed Oct 10 13:30:45 EDT 2007 Pekka.Pessi@nokia.com
* msg_parser.awk: removed extra "const"
Wed Oct 10 13:31:45 EDT 2007 Pekka.Pessi@nokia.com
* Makefile.am's: fixed distclean of documentation
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@5840 d0543943-73ff-0310-b7d9-9358b9ac24b2
2007-10-11 14:16:59 +00:00
|
|
|
/**@internal
|
2006-12-21 06:30:28 +00:00
|
|
|
* @file stun_mini.c
|
|
|
|
* @brief Minimal stun server
|
|
|
|
*
|
|
|
|
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
|
|
|
* @author Tat Chan <Tat.Chan@nokia.com>
|
|
|
|
* @author Kai Vehmanen <kai.vehmanen@nokia.com>
|
|
|
|
*
|
|
|
|
* @date Created: Fri Oct 3 13:40:41 2003 ppessi
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include "stun_internal.h"
|
|
|
|
|
|
|
|
#include <assert.h>
|
2007-05-09 12:35:53 +00:00
|
|
|
#include <string.h>
|
2007-12-11 10:15:58 +00:00
|
|
|
#include <stdlib.h>
|
2006-12-21 06:30:28 +00:00
|
|
|
|
|
|
|
typedef struct stun_bound_s stun_bound_t;
|
|
|
|
|
|
|
|
struct stun_bound_s
|
|
|
|
{
|
|
|
|
stun_bound_t *ss_next;
|
|
|
|
su_socket_t ss_socket;
|
|
|
|
int ss_scope; /* LI_SCOPE */
|
|
|
|
socklen_t ss_addrlen;
|
|
|
|
union {
|
|
|
|
struct sockaddr_in sin[1];
|
|
|
|
struct sockaddr_storage storage[1];
|
|
|
|
char array[sizeof (struct sockaddr_storage)];
|
|
|
|
} ss_addr;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct stun_mini_s
|
|
|
|
{
|
|
|
|
stun_bound_t *sockets;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int process_3489_request(stun_mini_t *mini,
|
|
|
|
stun_msg_t *request, stun_msg_t *response,
|
|
|
|
su_socket_t socket, void *, socklen_t);
|
|
|
|
|
|
|
|
static int process_bis_request(stun_mini_t *mini,
|
|
|
|
stun_msg_t *request, stun_msg_t *response,
|
|
|
|
su_socket_t socket, void *, socklen_t);
|
|
|
|
|
|
|
|
int send_stun_error(stun_msg_t *response,
|
|
|
|
int error,
|
|
|
|
int socket,
|
|
|
|
void *transaction_id,
|
|
|
|
void *from,
|
|
|
|
socklen_t fromlen);
|
|
|
|
|
|
|
|
/** Create a stun miniserver */
|
|
|
|
stun_mini_t *stun_mini_create(void)
|
|
|
|
{
|
|
|
|
return calloc(1, sizeof (stun_mini_t));
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Destroy a stun miniserver */
|
|
|
|
void stun_mini_destroy(stun_mini_t *mini)
|
|
|
|
{
|
|
|
|
if (mini) {
|
|
|
|
stun_bound_t *ss, **next;
|
|
|
|
for (next = &mini->sockets; *next; ) {
|
|
|
|
ss = *next;
|
|
|
|
*next = ss->ss_next;
|
|
|
|
free(ss);
|
|
|
|
}
|
|
|
|
free(mini);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Add a socket to stun miniserver. */
|
|
|
|
int stun_mini_add_socket(stun_mini_t *mini, su_socket_t socket)
|
|
|
|
{
|
|
|
|
stun_bound_t *ss, **next;
|
|
|
|
struct sockaddr_storage addr[1];
|
|
|
|
socklen_t addrlen = sizeof addr;
|
|
|
|
|
|
|
|
if (mini == NULL)
|
|
|
|
return su_seterrno(EFAULT);
|
|
|
|
|
|
|
|
for (next = &mini->sockets; *next; next = &(*next)->ss_next)
|
|
|
|
if (socket == (*next)->ss_socket)
|
|
|
|
return su_seterrno(EEXIST);
|
|
|
|
|
|
|
|
if (getsockname(socket, (void *)addr, &addrlen) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (addr->ss_family != AF_INET)
|
|
|
|
return su_seterrno(EAFNOSUPPORT);
|
|
|
|
|
|
|
|
ss = calloc(1, offsetof(stun_bound_t, ss_addr.array[addrlen]));
|
|
|
|
|
|
|
|
ss->ss_socket = socket;
|
|
|
|
ss->ss_scope = su_sockaddr_scope((void *)addr, addrlen);
|
|
|
|
|
|
|
|
memcpy(ss->ss_addr.array, addr, ss->ss_addrlen = addrlen);
|
|
|
|
|
|
|
|
*next = ss;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Remove socket from stun miniserver */
|
|
|
|
int stun_mini_remove_socket(stun_mini_t *mini, su_socket_t socket)
|
|
|
|
{
|
|
|
|
stun_bound_t *ss, **next;
|
|
|
|
|
|
|
|
if (mini == NULL)
|
|
|
|
return errno = EFAULT, -1;
|
|
|
|
|
|
|
|
for (next = &mini->sockets; *next; next = &(*next)->ss_next)
|
|
|
|
if (socket == (*next)->ss_socket) {
|
|
|
|
ss = *next;
|
|
|
|
*next = ss->ss_next;
|
|
|
|
free(ss);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return errno = ENOENT, -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void stun_mini_request(stun_mini_t *mini,
|
|
|
|
su_socket_t socket,
|
|
|
|
void *msg, ssize_t msglen,
|
|
|
|
void *from, socklen_t fromlen)
|
|
|
|
{
|
|
|
|
int error;
|
|
|
|
struct {
|
|
|
|
stun_msg_t in[1];
|
|
|
|
stun_msg_t out[1];
|
|
|
|
stun_msg_t error[1];
|
|
|
|
} m;
|
|
|
|
char const *verdict = NULL;
|
|
|
|
uint8_t *data = msg;
|
|
|
|
char buffer[80];
|
|
|
|
uint8_t const magic_cookie[4] = { 0x21, 0x12, 0xA4, 0x42 };
|
|
|
|
|
|
|
|
memset(&m, 0, sizeof m);
|
|
|
|
|
|
|
|
if (mini == NULL || msg == NULL || from == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (msglen < 20)
|
|
|
|
verdict = "runt";
|
|
|
|
else if (data[0] == 1)
|
|
|
|
verdict = "response";
|
|
|
|
else if (data[0] != 0)
|
|
|
|
verdict = "garbage";
|
|
|
|
else if (data[1] == 2)
|
|
|
|
verdict = "shared secret request";
|
|
|
|
else if (data[1] != 1)
|
|
|
|
verdict = "garbage";
|
|
|
|
|
|
|
|
{
|
|
|
|
struct sockaddr_in const *sin = from;
|
|
|
|
|
|
|
|
if (sin->sin_family == AF_INET)
|
|
|
|
inet_ntop(sin->sin_family, &sin->sin_addr, buffer, sizeof buffer);
|
|
|
|
else
|
|
|
|
sprintf(buffer, "<af=%u>", (unsigned)sin->sin_family);
|
|
|
|
|
|
|
|
fprintf(stderr, "stun %s from %s:%u\n",
|
|
|
|
verdict ? verdict : "request", buffer, ntohs(sin->sin_port));
|
|
|
|
|
|
|
|
if (verdict)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m.in->enc_buf.data = msg;
|
|
|
|
m.in->enc_buf.size = msglen;
|
|
|
|
|
|
|
|
if (memcmp(data + 4, magic_cookie, sizeof magic_cookie) == 0)
|
|
|
|
error = process_3489_request(mini, m.in, m.out, socket, from, fromlen);
|
|
|
|
else
|
|
|
|
error = process_bis_request(mini, m.in, m.out, socket, from, fromlen);
|
|
|
|
|
|
|
|
if (error)
|
|
|
|
send_stun_error(m.error, error, socket, data + 4, from, fromlen);
|
|
|
|
|
|
|
|
m.in->enc_buf.data = NULL;
|
|
|
|
|
|
|
|
stun_free_message(m.in);
|
|
|
|
stun_free_message(m.out);
|
|
|
|
stun_free_message(m.error);
|
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
int process_3489_request(stun_mini_t *mini,
|
|
|
|
stun_msg_t *request,
|
|
|
|
stun_msg_t *response,
|
|
|
|
su_socket_t socket,
|
|
|
|
void *from,
|
|
|
|
socklen_t fromlen)
|
|
|
|
{
|
|
|
|
stun_bound_t *ss, *changed = NULL, ss0[1];
|
|
|
|
stun_attr_t *a, **next;
|
|
|
|
stun_attr_sockaddr_t *addr;
|
|
|
|
int change_address = 0;
|
|
|
|
|
|
|
|
if (stun_parse_message(request) < 0) {
|
|
|
|
fprintf(stderr, "stun: error parsing request\n");
|
|
|
|
return STUN_400_BAD_REQUEST;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (request->stun_hdr.msg_type != BINDING_REQUEST) {
|
|
|
|
fprintf(stderr, "stun: not binding request\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
a = stun_get_attr(request->stun_attr, RESPONSE_ADDRESS);
|
|
|
|
if (a)
|
|
|
|
return STUN_600_GLOBAL_FAILURE;
|
|
|
|
|
|
|
|
/* compose header */
|
|
|
|
response->stun_hdr.msg_type = BINDING_RESPONSE;
|
|
|
|
memcpy(response->stun_hdr.tran_id, request->stun_hdr.tran_id,
|
|
|
|
sizeof response->stun_hdr.tran_id);
|
|
|
|
|
|
|
|
next = &response->stun_attr;
|
|
|
|
|
|
|
|
/* MAPPED-ADDRESS */
|
|
|
|
a = malloc(sizeof *a); if (!a) return STUN_500_SERVER_ERROR;
|
|
|
|
a->attr_type = MAPPED_ADDRESS;
|
|
|
|
addr = malloc(sizeof *addr); if (!addr) return STUN_500_SERVER_ERROR;
|
|
|
|
memcpy(addr, from, sizeof *addr);
|
|
|
|
a->pattr = addr;
|
|
|
|
a->next = NULL;
|
|
|
|
*next = a; next = &a->next;
|
|
|
|
|
|
|
|
/* SOURCE-ADDRESS */ /* depends on CHANGE_REQUEST */
|
|
|
|
a = stun_get_attr(request->stun_attr, CHANGE_REQUEST);
|
|
|
|
if (a)
|
|
|
|
change_address = ((stun_attr_changerequest_t *)a->pattr)->value;
|
|
|
|
|
|
|
|
if (change_address) {
|
|
|
|
struct sockaddr_in const *sin, *sin2;
|
|
|
|
int scope = su_sockaddr_scope(from, fromlen);
|
|
|
|
stun_bound_t *changed_ip = NULL, *same_scope = NULL;
|
|
|
|
|
|
|
|
sin = from;
|
|
|
|
|
|
|
|
for (changed = mini->sockets; changed; changed = changed->ss_next) {
|
|
|
|
sin2 = changed->ss_addr.sin;
|
|
|
|
|
|
|
|
if (scope != LI_SCOPE_HOST && changed->ss_scope == LI_SCOPE_HOST)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (scope != LI_SCOPE_SITE && changed->ss_scope == LI_SCOPE_SITE)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (same_scope == NULL)
|
|
|
|
same_scope = changed;
|
|
|
|
|
|
|
|
if (change_address & STUN_CR_CHANGE_IP)
|
|
|
|
if (!memcmp(&sin->sin_addr, &sin2->sin_addr, sizeof sin->sin_addr))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (changed_ip == NULL)
|
|
|
|
changed_ip = changed;
|
|
|
|
|
|
|
|
if (change_address & STUN_CR_CHANGE_PORT)
|
|
|
|
if (sin->sin_port == sin2->sin_port)
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (changed == NULL && (change_address & STUN_CR_CHANGE_IP))
|
|
|
|
/* We don't have socekt with both changed port and ip */
|
|
|
|
changed = changed_ip;
|
|
|
|
|
|
|
|
if (changed == NULL)
|
|
|
|
changed = same_scope;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (ss = mini->sockets; ss; ss = ss->ss_next)
|
|
|
|
if (socket == ss->ss_socket)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (ss == NULL) {
|
|
|
|
memset(ss = ss0, 0, sizeof ss0);
|
|
|
|
ss->ss_socket = socket;
|
|
|
|
ss->ss_addrlen = sizeof ss->ss_addr;
|
|
|
|
if (getsockname(socket, (void *)ss->ss_addr.array, &ss->ss_addrlen) < 0)
|
|
|
|
return STUN_500_SERVER_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
a = malloc(sizeof *a); if (!a) return STUN_500_SERVER_ERROR;
|
|
|
|
a->attr_type = SOURCE_ADDRESS;
|
|
|
|
addr = malloc(sizeof *addr); if (!addr) return STUN_500_SERVER_ERROR;
|
|
|
|
memcpy(addr, ss->ss_addr.array, sizeof *addr);
|
|
|
|
a->pattr = addr;
|
|
|
|
a->next = NULL;
|
|
|
|
*next = a; next = &(a->next);
|
|
|
|
|
|
|
|
if (changed) {
|
|
|
|
socket = changed->ss_socket;
|
|
|
|
|
|
|
|
/* CHANGED-ADDRESS */
|
|
|
|
a = malloc(sizeof *a); if (!a) return STUN_500_SERVER_ERROR;
|
|
|
|
a->attr_type = CHANGED_ADDRESS;
|
|
|
|
addr = malloc(sizeof *addr); if (!addr) return STUN_500_SERVER_ERROR;
|
|
|
|
memcpy(addr, changed->ss_addr.array, sizeof *addr);
|
|
|
|
|
|
|
|
a->pattr = addr;
|
|
|
|
a->next = NULL;
|
|
|
|
*next = a; next = &(a->next);
|
|
|
|
}
|
|
|
|
|
|
|
|
stun_send_message(socket, (void *)from, response, NULL);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int process_bis_request(stun_mini_t *mini,
|
|
|
|
stun_msg_t *request, stun_msg_t *response,
|
|
|
|
su_socket_t socket,
|
|
|
|
void *from, socklen_t fromlen)
|
|
|
|
{
|
|
|
|
return process_3489_request(mini, request, response, socket, from, fromlen);
|
|
|
|
}
|
|
|
|
|
|
|
|
int send_stun_error(stun_msg_t *response,
|
|
|
|
int error,
|
|
|
|
int socket,
|
|
|
|
void *transaction_id,
|
|
|
|
void *from,
|
|
|
|
socklen_t fromlen)
|
|
|
|
{
|
|
|
|
stun_attr_t *attr;
|
|
|
|
stun_attr_errorcode_t *errorcode;
|
|
|
|
char const *phrase = stun_response_phrase(error);
|
|
|
|
|
|
|
|
if (!phrase)
|
|
|
|
error = STUN_500_SERVER_ERROR, phrase = "Internal Server Error";
|
|
|
|
|
|
|
|
stun_init_message(response);
|
|
|
|
|
|
|
|
response->stun_hdr.msg_type = BINDING_ERROR_RESPONSE;
|
|
|
|
response->stun_hdr.msg_len = 0; /* actual len computed later */
|
|
|
|
|
|
|
|
memcpy(response->stun_hdr.tran_id, transaction_id, 16);
|
|
|
|
|
|
|
|
/* ERROR-CODE */
|
|
|
|
attr = malloc(sizeof *attr); if (!attr) return -1;
|
|
|
|
response->stun_attr = attr;
|
|
|
|
attr->attr_type = ERROR_CODE;
|
|
|
|
|
|
|
|
errorcode = malloc(sizeof(*errorcode));
|
|
|
|
if (!errorcode)
|
|
|
|
return -1;
|
|
|
|
errorcode->code = error;
|
|
|
|
errorcode->phrase = malloc(strlen(phrase) + 1);
|
|
|
|
if (!errorcode->phrase)
|
|
|
|
return -1;
|
|
|
|
strcpy(errorcode->phrase, phrase);
|
|
|
|
attr->pattr = errorcode;
|
|
|
|
|
|
|
|
stun_send_message(socket, from, response, NULL);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|