summaryrefslogtreecommitdiffstats
path: root/tinyNET/src/tnet_nat.c
diff options
context:
space:
mode:
Diffstat (limited to 'tinyNET/src/tnet_nat.c')
-rwxr-xr-xtinyNET/src/tnet_nat.c380
1 files changed, 189 insertions, 191 deletions
diff --git a/tinyNET/src/tnet_nat.c b/tinyNET/src/tnet_nat.c
index 53a009a..7e536c1 100755
--- a/tinyNET/src/tnet_nat.c
+++ b/tinyNET/src/tnet_nat.c
@@ -7,12 +7,12 @@
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
-*
+*
* DOUBANGO 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 General Public License for more details.
-*
+*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
@@ -40,24 +40,23 @@
/**@defgroup tnet_nat_group NAT Traversal API (STUN, TURN and ICE).
*/
-typedef struct tnet_nat_ctx_s
-{
- TSK_DECLARE_OBJECT;
+typedef struct tnet_nat_ctx_s {
+ TSK_DECLARE_OBJECT;
- tnet_socket_type_t socket_type;
+ tnet_socket_type_t socket_type;
- char* username; /**< The username to use to authenticate against the TURN/STUN server. */
- char* password; /**< The password to use to authenticate against the TURN/STUN server. */
+ char* username; /**< The username to use to authenticate against the TURN/STUN server. */
+ char* password; /**< The password to use to authenticate against the TURN/STUN server. */
- char* server_address; /**< TURN/STUN server address (could be FQDN or IP) */
- tnet_port_t server_port; /**< TURN/STUN server port. */
+ char* server_address; /**< TURN/STUN server address (could be FQDN or IP) */
+ tnet_port_t server_port; /**< TURN/STUN server port. */
- uint16_t RTO; /**< Estimate of the round-trip time (RTT) in millisecond. */
- uint16_t Rc; /**< Number of retransmissions for UDP in millisecond. */
+ uint16_t RTO; /**< Estimate of the round-trip time (RTT) in millisecond. */
+ uint16_t Rc; /**< Number of retransmissions for UDP in millisecond. */
- unsigned use_dnsquery:1; /**< Indicates whether to use DNS SRV query to find the stun/turn ip address. */
-
- tnet_stun_bindings_L_t *stun_bindings; /**< List of all STUN2 bindings associated to this context. */
+ unsigned use_dnsquery:1; /**< Indicates whether to use DNS SRV query to find the stun/turn ip address. */
+
+ tnet_stun_bindings_L_t *stun_bindings; /**< List of all STUN2 bindings associated to this context. */
}
tnet_nat_ctx_t;
@@ -67,88 +66,88 @@ tnet_nat_ctx_t;
*/
struct tnet_nat_ctx_s* tnet_nat_context_create(tnet_socket_type_t socket_type, const char* pc_username, const char* pc_password)
{
- extern const tsk_object_def_t *tnet_nat_context_def_t;
- struct tnet_nat_ctx_s* p_ctx;
-
- if (!(p_ctx = tsk_object_new(tnet_nat_context_def_t)) || !(p_ctx->stun_bindings = tsk_list_create())) {
- TSK_OBJECT_SAFE_FREE(p_ctx);
- TSK_DEBUG_ERROR("Failed to create NAT context");
- return tsk_null;
- }
-
- p_ctx->socket_type = socket_type;
- p_ctx->username = tsk_strdup(pc_username);
- p_ctx->password = tsk_strdup(pc_password);
- p_ctx->server_port = kStunPortDefaultTcpUdp;
- /* 7.2.1. Sending over UDP
- In fixed-line access links, a value of 500 ms is RECOMMENDED.
- */
- p_ctx->RTO = kStunRTO;
- /* 7.2.1. Sending over UDP
- Rc SHOULD be configurable and SHOULD have a default of 7.
- */
- p_ctx->Rc = kStunRC;
-
- return p_ctx;
+ extern const tsk_object_def_t *tnet_nat_context_def_t;
+ struct tnet_nat_ctx_s* p_ctx;
+
+ if (!(p_ctx = tsk_object_new(tnet_nat_context_def_t)) || !(p_ctx->stun_bindings = tsk_list_create())) {
+ TSK_OBJECT_SAFE_FREE(p_ctx);
+ TSK_DEBUG_ERROR("Failed to create NAT context");
+ return tsk_null;
+ }
+
+ p_ctx->socket_type = socket_type;
+ p_ctx->username = tsk_strdup(pc_username);
+ p_ctx->password = tsk_strdup(pc_password);
+ p_ctx->server_port = kStunPortDefaultTcpUdp;
+ /* 7.2.1. Sending over UDP
+ In fixed-line access links, a value of 500 ms is RECOMMENDED.
+ */
+ p_ctx->RTO = kStunRTO;
+ /* 7.2.1. Sending over UDP
+ Rc SHOULD be configurable and SHOULD have a default of 7.
+ */
+ p_ctx->Rc = kStunRC;
+
+ return p_ctx;
}
-/** Predicate function to find stun binding by id.
+/** Predicate function to find stun binding by id.
*
- * @param [in,out] item The current list item.
- * @param [in,out] id A pointer to the binding identifier.
+ * @param [in,out] item The current list item.
+ * @param [in,out] id A pointer to the binding identifier.
*
- * @return Zero if current list item hold a binding with the same id and -1 otherwise.
+ * @return Zero if current list item hold a binding with the same id and -1 otherwise.
**/
int __pred_find_stun_binding(const tsk_list_item_t* item, const void* id)
{
- if(item) {
- tnet_stun_binding_t *p_bind = item->data;
- if (p_bind) {
- tnet_stun_binding_id_t binding_id = *((tnet_stun_binding_id_t*)id);
- return (p_bind->id == binding_id) ? 0 : -1;
- }
- }
- return -1;
+ if(item) {
+ tnet_stun_binding_t *p_bind = item->data;
+ if (p_bind) {
+ tnet_stun_binding_id_t binding_id = *((tnet_stun_binding_id_t*)id);
+ return (p_bind->id == binding_id) ? 0 : -1;
+ }
+ }
+ return -1;
}
/**@ingroup tnet_nat_group
*
* Sets the address of the STUN/TURN server.
*
- * @param [in,out] p_self The NAT context.
- * @param [in,out] pc_server_address The address of server.
+ * @param [in,out] p_self The NAT context.
+ * @param [in,out] pc_server_address The address of server.
*
- * @return Zero if succeed and non zero error code otherwise.
+ * @return Zero if succeed and non zero error code otherwise.
**/
int tnet_nat_set_server_address(struct tnet_nat_ctx_s* p_self, const char* pc_server_address)
{
- if (!p_self) {
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
- tsk_strupdate(&(p_self->server_address), pc_server_address);
- return 0;
+ if (!p_self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ tsk_strupdate(&(p_self->server_address), pc_server_address);
+ return 0;
}
/**@ingroup tnet_nat_group
*
* Sets the address and port of the STUN/TURN server.
*
- * @param [in,out] p_self The NAT context.
- * @param [in,out] pc_server_address The address of server.
- * @param u_server_port The server port.
+ * @param [in,out] p_self The NAT context.
+ * @param [in,out] pc_server_address The address of server.
+ * @param u_server_port The server port.
*
- * @return Zero if succeed and non zero error code otherwise.
+ * @return Zero if succeed and non zero error code otherwise.
**/
int tnet_nat_set_server(struct tnet_nat_ctx_s* p_self, const char* pc_server_address, tnet_port_t u_server_port)
{
- if (!p_self) {
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
- tsk_strupdate(&(p_self->server_address), pc_server_address);
- p_self->server_port = u_server_port;
- return 0;
+ if (!p_self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ tsk_strupdate(&(p_self->server_address), pc_server_address);
+ p_self->server_port = u_server_port;
+ return 0;
}
/**@ingroup tnet_nat_group
@@ -156,7 +155,7 @@ int tnet_nat_set_server(struct tnet_nat_ctx_s* p_self, const char* pc_server_add
* Creates and sends a STUN2 binding request to the STUN/TURN server in order to get the server reflexive
* address associated to this file descriptor (or socket). The caller should call @ref tnet_nat_stun_unbind to destroy the binding.
*
- * @param [in,out] p_self The NAT context.
+ * @param [in,out] p_self The NAT context.
* @param localFD The local file descriptor (or socket) for which to get the reflexive server address.
*
* @return A valid binding id if succeed and @ref kStunBindingInvalidId otherwise. If the returned id is valid then
@@ -166,13 +165,13 @@ int tnet_nat_set_server(struct tnet_nat_ctx_s* p_self, const char* pc_server_add
**/
tnet_stun_binding_id_t tnet_nat_stun_bind(const struct tnet_nat_ctx_s* p_self, const tnet_fd_t localFD)
{
- tnet_stun_binding_id_t id = kStunBindingInvalidId;
- tnet_stun_binding_t *p_binding = tsk_null;
- int ret;
- if (!p_self || localFD == TNET_INVALID_FD) {
- TSK_DEBUG_ERROR("Invalid parameter");
- goto bail;
- }
+ tnet_stun_binding_id_t id = kStunBindingInvalidId;
+ tnet_stun_binding_t *p_binding = tsk_null;
+ int ret;
+ if (!p_self || localFD == TNET_INVALID_FD) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ goto bail;
+ }
if ((ret = tnet_stun_binding_create(localFD, p_self->socket_type, p_self->server_address, p_self->server_port, p_self->username, p_self->password, &p_binding))) {
goto bail;
}
@@ -183,7 +182,7 @@ tnet_stun_binding_id_t tnet_nat_stun_bind(const struct tnet_nat_ctx_s* p_self, c
tsk_list_push_back_data(p_self->stun_bindings, (void**)&p_binding);
bail:
- TSK_OBJECT_SAFE_FREE(p_binding);
+ TSK_OBJECT_SAFE_FREE(p_binding);
return id;
}
@@ -198,19 +197,19 @@ bail:
**/
int tnet_nat_stun_send_bind(const struct tnet_nat_ctx_s* pc_self, struct tnet_stun_binding_s *p_binding)
{
- int ret = -1;
+ int ret = -1;
tnet_stun_pkt_resp_t *p_pkt_resp = tsk_null;
tnet_stun_pkt_req_t *p_pkt_req = tsk_null;
- if (!pc_self || !p_binding) {
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
+ if (!pc_self || !p_binding) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
- if (!TNET_SOCKET_TYPE_IS_DGRAM(p_binding->socket_type)) {
- TSK_DEBUG_ERROR("Only DGRAM could be used for STUN transport");
- return -2;
- }
+ if (!TNET_SOCKET_TYPE_IS_DGRAM(p_binding->socket_type)) {
+ TSK_DEBUG_ERROR("Only DGRAM could be used for STUN transport");
+ return -2;
+ }
if ((ret = tnet_stun_binding_create_req(p_binding, &p_pkt_req))) {
goto bail;
@@ -225,51 +224,51 @@ int tnet_nat_stun_send_bind(const struct tnet_nat_ctx_s* pc_self, struct tnet_st
authentication or message integrity applied.
*/
stun_phase0: {
- if ((ret = tnet_stun_utils_send_unreliably(p_binding->localFD, pc_self->RTO, pc_self->Rc, p_pkt_req, (struct sockaddr*)&p_binding->addr_server, &p_pkt_resp))) {
- goto bail;
- }
+ if ((ret = tnet_stun_utils_send_unreliably(p_binding->localFD, pc_self->RTO, pc_self->Rc, p_pkt_req, (struct sockaddr*)&p_binding->addr_server, &p_pkt_resp))) {
+ goto bail;
+ }
if (p_pkt_resp) {
if (TNET_STUN_PKT_RESP_IS_ERROR(p_pkt_resp)) {
- uint16_t u_code;
- if ((ret = tnet_stun_pkt_get_errorcode(p_pkt_resp, &u_code))) {
- goto bail;
- }
- if (u_code == kStunErrCodeUnauthorized || u_code == kStunErrCodeStaleNonce) {
- if (u_code == kStunErrCodeUnauthorized) {
- // Make sure this is not an authentication failure (#2 401)
- // Do not send another req to avoid endless messages
- if ((tnet_stun_pkt_attr_exists(p_pkt_req, tnet_stun_attr_type_message_integrity))) { // already has a MESSAGE-INTEGRITY?
- TSK_DEBUG_ERROR("STUN authentication failed");
- goto bail;
- }
- }
- if ((ret = tnet_stun_pkt_auth_prepare_2(p_pkt_req, p_binding->p_username, p_binding->p_password, p_pkt_resp))) {
- goto bail;
- }
- // Try to send again now that authinfo is up2date
- goto stun_phase0;
- }
- else if (u_code == kStunErrCodeUnknownAttributes) {
- if((ret = tnet_stun_pkt_process_err420(p_pkt_req, p_pkt_resp))) {
- goto bail;
- }
- // Try to send again now that authinfo is up2date
- goto stun_phase0;
- }
- ret = -3;
+ uint16_t u_code;
+ if ((ret = tnet_stun_pkt_get_errorcode(p_pkt_resp, &u_code))) {
+ goto bail;
+ }
+ if (u_code == kStunErrCodeUnauthorized || u_code == kStunErrCodeStaleNonce) {
+ if (u_code == kStunErrCodeUnauthorized) {
+ // Make sure this is not an authentication failure (#2 401)
+ // Do not send another req to avoid endless messages
+ if ((tnet_stun_pkt_attr_exists(p_pkt_req, tnet_stun_attr_type_message_integrity))) { // already has a MESSAGE-INTEGRITY?
+ TSK_DEBUG_ERROR("STUN authentication failed");
+ goto bail;
+ }
+ }
+ if ((ret = tnet_stun_pkt_auth_prepare_2(p_pkt_req, p_binding->p_username, p_binding->p_password, p_pkt_resp))) {
+ goto bail;
+ }
+ // Try to send again now that authinfo is up2date
+ goto stun_phase0;
+ }
+ else if (u_code == kStunErrCodeUnknownAttributes) {
+ if((ret = tnet_stun_pkt_process_err420(p_pkt_req, p_pkt_resp))) {
+ goto bail;
+ }
+ // Try to send again now that authinfo is up2date
+ goto stun_phase0;
+ }
+ ret = -3;
}
else {
- const tnet_stun_attr_address_t* pc_addr;
- if ((ret = tnet_stun_pkt_attr_find_first(p_pkt_resp, tnet_stun_attr_type_xor_mapped_address, (const tnet_stun_attr_t**)&pc_addr)) == 0 && pc_addr) {
- TSK_OBJECT_SAFE_FREE(p_binding->p_xmaddr);
- p_binding->p_xmaddr = tsk_object_ref(TSK_OBJECT(pc_addr));
- }
- if ((ret = tnet_stun_pkt_attr_find_first(p_pkt_resp, tnet_stun_attr_type_mapped_address, (const tnet_stun_attr_t**)&pc_addr)) == 0 && pc_addr) {
- TSK_OBJECT_SAFE_FREE(p_binding->p_maddr);
- p_binding->p_maddr = tsk_object_ref(TSK_OBJECT(pc_addr));
- }
- }
+ const tnet_stun_attr_address_t* pc_addr;
+ if ((ret = tnet_stun_pkt_attr_find_first(p_pkt_resp, tnet_stun_attr_type_xor_mapped_address, (const tnet_stun_attr_t**)&pc_addr)) == 0 && pc_addr) {
+ TSK_OBJECT_SAFE_FREE(p_binding->p_xmaddr);
+ p_binding->p_xmaddr = tsk_object_ref(TSK_OBJECT(pc_addr));
+ }
+ if ((ret = tnet_stun_pkt_attr_find_first(p_pkt_resp, tnet_stun_attr_type_mapped_address, (const tnet_stun_attr_t**)&pc_addr)) == 0 && pc_addr) {
+ TSK_OBJECT_SAFE_FREE(p_binding->p_maddr);
+ p_binding->p_maddr = tsk_object_ref(TSK_OBJECT(pc_addr));
+ }
+ }
}
}
/* END OF stun_phase0 */
@@ -285,51 +284,51 @@ bail:
* Gets the server reflexive address associated to this STUN2 binding.
*
*
- * @param [in,out] p_self The NAT context.
- * @param id The id of the STUN2 binding conetxt (obtained using @ref tnet_nat_stun_bind) holding the server-reflexive address.
- * @param [in,out] pp_ip The reflexive IP address. It is up the the caller to free the returned string
- * @param [in,out] pu_port The reflexive port.
+ * @param [in,out] p_self The NAT context.
+ * @param id The id of the STUN2 binding conetxt (obtained using @ref tnet_nat_stun_bind) holding the server-reflexive address.
+ * @param [in,out] pp_ip The reflexive IP address. It is up the the caller to free the returned string
+ * @param [in,out] pu_port The reflexive port.
*
- * @return Zero if succeed and non zero error code otherwise.
+ * @return Zero if succeed and non zero error code otherwise.
**/
int tnet_nat_stun_get_reflexive_address(const struct tnet_nat_ctx_s* p_self, tnet_stun_binding_id_t id, char** pp_ip, tnet_port_t *pu_port)
{
- const tsk_list_item_t* item;
- if (!p_self) {
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
- if (!pp_ip && !pu_port) {
- return 0;
- }
-
- if ((item = tsk_list_find_item_by_pred(p_self->stun_bindings, __pred_find_stun_binding, &id)) && item->data) {
- const tnet_stun_binding_t *pc_bind = (const tnet_stun_binding_t *)item->data;
- const struct tnet_stun_attr_address_s *pc_addr = pc_bind->p_xmaddr ? pc_bind->p_xmaddr : pc_bind->p_maddr;
- if (pc_addr) {
- tnet_ip_t ip;
- int ret;
- if ((ret = tnet_stun_utils_inet_ntop((pc_addr->e_family == tnet_stun_address_family_ipv6), &pc_addr->address, &ip))) {
- return ret;
- }
- if (pp_ip) {
- tsk_strupdate(pp_ip, ip);
- }
- if (pu_port) {
- *pu_port = pc_addr->u_port;
- }
- return 0;
- }
- }
- return -2;
+ const tsk_list_item_t* item;
+ if (!p_self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if (!pp_ip && !pu_port) {
+ return 0;
+ }
+
+ if ((item = tsk_list_find_item_by_pred(p_self->stun_bindings, __pred_find_stun_binding, &id)) && item->data) {
+ const tnet_stun_binding_t *pc_bind = (const tnet_stun_binding_t *)item->data;
+ const struct tnet_stun_attr_address_s *pc_addr = pc_bind->p_xmaddr ? pc_bind->p_xmaddr : pc_bind->p_maddr;
+ if (pc_addr) {
+ tnet_ip_t ip;
+ int ret;
+ if ((ret = tnet_stun_utils_inet_ntop((pc_addr->e_family == tnet_stun_address_family_ipv6), &pc_addr->address, &ip))) {
+ return ret;
+ }
+ if (pp_ip) {
+ tsk_strupdate(pp_ip, ip);
+ }
+ if (pu_port) {
+ *pu_port = pc_addr->u_port;
+ }
+ return 0;
+ }
+ }
+ return -2;
}
/**@ingroup tnet_nat_group
*
* Removes a STUN2 binding from the NAT context.
*
- * @param [in,out] p_self The NAT context from which to remove the STUN2 binding.
- * @param id The id of the STUN2 binding to remove.
+ * @param [in,out] p_self The NAT context from which to remove the STUN2 binding.
+ * @param id The id of the STUN2 binding to remove.
*
* @return Zero if succeed and non zero error code otherwise.
*
@@ -338,12 +337,12 @@ int tnet_nat_stun_get_reflexive_address(const struct tnet_nat_ctx_s* p_self, tne
**/
int tnet_nat_stun_unbind(const struct tnet_nat_ctx_s* p_self, tnet_stun_binding_id_t id)
{
- if (!p_self) {
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
- tsk_list_remove_item_by_pred(p_self->stun_bindings, __pred_find_stun_binding, &id);
- return 0;
+ if (!p_self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ tsk_list_remove_item_by_pred(p_self->stun_bindings, __pred_find_stun_binding, &id);
+ return 0;
}
@@ -352,30 +351,29 @@ int tnet_nat_stun_unbind(const struct tnet_nat_ctx_s* p_self, tnet_stun_binding_
//
static tsk_object_t* tnet_nat_context_ctor(tsk_object_t * self, va_list * app)
{
- tnet_nat_ctx_t *p_ctx = (tnet_nat_ctx_t*)self;
- if (p_ctx) {
- }
- return self;
+ tnet_nat_ctx_t *p_ctx = (tnet_nat_ctx_t*)self;
+ if (p_ctx) {
+ }
+ return self;
}
static tsk_object_t* tnet_nat_context_dtor(tsk_object_t * self)
-{
- tnet_nat_ctx_t *p_ctx = (tnet_nat_ctx_t*)self;
- if (p_ctx) {
- TSK_FREE(p_ctx->username);
- TSK_FREE(p_ctx->password);
- TSK_FREE(p_ctx->server_address);
-
- TSK_OBJECT_SAFE_FREE(p_ctx->stun_bindings);
- TSK_DEBUG_INFO("*** NAT context destroyed ***");
- }
-
- return self;
-}
-static const tsk_object_def_t tnet_nat_context_def_s =
{
- sizeof(tnet_nat_ctx_t),
- tnet_nat_context_ctor,
- tnet_nat_context_dtor,
- tsk_null,
+ tnet_nat_ctx_t *p_ctx = (tnet_nat_ctx_t*)self;
+ if (p_ctx) {
+ TSK_FREE(p_ctx->username);
+ TSK_FREE(p_ctx->password);
+ TSK_FREE(p_ctx->server_address);
+
+ TSK_OBJECT_SAFE_FREE(p_ctx->stun_bindings);
+ TSK_DEBUG_INFO("*** NAT context destroyed ***");
+ }
+
+ return self;
+}
+static const tsk_object_def_t tnet_nat_context_def_s = {
+ sizeof(tnet_nat_ctx_t),
+ tnet_nat_context_ctor,
+ tnet_nat_context_dtor,
+ tsk_null,
};
const tsk_object_def_t *tnet_nat_context_def_t = &tnet_nat_context_def_s;
OpenPOWER on IntegriCloud