1 /*
2 * Copyright (C) 2011, 2012, 2013 Citrix Systems
3 *
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the project nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31 #include "stun_buffer.h"
32
33 ////////////////////// BUFFERS ///////////////////////////
34
stun_init_buffer(stun_buffer * buf)35 int stun_init_buffer(stun_buffer *buf) {
36 if(!buf) return -1;
37 bzero(buf->buf,sizeof(buf->buf));
38 buf->len=0;
39 buf->offset=0;
40 buf->coffset=0;
41 return 0;
42 }
43
stun_get_size(const stun_buffer * buf)44 int stun_get_size(const stun_buffer *buf) {
45 if(!buf) return 0;
46 return sizeof(buf->buf);
47 }
48
49 ////////////////////////////////////////////////////////////
50
stun_tid_from_message(const stun_buffer * buf,stun_tid * id)51 void stun_tid_from_message(const stun_buffer *buf, stun_tid* id) {
52 stun_tid_from_message_str(buf->buf,(size_t)(buf->len), id);
53 }
54
stun_tid_generate_in_message(stun_buffer * buf,stun_tid * id)55 void stun_tid_generate_in_message(stun_buffer* buf, stun_tid* id) {
56 if(buf) {
57 stun_tid_generate_in_message_str(buf->buf, id);
58 }
59 }
60
61 ////////////////////////////////////////////////////////
62
is_channel_msg(const stun_buffer * buf)63 static inline int is_channel_msg(const stun_buffer* buf) {
64 if(buf && buf->len>0) {
65 return is_channel_msg_str(buf->buf, (size_t)(buf->len));
66 }
67 return 0;
68 }
69
stun_is_command_message(const stun_buffer * buf)70 int stun_is_command_message(const stun_buffer* buf) {
71 if(!buf || buf->len<=0)
72 return 0;
73 else
74 return stun_is_command_message_str(buf->buf,(size_t)(buf->len));
75 }
76
stun_is_request(const stun_buffer * buf)77 int stun_is_request(const stun_buffer* buf) {
78 return stun_is_request_str(buf->buf,(size_t)buf->len);
79 }
80
stun_is_success_response(const stun_buffer * buf)81 int stun_is_success_response(const stun_buffer* buf) {
82 return stun_is_success_response_str(buf->buf, (size_t)(buf->len));
83 }
84
stun_is_error_response(const stun_buffer * buf,int * err_code,uint8_t * err_msg,size_t err_msg_size)85 int stun_is_error_response(const stun_buffer* buf, int *err_code, uint8_t *err_msg, size_t err_msg_size) {
86 return stun_is_error_response_str(buf->buf, (size_t)(buf->len), err_code, err_msg, err_msg_size);
87 }
88
stun_is_response(const stun_buffer * buf)89 int stun_is_response(const stun_buffer* buf) {
90 return stun_is_response_str(buf->buf,(size_t)(buf->len));
91 }
92
stun_is_indication(const stun_buffer * buf)93 int stun_is_indication(const stun_buffer* buf) {
94 if(is_channel_msg(buf)) return 0;
95 return IS_STUN_INDICATION(stun_get_msg_type(buf));
96 }
97
stun_get_method(const stun_buffer * buf)98 uint16_t stun_get_method(const stun_buffer* buf) {
99 return stun_get_method_str(buf->buf, (size_t)(buf->len));
100 }
101
stun_get_msg_type(const stun_buffer * buf)102 uint16_t stun_get_msg_type(const stun_buffer* buf) {
103 if(!buf) return (uint16_t)-1;
104 return stun_get_msg_type_str(buf->buf,(size_t)buf->len);
105 }
106
107 ////////////////////////////////////////////////////////////
108
stun_init_command(uint16_t message_type,stun_buffer * buf)109 static void stun_init_command(uint16_t message_type, stun_buffer* buf) {
110 buf->len=stun_get_size(buf);
111 stun_init_command_str(message_type, buf->buf, (size_t*)(&(buf->len)));
112 }
113
stun_init_request(uint16_t method,stun_buffer * buf)114 void stun_init_request(uint16_t method, stun_buffer* buf) {
115 stun_init_command(stun_make_request(method), buf);
116 }
117
stun_init_indication(uint16_t method,stun_buffer * buf)118 void stun_init_indication(uint16_t method, stun_buffer* buf) {
119 stun_init_command(stun_make_indication(method), buf);
120 }
121
stun_init_success_response(uint16_t method,stun_buffer * buf,stun_tid * id)122 void stun_init_success_response(uint16_t method, stun_buffer* buf, stun_tid* id) {
123 buf->len=stun_get_size(buf);
124 stun_init_success_response_str(method, buf->buf, (size_t*)(&(buf->len)), id);
125 }
126
stun_init_error_response(uint16_t method,stun_buffer * buf,uint16_t error_code,const uint8_t * reason,stun_tid * id)127 void stun_init_error_response(uint16_t method, stun_buffer* buf, uint16_t error_code, const uint8_t *reason, stun_tid* id) {
128 buf->len=stun_get_size(buf);
129 stun_init_error_response_str(method, buf->buf, (size_t*)(&(buf->len)), error_code, reason, id);
130 }
131
132 ///////////////////////////////////////////////////////////////////////////////
133
stun_get_command_message_len(const stun_buffer * buf)134 int stun_get_command_message_len(const stun_buffer* buf) {
135 return stun_get_command_message_len_str(buf->buf, (size_t)(buf->len));
136 }
137
138 ///////////////////////////////////////////////////////////////////////////////
139
stun_init_channel_message(uint16_t chnumber,stun_buffer * buf,int length,int do_padding)140 int stun_init_channel_message(uint16_t chnumber, stun_buffer* buf, int length, int do_padding) {
141 return stun_init_channel_message_str(chnumber, buf->buf, (size_t*)(&(buf->len)), length, do_padding);
142 }
143
stun_is_channel_message(stun_buffer * buf,uint16_t * chnumber,int is_padding_mandatory)144 int stun_is_channel_message(stun_buffer* buf, uint16_t* chnumber, int is_padding_mandatory) {
145 if(!buf) return 0;
146 size_t blen = (size_t)buf->len;
147 int ret = stun_is_channel_message_str(buf->buf, &blen, chnumber, is_padding_mandatory);
148 if(ret) {
149 buf->len=(ssize_t)blen;
150 }
151 return ret;
152 }
153
154 ///////////////////////////////////////////////////////////////////////////////
155
stun_set_allocate_request(stun_buffer * buf,uint32_t lifetime,int af4,int af6,uint8_t transport,int mobile,const char * rt,int ep)156 int stun_set_allocate_request(stun_buffer* buf, uint32_t lifetime, int af4, int af6, uint8_t transport, int mobile, const char *rt, int ep) {
157 return stun_set_allocate_request_str(buf->buf, (size_t*)(&(buf->len)), lifetime, af4, af6, transport, mobile, rt, ep);
158 }
159
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,uint32_t lifetime,uint32_t max_lifetime,int error_code,const uint8_t * reason,uint64_t reservation_token,char * mobile_id)160 int stun_set_allocate_response(stun_buffer* buf, stun_tid* tid,
161 const ioa_addr *relayed_addr1, const ioa_addr *relayed_addr2,
162 const ioa_addr *reflexive_addr,
163 uint32_t lifetime, uint32_t max_lifetime, int error_code, const uint8_t *reason,
164 uint64_t reservation_token, char *mobile_id) {
165
166 return stun_set_allocate_response_str(buf->buf, (size_t*)(&(buf->len)), tid,
167 relayed_addr1, relayed_addr2, reflexive_addr,
168 lifetime, max_lifetime, error_code, reason,
169 reservation_token, mobile_id);
170
171 }
172
173 ///////////////////////////////////////////////////////////////////////////////
174
stun_set_channel_bind_request(stun_buffer * buf,const ioa_addr * peer_addr,uint16_t channel_number)175 uint16_t stun_set_channel_bind_request(stun_buffer* buf,
176 const ioa_addr* peer_addr, uint16_t channel_number) {
177
178 return stun_set_channel_bind_request_str(buf->buf,(size_t*)(&(buf->len)), peer_addr, channel_number);
179 }
180
stun_set_channel_bind_response(stun_buffer * buf,stun_tid * tid,int error_code,const uint8_t * reason)181 void stun_set_channel_bind_response(stun_buffer* buf, stun_tid* tid, int error_code, const uint8_t *reason) {
182 stun_set_channel_bind_response_str(buf->buf, (size_t*)(&(buf->len)), tid, error_code, reason);
183 }
184
185 ////////////////////////////////////////////////////////////////
186
stun_attr_get_first(const stun_buffer * buf)187 stun_attr_ref stun_attr_get_first(const stun_buffer* buf) {
188 return stun_attr_get_first_str(buf->buf, (size_t)(buf->len));
189 }
190
stun_attr_get_next(const stun_buffer * buf,stun_attr_ref prev)191 stun_attr_ref stun_attr_get_next(const stun_buffer* buf, stun_attr_ref prev) {
192 return stun_attr_get_next_str(buf->buf, (size_t)(buf->len), prev);
193 }
194
stun_attr_add(stun_buffer * buf,uint16_t attr,const char * avalue,int alen)195 int stun_attr_add(stun_buffer* buf, uint16_t attr, const char* avalue, int alen) {
196 return stun_attr_add_str(buf->buf, (size_t*)(&(buf->len)), attr, (const uint8_t *)avalue, alen);
197 }
198
stun_attr_add_channel_number(stun_buffer * buf,uint16_t chnumber)199 int stun_attr_add_channel_number(stun_buffer* buf, uint16_t chnumber) {
200 return stun_attr_add_channel_number_str(buf->buf, (size_t *)(&(buf->len)), chnumber);
201 }
202
stun_attr_add_addr(stun_buffer * buf,uint16_t attr_type,const ioa_addr * ca)203 int stun_attr_add_addr(stun_buffer *buf,uint16_t attr_type, const ioa_addr* ca) {
204 return stun_attr_add_addr_str(buf->buf,(size_t*)(&(buf->len)), attr_type, ca);
205 }
206
stun_attr_get_addr(const stun_buffer * buf,stun_attr_ref attr,ioa_addr * ca,const ioa_addr * default_addr)207 int stun_attr_get_addr(const stun_buffer *buf, stun_attr_ref attr, ioa_addr* ca,
208 const ioa_addr *default_addr) {
209
210 return stun_attr_get_addr_str(buf->buf, (size_t)(buf->len), attr, ca, default_addr);
211 }
212
stun_attr_get_first_addr(const stun_buffer * buf,uint16_t attr_type,ioa_addr * ca,const ioa_addr * default_addr)213 int stun_attr_get_first_addr(const stun_buffer *buf, uint16_t attr_type, ioa_addr* ca,
214 const ioa_addr *default_addr) {
215
216 return stun_attr_get_first_addr_str(buf->buf, (size_t)(buf->len), attr_type, ca, default_addr);
217 }
218
stun_attr_add_even_port(stun_buffer * buf,uint8_t value)219 int stun_attr_add_even_port(stun_buffer* buf, uint8_t value) {
220 if(value) value=0x80;
221 return stun_attr_add(buf,STUN_ATTRIBUTE_EVEN_PORT,(const char*)&value,1);
222 }
223
stun_attr_get_first_channel_number(const stun_buffer * buf)224 uint16_t stun_attr_get_first_channel_number(const stun_buffer *buf) {
225 return stun_attr_get_first_channel_number_str(buf->buf, (size_t)(buf->len));
226 }
227
stun_attr_get_first_by_type(const stun_buffer * buf,uint16_t attr_type)228 stun_attr_ref stun_attr_get_first_by_type(const stun_buffer* buf, uint16_t attr_type) {
229 return stun_attr_get_first_by_type_str(buf->buf, (size_t)(buf->len), attr_type);
230 }
231
232 ///////////////////////////////////////////////////////////////////////////////
233
stun_set_binding_request(stun_buffer * buf)234 void stun_set_binding_request(stun_buffer* buf) {
235 stun_set_binding_request_str(buf->buf, (size_t*)(&(buf->len)));
236 }
237
stun_set_binding_response(stun_buffer * buf,stun_tid * tid,const ioa_addr * reflexive_addr,int error_code,const uint8_t * reason)238 int stun_set_binding_response(stun_buffer* buf, stun_tid* tid,
239 const ioa_addr *reflexive_addr, int error_code, const uint8_t *reason) {
240 return stun_set_binding_response_str(buf->buf, (size_t*)(&(buf->len)), tid,
241 reflexive_addr, error_code, reason,
242 0,0);
243 }
244
stun_prepare_binding_request(stun_buffer * buf)245 void stun_prepare_binding_request(stun_buffer* buf) {
246 stun_set_binding_request_str(buf->buf, (size_t*)(&(buf->len)));
247 }
248
stun_is_binding_response(const stun_buffer * buf)249 int stun_is_binding_response(const stun_buffer* buf) {
250 return stun_is_binding_response_str(buf->buf, (size_t)(buf->len));
251 }
252
253 ///////////////////////////////////////////////////////
254