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