From 3c40c14f40b1f382e7fac9dff548865358cd8655 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 31 Jan 2015 23:25:45 +0000 Subject: [PATCH] working on new dual-allocation implementation --- ChangeLog | 2 + TODO | 4 +- src/apps/common/stun_buffer.c | 4 +- src/apps/common/stun_buffer.h | 2 +- src/apps/uclient/mainuclient.c | 4 ++ src/apps/uclient/startuclient.c | 25 +++---- src/client++/TurnMsgLib.h | 4 +- src/client/ns_turn_msg.c | 109 +++++++++++++++++++++++------- src/client/ns_turn_msg.h | 5 +- src/client/ns_turn_msg_defs.h | 6 +- src/client/ns_turn_msg_defs_new.h | 5 ++ src/server/ns_turn_server.c | 45 +++++++++--- 12 files changed, 155 insertions(+), 60 deletions(-) diff --git a/ChangeLog b/ChangeLog index 11674133..889630d9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,8 @@ 1/31/2015 Oleg Moskalenko Version 4.4.1.2 'Ardee West': - hostname-to-IP-address resolution fix; + - SSODA updates according to turnbis specs; + - TRANSPORT attribute handling fixed; 1/24/2015 Oleg Moskalenko Version 4.4.1.1 'Ardee West': diff --git a/TODO b/TODO index 5fe9a166..cc38d831 100644 --- a/TODO +++ b/TODO @@ -4,7 +4,7 @@ ================================================================== -1) Fedora official package (turnserver or coturn ? TBD). +1) Fedora official package. 2) MS Windows support. @@ -90,7 +90,7 @@ ================================================================== -nope +1) Peer for TCP relay. ================================================================== diff --git a/src/apps/common/stun_buffer.c b/src/apps/common/stun_buffer.c index 09990e65..c4ee5754 100644 --- a/src/apps/common/stun_buffer.c +++ b/src/apps/common/stun_buffer.c @@ -153,8 +153,8 @@ int stun_is_channel_message(stun_buffer* buf, u16bits* chnumber, int is_padding_ /////////////////////////////////////////////////////////////////////////////// -int stun_set_allocate_request(stun_buffer* buf, u32bits lifetime, int af4, int af6, u08bits transport, int mobile) { - return stun_set_allocate_request_str(buf->buf, (size_t*)(&(buf->len)), lifetime, af4, af6, transport, mobile); +int stun_set_allocate_request(stun_buffer* buf, u32bits lifetime, int af4, int af6, u08bits transport, int mobile, const char *rt, int ep) { + return stun_set_allocate_request_str(buf->buf, (size_t*)(&(buf->len)), lifetime, af4, af6, transport, mobile, rt, ep); } int stun_set_allocate_response(stun_buffer* buf, stun_tid* tid, diff --git a/src/apps/common/stun_buffer.h b/src/apps/common/stun_buffer.h index 0d3e3608..fe7dc256 100644 --- a/src/apps/common/stun_buffer.h +++ b/src/apps/common/stun_buffer.h @@ -101,7 +101,7 @@ int stun_is_channel_message(stun_buffer* buf, u16bits* chnumber, int is_padding_ /////////////////////////////////////////////////////////////// -int stun_set_allocate_request(stun_buffer* buf, u32bits lifetime, int af4, int af6, u08bits transport, int mobile); +int stun_set_allocate_request(stun_buffer* buf, u32bits lifetime, int af4, int af6, u08bits transport, int mobile, const char* rt, int ep); int stun_set_allocate_response(stun_buffer* buf, stun_tid* tid, const ioa_addr *relayed_addr1, const ioa_addr *relayed_addr2, const ioa_addr *reflexive_addr, diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index 3c7fa867..a794323b 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -392,6 +392,10 @@ int main(int argc, char **argv) } } + if(dual_allocation) { + no_rtcp = 1; + } + if(g_use_auth_secret_with_timestamp) { { diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index 54da33c6..8019df82 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -370,39 +370,30 @@ static int clnet_allocate(int verbose, reopen_socket = 0; } - if(current_reservation_token) { - af = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT; - } - int af4 = dual_allocation || (af == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4); int af6 = dual_allocation || (af == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6); + uint64_t reservation_token = 0; + char* rt = NULL; + int ep = !no_rtcp; + if(!no_rtcp) { if (!never_allocate_rtcp && allocate_rtcp) { - af4 = 0; - af6 = 0; + reservation_token = ioa_ntoh64(current_reservation_token); + rt = (char*) (&reservation_token); } } if(!dos) - stun_set_allocate_request(&request_message, UCLIENT_SESSION_LIFETIME, af4, af6, relay_transport, mobility); + stun_set_allocate_request(&request_message, UCLIENT_SESSION_LIFETIME, af4, af6, relay_transport, mobility, rt, ep); else - stun_set_allocate_request(&request_message, UCLIENT_SESSION_LIFETIME/3, af4, af6, relay_transport, mobility); + stun_set_allocate_request(&request_message, UCLIENT_SESSION_LIFETIME/3, af4, af6, relay_transport, mobility, rt, ep); if(bps) stun_attr_add_bandwidth_str(request_message.buf, (size_t*)(&(request_message.len)), bps); if(dont_fragment) stun_attr_add(&request_message, STUN_ATTRIBUTE_DONT_FRAGMENT, NULL, 0); - if(!no_rtcp) { - if (!never_allocate_rtcp && allocate_rtcp) { - uint64_t reservation_token = ioa_ntoh64(current_reservation_token); - stun_attr_add(&request_message, STUN_ATTRIBUTE_RESERVATION_TOKEN, - (char*) (&reservation_token), 8); - } else { - stun_attr_add_even_port(&request_message, 1); - } - } add_origin(&request_message); diff --git a/src/client++/TurnMsgLib.h b/src/client++/TurnMsgLib.h index 008bbc05..a0332927 100644 --- a/src/client++/TurnMsgLib.h +++ b/src/client++/TurnMsgLib.h @@ -849,8 +849,8 @@ public: /** * Construct allocate request */ - void constructAllocateRequest(u32bits lifetime, int af4, int af6, u08bits transport, int mobile) { - stun_set_allocate_request_str(_buffer, &_sz, lifetime, af4, af6, transport, mobile); + void constructAllocateRequest(u32bits lifetime, int af4, int af6, u08bits transport, int mobile, const char* rt, int ep) { + stun_set_allocate_request_str(_buffer, &_sz, lifetime, af4, af6, transport, mobile, rt, ep); } /** diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index fed7d46f..5a463f18 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -737,7 +737,7 @@ int stun_get_message_len_str(u08bits *buf, size_t blen, int padding, size_t *app ////////// ALLOCATE /////////////////////////////////// int stun_set_allocate_request_str(u08bits* buf, size_t *len, u32bits lifetime, int af4, int af6, - u08bits transport, int mobile) { + u08bits transport, int mobile, const char* rt, int ep) { stun_init_request_str(STUN_METHOD_ALLOCATE, buf, len); @@ -758,28 +758,49 @@ int stun_set_allocate_request_str(u08bits* buf, size_t *len, u32bits lifetime, i if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_LIFETIME,(u08bits*)(&field),sizeof(field))<0) return -1; } - if(mobile) { - if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_MOBILITY_TICKET,(const u08bits*)"",0)<0) return -1; - } + if(rt) { - //ADRESS-FAMILY - if (af4) { - u08bits field[4]; - field[0] = (u08bits)STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4; - field[1]=0; - field[2]=0; - field[3]=0; - if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY,field,sizeof(field))<0) return -1; - } + stun_attr_add_str(buf,len, STUN_ATTRIBUTE_RESERVATION_TOKEN, (const u08bits*) rt, 8); - if (af6) { - u08bits field[4]; - field[0] = (u08bits)STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6; - field[1]=0; - field[2]=0; - field[3]=0; - if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY,field,sizeof(field))<0) return -1; - }; + } else { + + if(mobile) { + if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_MOBILITY_TICKET,(const u08bits*)"",0)<0) return -1; + } + + if(ep) { + uint8_t value = 0x80; + if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_EVEN_PORT,(const u08bits*)&value,1)<0) return -1; + } + + //ADRESS-FAMILY + if (af4 && !af6) { + u08bits field[4]; + field[0] = (u08bits)STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4; + field[1]=0; + field[2]=0; + field[3]=0; + if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY,field,sizeof(field))<0) return -1; + } + + if (af6 && !af4) { + u08bits field[4]; + field[0] = (u08bits)STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6; + field[1]=0; + field[2]=0; + field[3]=0; + if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY,field,sizeof(field))<0) return -1; + } + + if (af4 && af6) { + u08bits field[4]; + field[0] = (u08bits)STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6; + field[1]=0; + field[2]=0; + field[3]=0; + if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_ADDITIONAL_ADDRESS_FAMILY,field,sizeof(field))<0) return -1; + } + } return 0; } @@ -1246,7 +1267,7 @@ int stun_attr_get_first_addr_str(const u08bits *buf, size_t len, u16bits attr_ty while(attr) { if(stun_attr_is_addr(attr) && (attr_type == stun_attr_get_type(attr))) { if(stun_attr_get_addr_str(buf,len,attr,ca,default_addr)==0) { - return 0; + return 0; } } attr=stun_attr_get_next_str(buf,len,attr); @@ -1273,6 +1294,48 @@ int stun_attr_add_bandwidth_str(u08bits* buf, size_t *len, band_limit_t bps0) { return stun_attr_add_str(buf,len,STUN_ATTRIBUTE_NEW_BANDWIDTH,(u08bits*)(&field),sizeof(field)); } +int stun_attr_add_address_error_code(u08bits* buf, size_t *len, int requested_address_family, u08bits error_code) +{ + u08bits field[4]; + field[0]=(u08bits)requested_address_family; + field[1]=error_code; + field[2]=0; + field[3]=0; + return stun_attr_add_str(buf,len,STUN_ATTRIBUTE_ADDRESS_ERROR_CODE,field,sizeof(field)); +} + +int stun_attr_get_address_error_code(u08bits* buf, size_t len, int *requested_address_family, u08bits *error_code) +{ + if(requested_address_family) { + *requested_address_family = 0; + } + if(error_code) { + *error_code = 0; + } + if(buf && len) { + stun_attr_ref sar = stun_attr_get_first_by_type_str(buf, len, STUN_ATTRIBUTE_ADDRESS_ERROR_CODE); + if(sar) { + const u08bits* value = stun_attr_get_value(sar); + if(!value) { + return -1; + } else { + int alen = stun_attr_get_len(sar); + if(alen != 4) { + return -1; + } + if(requested_address_family) { + *requested_address_family = value[0]; + } + if(error_code) { + *error_code = value[1]; + } + return 0; + } + } + } + return 0; +} + u16bits stun_attr_get_first_channel_number_str(const u08bits *buf, size_t len) { stun_attr_ref attr=stun_attr_get_first_str(buf,len); @@ -1280,7 +1343,7 @@ u16bits stun_attr_get_first_channel_number_str(const u08bits *buf, size_t len) { if(stun_attr_get_type(attr) == STUN_ATTRIBUTE_CHANNEL_NUMBER) { u16bits ret = stun_attr_get_channel_number(attr); if(STUN_VALID_CHANNEL(ret)) { - return ret; + return ret; } } attr=stun_attr_get_next_str(buf,len,attr); diff --git a/src/client/ns_turn_msg.h b/src/client/ns_turn_msg.h index 0d6d93ea..0b248bdc 100644 --- a/src/client/ns_turn_msg.h +++ b/src/client/ns_turn_msg.h @@ -151,9 +151,12 @@ int stun_attr_get_addr_str(const u08bits *buf, size_t len, stun_attr_ref attr, i int stun_attr_get_first_addr_str(const u08bits *buf, size_t len, u16bits attr_type, ioa_addr* ca, const ioa_addr *default_addr); int stun_attr_add_channel_number_str(u08bits* buf, size_t *len, u16bits chnumber); int stun_attr_add_bandwidth_str(u08bits* buf, size_t *len, band_limit_t bps); +int stun_attr_add_address_error_code(u08bits* buf, size_t *len, int requested_address_family, u08bits error_code); +/* return +1 if present, 0 if not, -1 if error: */ +int stun_attr_get_address_error_code(u08bits* buf, size_t len, int *requested_address_family, u08bits *error_code); u16bits stun_attr_get_first_channel_number_str(const u08bits *buf, size_t len); -int stun_set_allocate_request_str(u08bits* buf, size_t *len, u32bits lifetime, int af4, int af6, u08bits transport, int mobile); +int stun_set_allocate_request_str(u08bits* buf, size_t *len, u32bits lifetime, int af4, int af6, u08bits transport, int mobile, const char* rt, int ep); int stun_set_allocate_response_str(u08bits* buf, size_t *len, stun_tid* tid, const ioa_addr *relayed_addr1, const ioa_addr *relayed_addr2, const ioa_addr *reflexive_addr, diff --git a/src/client/ns_turn_msg_defs.h b/src/client/ns_turn_msg_defs.h index 5e22c251..f0a22ee6 100644 --- a/src/client/ns_turn_msg_defs.h +++ b/src/client/ns_turn_msg_defs.h @@ -123,11 +123,11 @@ /* RFC 5780 */ #define STUN_ATTRIBUTE_PADDING (0x0026) #define STUN_ATTRIBUTE_RESPONSE_PORT (0x0027) -#define STUN_ATTRIBUTE_RESPONSE_ORIGIN (0x802b) -#define STUN_ATTRIBUTE_OTHER_ADDRESS (0x802c) +#define STUN_ATTRIBUTE_RESPONSE_ORIGIN (0x802B) +#define STUN_ATTRIBUTE_OTHER_ADDRESS (0x802C) /* RFC 6062 ==>> */ -#define STUN_ATTRIBUTE_CONNECTION_ID (0x002a) +#define STUN_ATTRIBUTE_CONNECTION_ID (0x002A) /* <<== RFC 6062 */ #define STUN_VALID_CHANNEL(chn) ((chn)>=0x4000 && (chn)<=0x7FFF) diff --git a/src/client/ns_turn_msg_defs_new.h b/src/client/ns_turn_msg_defs_new.h index 82909716..99709b3a 100644 --- a/src/client/ns_turn_msg_defs_new.h +++ b/src/client/ns_turn_msg_defs_new.h @@ -175,4 +175,9 @@ struct _encoded_oauth_token { typedef struct _encoded_oauth_token encoded_oauth_token; +////////////// SSODA /////////////////// + +#define STUN_ATTRIBUTE_ADDITIONAL_ADDRESS_FAMILY (0x8032) +#define STUN_ATTRIBUTE_ADDRESS_ERROR_CODE (0x8033) + #endif //__LIB_TURN_MSG_DEFS_NEW__ diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 6b9d8f8a..dd7f2b2d 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -914,6 +914,10 @@ static int handle_turn_allocate(turn_turnserver *server, int *err_code, const u08bits **reason, u16bits *unknown_attrs, u16bits *ua_num, ioa_net_data *in_buffer, ioa_network_buffer_handle nbh) { + + int err_code4 = 0; + int err_code6 = 0; + allocation* alloc = get_allocation_ss(ss); if (is_allocation_valid(alloc)) { @@ -1033,15 +1037,15 @@ static int handle_turn_allocate(turn_turnserver *server, const u08bits* value = stun_attr_get_value(sar); if (value) { transport = get_transport_value(value); - if (!transport || value[1] || value[2] || value[3]) { + if (!transport) { *err_code = 442; *reason = (const u08bits *)"Unsupported Transport Protocol"; } if((transport == STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE) && *(server->no_tcp_relay)) { - *err_code = 403; + *err_code = 442; *reason = (const u08bits *)"TCP Transport is not allowed by the TURN Server configuration"; } else if((transport == STUN_ATTRIBUTE_TRANSPORT_UDP_VALUE) && *(server->no_udp_relay)) { - *err_code = 403; + *err_code = 442; *reason = (const u08bits *)"UDP Transport is not allowed by the TURN Server configuration"; } else if(ss->client_socket) { SOCKET_TYPE cst = get_ioa_socket_type(ss->client_socket); @@ -1113,17 +1117,29 @@ static int handle_turn_allocate(turn_turnserver *server, } } break; + case STUN_ATTRIBUTE_ADDITIONAL_ADDRESS_FAMILY: case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY: { if(in_reservation_token) { *err_code = 400; *reason = (const u08bits *)"Address family attribute can not be used with reservation token request"; + } else if(af4 || af6) { + *err_code = 400; + *reason = (const u08bits *)"Extra address family attribute can not be used in the request"; } else { int af_req = stun_get_requested_address_family(sar); switch (af_req) { case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4: - af4 = af_req; + if(attr_type == STUN_ATTRIBUTE_ADDITIONAL_ADDRESS_FAMILY) { + *err_code = 400; + *reason = (const u08bits *)"Invalid value of the additional address family attribute"; + } else { + af4 = af_req; + } break; case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6: + if(attr_type == STUN_ATTRIBUTE_ADDITIONAL_ADDRESS_FAMILY) { + af4 = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4; + } af6 = af_req; break; default: @@ -1248,9 +1264,9 @@ static int handle_turn_allocate(turn_turnserver *server, } } } else { - int err_code4 = 0; const u08bits *reason4 = NULL; - if(af4) { + const u08bits *reason6 = NULL; + { int af4res = create_relay_connection(server, ss, lifetime, af4, transport, even_port, in_reservation_token, &out_reservation_token, @@ -1263,9 +1279,7 @@ static int handle_turn_allocate(turn_turnserver *server, } } } - int err_code6 = 0; - const u08bits *reason6 = NULL; - if(af6) { + { int af6res = create_relay_connection(server, ss, lifetime, af6, transport, even_port, in_reservation_token, &out_reservation_token, @@ -1373,6 +1387,19 @@ static int handle_turn_allocate(turn_turnserver *server, *resp_constructed = 1; } + if(*resp_constructed && !(*err_code)) { + if(err_code4) { + size_t len = ioa_network_buffer_get_size(nbh); + stun_attr_add_address_error_code(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4, (u08bits)err_code4); + ioa_network_buffer_set_size(nbh,len); + } + if(err_code6) { + size_t len = ioa_network_buffer_get_size(nbh); + stun_attr_add_address_error_code(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6, (u08bits)err_code6); + ioa_network_buffer_set_size(nbh,len); + } + } + return 0; }