Browse code

- added STUN keep-alive functionality in accordance with draft-ietf-behave-rfc3489bis-04.txt

Vladimir Marek authored on 13/10/2006 13:08:42
Showing 10 changed files
... ...
@@ -351,6 +351,8 @@ endif
351 351
 # -DPROFILING
352 352
 #		if enabled profiling will be enabled for child processes
353 353
 #		Don't forget to set PROFILE (see below)
354
+# -DUSE_STUN
355
+#		compiles in stun support
354 356
 
355 357
 # Sometimes is needes correct non-quoted $OS. HACK: gcc translates known OS to number ('linux'), so there is added underscore
356 358
 
... ...
@@ -394,6 +396,10 @@ ifneq ($(TLS),)
394 394
 	DEFS+= -DUSE_TLS
395 395
 endif
396 396
 
397
+ifneq ($(STUN),)
398
+	DEFS+= -DUSE_STUN
399
+endif
400
+
397 401
 ifeq ($(mode),)
398 402
 	mode = release
399 403
 endif
... ...
@@ -1388,6 +1394,11 @@ DEFS+= -I$(LOCALBASE)/ssl/include
1388 1388
 LIBS+= -L$(LOCALBASE)/lib -L$(LOCALBASE)/ssl/lib -lssl  -lcrypto
1389 1389
 endif
1390 1390
 
1391
+ifneq ($(STUN),)
1392
+DEFS+= -I$(LOCALBASE)/ssl/include
1393
+LIBS+= -L$(LOCALBASE)/lib -L$(LOCALBASE)/ssl/lib -lcrypto
1394
+endif
1395
+
1391 1396
 ifneq ($(found_lock_method), yes)
1392 1397
 $(warning	No locking method found so far, trying SYS V sems)
1393 1398
 		DEFS+= -DUSE_SYSV_SEM  # try sys v sems
... ...
@@ -60,8 +60,10 @@
60 60
  *              to_{ip,port} (andrei)
61 61
  *  2005-12-12  separated drop, exit, break, return, added RETCODE (andrei)
62 62
  *  2005-12-19  select framework (mma)
63
- * 2006-09-11  added dns cache (use, flags, ttls, mem ,gc) & dst blacklist
63
+ *  2006-09-11  added dns cache (use, flags, ttls, mem ,gc) & dst blacklist
64 64
  *              options (andrei)
65
+ *  2006-10-13  added STUN_ALLOW_STUN, STUN_ALLOW_FP, STUN_REFRESH_INTERVAL
66
+ *              (vlada)
65 67
  */
66 68
 
67 69
 
... ...
@@ -289,6 +291,11 @@ MCAST_LOOPBACK		"mcast_loopback"
289 289
 MCAST_TTL		"mcast_ttl"
290 290
 TOS			"tos"
291 291
 
292
+/* stun config variables */
293
+STUN_REFRESH_INTERVAL "stun_refresh_interval"
294
+STUN_ALLOW_STUN "stun_allow_stun"
295
+STUN_ALLOW_FP "stun_allow_fp"
296
+
292 297
 LOADMODULE	loadmodule
293 298
 MODPARAM        modparam
294 299
 
... ...
@@ -528,6 +535,10 @@ EAT_ABLE	[\ \t\b\r]
528 528
 <INITIAL>{LOADMODULE}	{ count(); yylval.strval=yytext; return LOADMODULE; }
529 529
 <INITIAL>{MODPARAM}     { count(); yylval.strval=yytext; return MODPARAM; }
530 530
 
531
+<INITIAL>{STUN_REFRESH_INTERVAL} { count(); yylval.strval=yytext; return STUN_REFRESH_INTERVAL;}
532
+<INITIAL>{STUN_ALLOW_STUN} { count(); yylval.strval=yytext; return STUN_ALLOW_STUN;}
533
+<INITIAL>{STUN_ALLOW_FP} { count(); yylval.strval=yytext; return STUN_ALLOW_FP;}
534
+
531 535
 <INITIAL>{EQUAL}	{ count(); return EQUAL; }
532 536
 <INITIAL>{ADDEQ}          { count(); return ADDEQ; }
533 537
 <INITIAL>{EQUAL_T}	{ count(); return EQUAL_T; }
... ...
@@ -74,6 +74,8 @@
74 74
  * 2006-05-30  avp flags (tma)
75 75
  * 2006-09-11  added dns cache (use, flags, ttls, mem ,gc) & dst blacklist
76 76
  *              options (andrei)
77
+ * 2006-10-13  added STUN_ALLOW_STUN, STUN_ALLOW_FP, STUN_REFRESH_INTERVAL
78
+ *              (vlada)
77 79
  */
78 80
 
79 81
 %{
... ...
@@ -335,6 +337,10 @@ static struct socket_id* mk_listen_id(char*, int, int);
335 335
 %token ATTR_GLOBAL
336 336
 %token ADDEQ
337 337
 
338
+%token STUN_REFRESH_INTERVAL
339
+%token STUN_ALLOW_STUN
340
+%token STUN_ALLOW_FP
341
+
338 342
 /* operators */
339 343
 %nonassoc EQUAL
340 344
 %nonassoc EQUAL_T
... ...
@@ -864,6 +870,25 @@ assign_stm:
864 864
 	| TOS EQUAL NUMBER { tos=$3; }
865 865
 	| TOS EQUAL error { yyerror("number expected"); }
866 866
 	| error EQUAL { yyerror("unknown config variable"); }
867
+	| STUN_REFRESH_INTERVAL EQUAL NUMBER { 
868
+		#ifdef USE_STUN
869
+			stun_refresh_interval=$3;
870
+		#endif
871
+		}
872
+	| STUN_REFRESH_INTERVAL EQUAL error{ yyerror("number expected"); }
873
+	| STUN_ALLOW_STUN EQUAL NUMBER { 
874
+		#ifdef USE_STUN
875
+			stun_allow_stun=$3;
876
+		#endif
877
+		}
878
+	| STUN_ALLOW_STUN EQUAL error{ yyerror("number expected"); }
879
+	| STUN_ALLOW_FP EQUAL NUMBER { 
880
+		#ifdef USE_STUN
881
+			stun_allow_fp=$3;
882
+		#endif
883
+		}
884
+	| STUN_ALLOW_FP EQUAL error{ yyerror("number expected"); }
885
+	| error EQUAL { yyerror("unknown config variable"); }
867 886
 	;
868 887
 module_stm:
869 888
 	LOADMODULE STRING {
... ...
@@ -114,6 +114,12 @@ extern int mcast_loopback;
114 114
 extern int mcast_ttl;
115 115
 #endif /* USE_MCAST */
116 116
 
117
+#ifdef USE_STUN
118
+extern unsigned int stun_refresh_interval;
119
+extern int stun_allow_stun;
120
+extern int stun_allow_fp;
121
+#endif
122
+
117 123
 extern int tos;
118 124
 
119 125
 /*
... ...
@@ -62,6 +62,8 @@
62 62
  *               of them might use it "unset" (andrei)
63 63
  *  2005-07-25  use sigaction for setting the signal handlers (andrei)
64 64
  *  2006-07-13  added dns cache/failover init. (andrei)
65
+ *  2006-10-13  added global variables stun_refresh_interval, stun_allow_stun
66
+ *              and stun_allow_fp (vlada)
65 67
  */
66 68
 
67 69
 
... ...
@@ -353,6 +355,15 @@ unsigned short port_no=0; /* default port*/
353 353
 unsigned short tls_port_no=0; /* default port */
354 354
 #endif
355 355
 
356
+#ifdef USE_STUN
357
+/* refresh interval in miliseconds */
358
+unsigned int stun_refresh_interval=0;
359
+/* stun can be switch off even if it is compiled */
360
+int stun_allow_stun=1;
361
+/* use or don't use fingerprint */
362
+int stun_allow_fp=1;
363
+#endif
364
+
356 365
 struct host_alias* aliases=0; /* name aliases list */
357 366
 
358 367
 /* Parameter to child_init */
359 368
new file mode 100644
... ...
@@ -0,0 +1,1080 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * Copyright (C) 2001-2003 FhG Fokus
4
+ *
5
+ * This file is part of ser, a free SIP server.
6
+ *
7
+ * ser is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version
11
+ *
12
+ * For a license to use the ser software under conditions
13
+ * other than those described here, or to purchase support for this
14
+ * software, please contact iptel.org by e-mail at the following addresses:
15
+ *    info@iptel.org
16
+ *
17
+ * ser is distributed in the hope that it will be useful,
18
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
+ * GNU General Public License for more details.
21
+ *
22
+ * You should have received a copy of the GNU General Public License 
23
+ * along with this program; if not, write to the Free Software 
24
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25
+ *
26
+ * History
27
+ * --------
28
+ *  2006-10-13  created (vlada)
29
+ */
30
+
31
+#ifdef USE_STUN 
32
+ 
33
+#include <arpa/inet.h>
34
+#include "ser_stun.h"
35
+#include "forward.h"
36
+
37
+extern unsigned char* SHA1(const unsigned char* d, size_t m,unsigned char* md);
38
+
39
+/*
40
+ * ****************************************************************************
41
+ *                     Declaration of functions                               *
42
+ * ****************************************************************************
43
+ */
44
+int stun_parse_header(struct stun_msg* req, USHORT_T* error_code);
45
+int stun_parse_body(
46
+				struct stun_msg* req,
47
+				struct stun_unknown_att** unknown,
48
+				USHORT_T* error_code);
49
+void stun_delete_unknown_attrs(struct stun_unknown_att* unknown);
50
+struct stun_unknown_att* stun_alloc_unknown_attr(USHORT_T type);
51
+int stun_add_address_attr(struct stun_msg* res, 
52
+						UINT_T		af,
53
+						USHORT_T	port,
54
+						UINT_T*		ip_addr,
55
+						USHORT_T	type,
56
+						int do_xor);
57
+int add_unknown_attr(struct stun_msg* res, struct stun_unknown_att* unknown);
58
+int add_error_code(struct stun_msg* res, USHORT_T error_code);
59
+int add_fingerprint(struct stun_buffer* msg);
60
+int copy_str_to_buffer(struct stun_msg* res, const char* data, UINT_T pad);
61
+int validate_fingerprint(struct stun_msg* req, USHORT_T* error_code);
62
+int reallock_buffer(struct stun_buffer* buffer, UINT_T len);
63
+int buf_copy(struct stun_buffer* msg, void* source, UINT_T len);
64
+void clean_memory(struct stun_msg* req,
65
+				struct stun_msg* res,	struct stun_unknown_att* unknown);
66
+int stun_create_response(
67
+						struct stun_msg* req,
68
+						struct stun_msg* res,
69
+						struct receive_info* ri,
70
+						struct stun_unknown_att* unknown, 
71
+						UINT_T error_code);
72
+int stun_add_common_integer_attr(struct stun_msg* res, USHORT_T type, UINT_T value);
73
+int stun_add_common_text_attr(struct stun_msg* res, USHORT_T type, char* value, 
74
+							USHORT_T pad);
75
+
76
+
77
+/*
78
+ * ****************************************************************************
79
+ *                      Definition of functions                               *
80
+ * ****************************************************************************
81
+ */
82
+ 
83
+/* 
84
+ * stun_process_msg(): 
85
+ * 			buf - incoming message
86
+ * 			len - length of incoming message
87
+ * 			ri  - information about socket that received a message and 
88
+ *                also information about sender (its IP, port, protocol)
89
+ * 
90
+ * This function ensures processing of incoming message. It's common for both
91
+ * TCP and UDP protocol. There is no other function as an interface.
92
+ * 
93
+ * Return value:	0	if there is no environment error
94
+ * 					-1	if there is some enviroment error such as insufficiency
95
+ * 						of memory
96
+ * 
97
+ */
98
+int stun_process_msg(char* buf, unsigned len, struct receive_info* ri)
99
+{
100
+	struct stun_msg 			msg_req;
101
+	struct stun_msg 			msg_res;
102
+	struct dest_info			dst;
103
+	struct stun_unknown_att*	unknown;
104
+	USHORT_T					error_code;
105
+	int ii;
106
+	 
107
+	memset(&msg_req, 0, sizeof(msg_req));
108
+	memset(&msg_res, 0, sizeof(msg_res));
109
+	
110
+	msg_req.msg.buf.s = buf;
111
+	msg_req.msg.buf.len = len;	
112
+	unknown = NULL;
113
+	error_code = RESPONSE_OK;
114
+	
115
+	if (stun_parse_header(&msg_req, &error_code) != 0) {
116
+		goto error;
117
+	}
118
+	
119
+	if (error_code == RESPONSE_OK) {
120
+		if (stun_parse_body(&msg_req, &unknown, &error_code) != 0) {
121
+			goto error;
122
+		}
123
+	}
124
+	
125
+	if (stun_create_response(&msg_req, &msg_res, ri,  
126
+							unknown, error_code) != 0) {
127
+		goto error;
128
+	}
129
+	
130
+	init_dst_from_rcv(&dst, ri);
131
+
132
+#ifdef EXTRA_DEBUG	
133
+	struct ip_addr ip;
134
+	su2ip_addr(&ip, &dst.to);
135
+	char *ipp = ip_addr2a(&ip);
136
+	int porttt = su_getport(&dst.to);
137
+	LOG(L_DBG, "DEBUG: ser_stun: %s:%d):\n", ip_addr2a(&ip), 
138
+		su_getport(&dst.to));
139
+#endif
140
+	
141
+	/* send STUN response */
142
+	if (msg_send(&dst, msg_res.msg.buf.s, msg_res.msg.buf.len) != 0) {
143
+		goto error;
144
+	}
145
+	
146
+	clean_memory(&msg_req, &msg_res, unknown);
147
+	return 0;
148
+	
149
+error:
150
+	clean_memory(&msg_req, &msg_res, unknown);
151
+	return FATAL_ERROR;
152
+}
153
+
154
+/*
155
+ * stun_parse_header():
156
+ * 			- req: request from host that should be processed
157
+ * 			- error_code: indication of any protocol error
158
+ * 
159
+ * This function ensures parsing of incoming header.
160
+ * 
161
+ * Return value:	0	if there is no environment error
162
+ * 					-1	if there is some enviroment error such as insufficiency
163
+ * 						of memory
164
+ */
165
+
166
+int stun_parse_header(struct stun_msg* req, USHORT_T* error_code)
167
+{
168
+	
169
+	if (sizeof(req->hdr) > req->msg.buf.len) {
170
+		/* the received message does not contain whole header */
171
+		LOG(L_INFO, "INFO: incomplete header of STUN message\n");
172
+		/* Any better solution? IMHO it's not possible to send error response
173
+		 * because the transaction ID is not available.
174
+		 */
175
+		return FATAL_ERROR;
176
+	}
177
+	
178
+	memcpy(&req->hdr, req->msg.buf.s, sizeof(struct stun_hdr));
179
+	req->hdr.type = ntohs(req->hdr.type);
180
+	
181
+	/* the SER supports only Binding Request right now */ 
182
+	if (req->hdr.type != BINDING_REQUEST) {
183
+		LOG(L_INFO, "INFO: unsupported type of STUN message: %x\n", 
184
+					req->hdr.type);
185
+		/* resending of same message is not welcome */
186
+		*error_code = GLOBAL_FAILURE_ERR;
187
+	}
188
+	
189
+	req->hdr.len = ntohs(req->hdr.len);
190
+	
191
+	/* check if there is correct magic cookie */
192
+	req->old = (req->hdr.id.magic_cookie == htonl(MAGIC_COOKIE)) ? 0 : 1;
193
+
194
+	return 0;
195
+}
196
+
197
+/*
198
+ * stun_parse_body():
199
+ * 			- req: request from host that should be processed
200
+ * 			- unknown: this is a link list header of attributes 
201
+ * 					   that are unknown to SER; defaul value is NULL
202
+ * 			- error_code: indication of any protocol error
203
+ * 
204
+ * Return value:	0	if there is no environment error
205
+ * 					-1	if there is some enviroment error such as insufficiency
206
+ * 						of memory
207
+ */
208
+int stun_parse_body(
209
+				struct stun_msg* req,
210
+				struct stun_unknown_att** unknown,
211
+				USHORT_T* error_code)
212
+{
213
+	UINT_T not_parsed;
214
+	struct stun_attr attr;
215
+	USHORT_T attr_size;
216
+	UINT_T padded_len;
217
+	struct stun_unknown_att*	tmp_unknown;
218
+	struct stun_unknown_att*	body;
219
+	char*	buf;
220
+	int		fp_present;
221
+	
222
+	attr_size = sizeof(struct stun_attr);
223
+	buf = &req->msg.buf.s[sizeof(struct stun_hdr)];
224
+	fp_present = 0;
225
+	
226
+	/* 
227
+	 * the message length is different for rfc and rfc bis 
228
+	 * the bis version contains fingerprint that is not included in 
229
+	 * length of body which is listed in header of message
230
+	 */
231
+	not_parsed = req->msg.buf.len - sizeof(struct stun_hdr);
232
+	
233
+	if (req->old) {
234
+		if (not_parsed != req->hdr.len) {
235
+			*error_code = BAD_REQUEST_ERR;
236
+			return 0;
237
+		} 
238
+	}
239
+	else {
240
+		if (not_parsed != 
241
+		    req->hdr.len + SHA_DIGEST_LENGTH + sizeof(struct stun_attr)) {
242
+			*error_code = BAD_REQUEST_ERR;
243
+			return 0;
244
+		}
245
+	}
246
+	
247
+	tmp_unknown = *unknown;
248
+	body = NULL;
249
+	
250
+	while (not_parsed > 0 && *error_code == RESPONSE_OK) {
251
+		memset(&attr, 0, attr_size);
252
+		
253
+		/* check if there are 4 bytes for attribute type and its value */
254
+		if (not_parsed < 4) {
255
+			*error_code = BAD_REQUEST_ERR;
256
+			continue;
257
+		}
258
+		
259
+		memcpy(&attr, buf, attr_size);
260
+		
261
+		buf += attr_size;
262
+		not_parsed -= attr_size;
263
+		
264
+		/* check if there is enought unparsed space for attribute's value */
265
+		if (not_parsed < ntohs(attr.len)) {
266
+			*error_code = BAD_REQUEST_ERR;
267
+			continue;
268
+		}
269
+		
270
+		/* check if the attribute is known to the server */
271
+		switch (htons(attr.type)) {			
272
+			case REALM_ATTR:
273
+			case NONCE_ATTR:
274
+			case MAPPED_ADDRESS_ATTR:
275
+			case XOR_MAPPED_ADDRESS_ATTR:
276
+			case ALTERNATE_SERVER_ATTR:
277
+			case REFRESH_INTERVAL_ATTR:
278
+			case RESPONSE_ADDRESS_ATTR:
279
+			case SOURCE_ADDRESS_ATTR:
280
+			case REFLECTED_FROM_ATTR:		
281
+			case CHANGE_REQUEST_ATTR:
282
+			case CHANGED_ADDRESS_ATTR:
283
+				padded_len = ntohs(attr.len);
284
+				break;
285
+			
286
+			/* following attributes must be padded to 4 bytes */
287
+			case USERNAME_ATTR:
288
+			case PASSWORD_ATTR:
289
+			case ERROR_CODE_ATTR:
290
+			case UNKNOWN_ATTRIBUTES_ATTR:
291
+			case SERVER_ATTR:
292
+				padded_len = PADDED_TO_FOUR(ntohs(attr.len));
293
+				break;
294
+
295
+			/* MESSAGE_INTEGRITY must be padded to sixty four bytes*/
296
+			case MESSAGE_INTEGRITY_ATTR:
297
+				padded_len = PADDED_TO_SIXTYFOUR(ntohs(attr.len));
298
+				break;
299
+			
300
+			case FINGERPRINT_ATTR:
301
+				fp_present = 1;			
302
+				if (ntohs(attr.len) != SHA_DIGEST_LENGTH) {
303
+					LOG(L_WARN, 
304
+						"WARNING: STUN: Incorrect fingerprint of request.\n");
305
+					*error_code = BAD_REQUEST_ERR;
306
+					continue;
307
+				}
308
+
309
+				memcpy(req->fp, buf, SHA_DIGEST_LENGTH);
310
+				if(stun_allow_fp) {
311
+					if (validate_fingerprint(req, error_code) != 0) {
312
+						LOG(L_WARN, 
313
+							"WARNING: STUN: Incorrect fingerprint of request.\n");
314
+						*error_code = BAD_REQUEST_ERR;
315
+						continue;
316
+					}
317
+				} 
318
+
319
+				padded_len = SHA_DIGEST_LENGTH;
320
+				if (not_parsed > SHA_DIGEST_LENGTH) {
321
+					/* fingerprint must be last parameter in request */
322
+					*error_code = BAD_REQUEST_ERR;
323
+					continue;
324
+				}
325
+				break;
326
+			
327
+			default:
328
+				/* 
329
+				 * the attribute is uknnown to the server
330
+				 * let see if it's necessary to generate error response 
331
+				 */
332
+				if (attr.type <= htons(MANDATORY_ATTR)) {
333
+					tmp_unknown = stun_alloc_unknown_attr(attr.type);
334
+					if (tmp_unknown == NULL) {
335
+						return FATAL_ERROR;
336
+					}
337
+					if (*unknown == NULL) {
338
+						*unknown = body = tmp_unknown;
339
+					}
340
+					else { 
341
+						body->next = tmp_unknown;
342
+						body = body->next;
343
+					}
344
+				}
345
+				padded_len = ntohs(attr.len);
346
+				break;
347
+		}
348
+		buf += padded_len;
349
+		not_parsed -= padded_len;
350
+	}  /* while */
351
+	
352
+	/*
353
+	 * The unknown attribute error code must set after parsing of whole body
354
+	 * because it's necessary to obtain all of unknown attributes! 
355
+	 */
356
+	if (*error_code == RESPONSE_OK && *unknown != NULL) {
357
+		*error_code = UNKNOWN_ATTRIBUTE_ERR;
358
+	} 
359
+	
360
+	if (fp_present == 0 && req->old == 0) {
361
+		/* missing mandatory attribute fingerprint */
362
+		*error_code = BAD_REQUEST_ERR;
363
+	}
364
+	
365
+	return 0;
366
+}
367
+
368
+/*
369
+ * stun_create_response():
370
+ * 			- req: original request from host
371
+ * 			- res: this will represent response to host
372
+ * 			- ri: information about request, necessary because of IP 
373
+ * 				  address and port 
374
+ *			- unknown: link list of unknown attributes
375
+ * 			- error_code: indication of any protocol error
376
+ * 
377
+ * The function stun_create_response ensures creating response to a host.
378
+ * The type of response depends on value of error_code parameter.
379
+ * 
380
+ * Return value:	0	if there is no environment error
381
+ * 					-1	if there is some enviroment error such as insufficiency
382
+ * 						of memory  
383
+ */
384
+
385
+int stun_create_response(
386
+						struct stun_msg* req,
387
+						struct stun_msg* res,
388
+						struct receive_info* ri,
389
+						struct stun_unknown_att* unknown, 
390
+						UINT_T error_code)
391
+{
392
+	/*
393
+	 * Alloc some space for response.
394
+	 * Optimalization? - maybe it would be better to use biggish static array.
395
+	 */
396
+	res->msg.buf.s = (char *) pkg_malloc(sizeof(char)*STUN_MSG_LEN);
397
+	if (res->msg.buf.s == NULL) {
398
+		LOG(L_ERR, "ERROR: STUN: out of memory\n");
399
+		return FATAL_ERROR;
400
+	}
401
+	
402
+	memset(res->msg.buf.s, 0, sizeof(char)*STUN_MSG_LEN); 
403
+	res->msg.buf.len = 0;
404
+	res->msg.empty = STUN_MSG_LEN;
405
+	
406
+	/* use magic cookie and transaction ID from request */
407
+	memcpy(&res->hdr.id, &req->hdr.id, sizeof(struct transaction_id));
408
+	/* the correct body length will be added ASAP it will be known */ 
409
+	res->hdr.len = htons(0);
410
+	
411
+	if (error_code == RESPONSE_OK) {
412
+		res->hdr.type = htons(BINDING_RESPONSE);
413
+		
414
+		/* copy header into msg buffer */
415
+		if (buf_copy(&res->msg, (void *) &res->hdr, 
416
+					sizeof(struct stun_hdr)) != 0) {
417
+			return FATAL_ERROR;
418
+		}
419
+
420
+		/* 
421
+		 * If the SER received message in old format, then the body will 
422
+		 * contain MAPPED-ADDRESS attribute instead of XOR-MAPPED-ADDRESS
423
+		 * attribute.
424
+		 */		
425
+		if (req->old == 0) {
426
+			if (stun_add_address_attr(res, ri->src_ip.af, ri->src_port, 
427
+						  ri->src_ip.u.addr32, XOR_MAPPED_ADDRESS_ATTR, 
428
+						  XOR) != 0) {
429
+				return FATAL_ERROR;
430
+			}
431
+			
432
+			if (stun_add_common_integer_attr(res, REFRESH_INTERVAL_ATTR, 
433
+						stun_refresh_interval) != 0) {
434
+				return FATAL_ERROR;
435
+			}
436
+		}
437
+		else {
438
+			if (stun_add_address_attr(res, ri->src_ip.af, ri->src_port, 
439
+						ri->src_ip.u.addr32, MAPPED_ADDRESS_ATTR, !XOR) != 0) {
440
+				return FATAL_ERROR;
441
+			}
442
+		}
443
+	}
444
+	else {
445
+		res->hdr.type = htons(BINDING_ERROR_RESPONSE);
446
+		
447
+		if (buf_copy(&res->msg, (void *) &res->hdr, 
448
+								sizeof(struct stun_hdr)) != 0) {
449
+			return FATAL_ERROR;
450
+		}
451
+		
452
+		if (add_error_code(res, error_code) != 0) {
453
+			return FATAL_ERROR;
454
+		}
455
+		
456
+		if (unknown != NULL) {
457
+			if (add_unknown_attr(res, unknown) != 0) {
458
+				return FATAL_ERROR;
459
+			}
460
+		} 
461
+	}
462
+	
463
+	/* count length of body except header and fingerprint
464
+	 * and copy message length at the beginning of buffer
465
+	 */
466
+	res->hdr.len = htons(res->msg.buf.len - sizeof(struct stun_hdr));
467
+	memcpy(&res->msg.buf.s[sizeof(USHORT_T)], (void *) &res->hdr.len,
468
+		sizeof(USHORT_T));
469
+	
470
+	if (req->old == 0) {
471
+		/* add optional information about server */
472
+		if (stun_add_common_text_attr(res, SERVER_ATTR, SERVER_HDR, PAD4)!=0) {
473
+			return FATAL_ERROR;
474
+		}
475
+		
476
+		if (stun_allow_fp) {	
477
+			if (add_fingerprint(&res->msg) != 0) {
478
+				return FATAL_ERROR;
479
+			}
480
+		}
481
+	}
482
+	
483
+	return 0;
484
+}
485
+
486
+/*
487
+ * add_unknown_attr()
488
+ * 			- res: response representation
489
+ * 			- unknown: link list of unknown attributes
490
+ * 
491
+ * The function add_unknown_attr ensures copy of link list of unknown 
492
+ * attributes into response buffer.
493
+ * 
494
+ * Return value:	0	if there is no environment error
495
+ * 					-1	if there is some enviroment error such as insufficiency
496
+ * 						of memory
497
+ * 
498
+ */
499
+int add_unknown_attr(struct stun_msg* res, struct stun_unknown_att* unknown)
500
+{
501
+	struct stun_attr attr;
502
+	struct stun_unknown_att* tmp_unknown;
503
+	UINT_T		counter;
504
+	USHORT_T	orig_len;
505
+
506
+	counter = 0;
507
+	orig_len = res->msg.buf.len;
508
+	tmp_unknown = unknown;
509
+	
510
+	attr.type = htons(UNKNOWN_ATTRIBUTES_ATTR);
511
+	attr.len = htons(0);
512
+	
513
+	if (buf_copy(&res->msg, (void *) &attr, sizeof(struct stun_attr)) != 0) {
514
+		return FATAL_ERROR;
515
+	}
516
+	
517
+	while (tmp_unknown != NULL) {
518
+		if (buf_copy(&res->msg, (void *)&tmp_unknown->type, 
519
+								sizeof(USHORT_T)) != 0) {
520
+			return FATAL_ERROR;
521
+		}
522
+		tmp_unknown = tmp_unknown->next;
523
+		++counter;
524
+	}
525
+	
526
+	attr.len = htons(res->msg.buf.len - orig_len);
527
+	memcpy(&res->msg.buf.s[orig_len], (void *)&attr, sizeof(struct stun_attr));
528
+	
529
+	/* check if there is an odd number of unknown attributes and if yes, 
530
+	 * repeat one of them because of padding to 32
531
+	 */
532
+	if (counter/2 != 0 && unknown != NULL) {
533
+		if (buf_copy(&res->msg, (void *)&unknown->type, sizeof(USHORT_T))!=0) {
534
+			return FATAL_ERROR;
535
+		}
536
+	}	
537
+	
538
+	return 0;
539
+}
540
+
541
+/*
542
+ * add_error_code()
543
+ * 			- res: response representation
544
+ * 			- error_code: value of error type
545
+ * 
546
+ * The function add_error_code ensures copy of link list of unknown 
547
+ * attributes into response buffer.
548
+ * 
549
+ * Return value:	0	if there is no environment error
550
+ * 					-1	if there is some enviroment error such as insufficiency
551
+ * 						of memory
552
+ */
553
+int add_error_code(struct stun_msg* res, USHORT_T error_code)
554
+{
555
+	struct stun_attr attr;
556
+	USHORT_T	orig_len;
557
+	USHORT_T	two_bytes;
558
+	int			text_pad;
559
+	char		err[2];
560
+	
561
+	orig_len = res->msg.buf.len;
562
+	text_pad = 0;
563
+	
564
+	/* the type and length will be copy as last one because of unknown length*/
565
+	if (res->msg.buf.len < sizeof(struct stun_attr)) {
566
+		if (reallock_buffer(&res->msg, sizeof(struct stun_attr)) != 0) {
567
+			return FATAL_ERROR;
568
+		}
569
+	}
570
+	res->msg.buf.len += sizeof(struct stun_attr);
571
+	res->msg.empty -= sizeof(struct stun_attr);
572
+	
573
+	/* first two bytes are empty */
574
+	two_bytes = 0x0000;
575
+	
576
+	if (buf_copy(&res->msg, (void *) &two_bytes, sizeof(USHORT_T)) != 0) {
577
+		return FATAL_ERROR;
578
+	}
579
+	
580
+	err[0] = error_code / 100;
581
+	err[1] = error_code % 100;
582
+	if (buf_copy(&res->msg, (void *) err, sizeof(UCHAR_T)*2) != 0) {
583
+		return FATAL_ERROR;
584
+	}
585
+	
586
+	switch (error_code) {
587
+		case TRY_ALTERNATE_ERR:
588
+			text_pad = copy_str_to_buffer(res, TRY_ALTERNATE_TXT, PAD4); 
589
+			break;
590
+		case BAD_REQUEST_ERR:
591
+			text_pad = copy_str_to_buffer(res, BAD_REQUEST_TXT, PAD4); 
592
+			break;
593
+		case UNAUTHORIZED_ERR:
594
+			text_pad = copy_str_to_buffer(res, UNAUTHORIZED_TXT, PAD4); 
595
+			break;
596
+		case UNKNOWN_ATTRIBUTE_ERR:
597
+			text_pad = copy_str_to_buffer(res, UNKNOWN_ATTRIBUTE_TXT, PAD4);
598
+			break;
599
+		case STALE_CREDENTIALS_ERR:
600
+			text_pad = copy_str_to_buffer(res, STALE_CREDENTIALS_TXT, PAD4); 
601
+			break;
602
+		case INTEGRITY_CHECK_ERR:
603
+			text_pad = copy_str_to_buffer(res, INTEGRITY_CHECK_TXT, PAD4); 
604
+			break;
605
+		case MISSING_USERNAME_ERR:
606
+			text_pad = copy_str_to_buffer(res, MISSING_USERNAME_TXT, PAD4); 
607
+			break;
608
+		case USE_TLS_ERR:
609
+			text_pad = copy_str_to_buffer(res, USE_TLS_TXT, PAD4); 
610
+			break;
611
+		case MISSING_REALM_ERR:
612
+			text_pad = copy_str_to_buffer(res, MISSING_REALM_TXT, PAD4); 
613
+			break;
614
+		case MISSING_NONCE_ERR:
615
+			text_pad = copy_str_to_buffer(res, MISSING_NONCE_TXT, PAD4); 
616
+			break;
617
+		case UNKNOWN_USERNAME_ERR:
618
+			text_pad = copy_str_to_buffer(res, UNKNOWN_USERNAME_TXT, PAD4); 
619
+			break;
620
+		case STALE_NONCE_ERR:
621
+			text_pad = copy_str_to_buffer(res, STALE_NONCE_TXT, PAD4);
622
+			break;
623
+		case SERVER_ERROR_ERR:
624
+			text_pad = copy_str_to_buffer(res, SERVER_ERROR_TXT, PAD4); 
625
+			break;
626
+		case GLOBAL_FAILURE_ERR:
627
+			text_pad = copy_str_to_buffer(res, GLOBAL_FAILURE_TXT, PAD4); 
628
+			break;
629
+		default:
630
+			LOG(L_ERR, "ERROR: STUN: Unknown error code.\n");
631
+			break;
632
+	}
633
+	if (text_pad < 0) {
634
+		goto error;
635
+	}
636
+	attr.type = htons(ERROR_CODE_ATTR);
637
+	/* count length of "value" field -> without type and lehgth field */
638
+	attr.len = htons(res->msg.buf.len - orig_len - 
639
+					 text_pad - sizeof(struct stun_attr));
640
+	memcpy(&res->msg.buf.s[orig_len], (void *)&attr, sizeof(struct stun_attr));
641
+	
642
+	return 0;
643
+
644
+error:
645
+	return FATAL_ERROR;
646
+}
647
+
648
+/*
649
+ * copy_str_to_buffer()
650
+ * 			- res: response representation
651
+ * 			- data: text data, in our case almost text representation of error
652
+ * 			- pad: the size of pad (for how much bytes the string should be 
653
+ * 				   padded
654
+ * 
655
+ * The function copy_str_to_buffer ensures copy of text buffer into response
656
+ * buffer.
657
+ * 
658
+ * Return value:	0	if there is no environment error
659
+ * 					-1	if there is some enviroment error such as insufficiency
660
+ * 						of memory
661
+ */
662
+int copy_str_to_buffer(struct stun_msg* res, const char* data, UINT_T pad)
663
+{
664
+	USHORT_T	pad_len;
665
+	UINT_T		data_len;
666
+	UCHAR_T		empty[pad];
667
+	
668
+	data_len = strlen(data);
669
+	memset(&empty, 0, pad);
670
+	
671
+	pad_len = pad - data_len%pad;
672
+	
673
+	if (buf_copy(&res->msg, (void *) data, sizeof(UCHAR_T)*data_len) != 0) {
674
+		return FATAL_ERROR;
675
+	}
676
+	
677
+	if (pad_len != 0) {
678
+		if (buf_copy(&res->msg, &empty, pad_len) != 0) {
679
+			return FATAL_ERROR;
680
+		}	
681
+	}
682
+
683
+	return pad_len;	
684
+}
685
+
686
+/*
687
+ * stun_add_address_attr()
688
+ * 			- res: response representation
689
+ * 			- af: address family
690
+ * 			- port: port
691
+ * 			- ip_addr: represent both IPv4 and IPv6, the differences is in 
692
+ * 			length  
693
+ * 			- type: type of attribute
694
+ * 			- do_xor: if the port should be XOR-ed or not.
695
+ * 
696
+ * The function stun_add_address_attr ensures copy of any IP attribute into
697
+ * response buffer.
698
+ * 
699
+ * Return value:	0	if there is no environment error
700
+ * 					-1	if there is some enviroment error such as insufficiency
701
+ * 						of memory
702
+ */
703
+int stun_add_address_attr(struct stun_msg* res, 
704
+						UINT_T		af,
705
+						USHORT_T	port,
706
+						UINT_T*		ip_addr,
707
+						USHORT_T	type,
708
+						int do_xor)
709
+{
710
+	struct stun_attr attr;
711
+	UINT_T	 id[IP_ADDR];
712
+	int		 ip_struct_len;
713
+	int i;
714
+	
715
+	ip_struct_len = 0;
716
+	attr.type = htons(type);
717
+	res->ip_addr.port = (do_xor) ? htons(port) ^ MAGIC_COOKIE_2B : htons(port);
718
+	switch(af) {
719
+		case AF_INET:
720
+			ip_struct_len = sizeof(struct stun_ip_addr) - 3*sizeof(UINT_T);
721
+			res->ip_addr.family = htons(IPV4_FAMILY);
722
+			memcpy(res->ip_addr.ip, ip_addr, IPV4_LEN);
723
+			res->ip_addr.ip[0] = (do_xor) ? 
724
+					res->ip_addr.ip[0] ^ MAGIC_COOKIE : res->ip_addr.ip[0];		
725
+			break;
726
+#ifdef USE_IPV6
727
+		case AF_INET6:
728
+			ip_struct_len = sizeof(struct stun_ip_addr);
729
+			res->ip_addr.family = htons(IPV6_FAMILY);
730
+			memcpy(&res->ip_addr.ip, ip_addr, IPV6_LEN);
731
+			memcpy(id, &res->hdr.id, sizeof(struct transaction_id));
732
+			for (i=0; i<IP_ADDR; i++) {
733
+				res->ip_addr.ip[i] = (do_xor) ? 
734
+							res->ip_addr.ip[i] ^ id[i] : res->ip_addr.ip[i];
735
+			}
736
+			break;
737
+#endif /* USE_IPV6 */ 
738
+		default:
739
+			break;
740
+	}
741
+	
742
+	attr.len = htons(ip_struct_len);
743
+	
744
+	/* copy type and attribute's length */ 
745
+	if (buf_copy(&res->msg, (void *) &attr, sizeof(struct stun_attr)) != 0) {
746
+		return FATAL_ERROR;
747
+	}
748
+	
749
+	/* copy family, port and IP */
750
+	if (buf_copy(&res->msg, (void *) &res->ip_addr, ip_struct_len) != 0) {
751
+		return FATAL_ERROR;
752
+	}
753
+
754
+	return 0;
755
+}
756
+
757
+/*
758
+ * add_fingerprint()
759
+ * 			- msg: response buffer
760
+ * 
761
+ * The function add_fingerprint ensures adding fingerprint attribute into
762
+ * response buffer.
763
+ * 
764
+ * Return value:	0	if there is no environment error
765
+ * 					-1	if there is some enviroment error such as insufficiency
766
+ * 						of memory
767
+ */
768
+int add_fingerprint(struct stun_buffer* msg)
769
+{
770
+	struct stun_attr attr;
771
+	USHORT_T attr_type_size;
772
+	
773
+	attr_type_size = sizeof(struct stun_attr);
774
+	attr.type = htons(FINGERPRINT_ATTR);
775
+	attr.len = htons(SHA_DIGEST_LENGTH);
776
+	
777
+	if (msg->empty < (SHA_DIGEST_LENGTH + attr_type_size)) {
778
+		if (reallock_buffer(msg, SHA_DIGEST_LENGTH + attr_type_size) != 0) {
779
+			return FATAL_ERROR;
780
+		}
781
+	}
782
+	
783
+	memcpy(&msg->buf.s[msg->buf.len], (void *) &attr, attr_type_size);	
784
+	msg->buf.len += attr_type_size;
785
+	msg->empty -= attr_type_size;
786
+	
787
+	if (SHA1((UCHAR_T *)msg->buf.s, msg->buf.len-attr_type_size, 
788
+			 (UCHAR_T *) &msg->buf.s[msg->buf.len]) == 0) {
789
+		LOG(L_ERR, "ERROR: STUN: SHA-1 algorithm failed.\n");
790
+		return FATAL_ERROR;
791
+	}
792
+	
793
+	msg->buf.len += SHA_DIGEST_LENGTH;
794
+	msg->empty -= SHA_DIGEST_LENGTH;
795
+	
796
+	return 0;
797
+}
798
+
799
+/*
800
+ * stun_alloc_unknown_attr()
801
+ * 			- type: type of unknown attribute
802
+ * 
803
+ * The function stun_alloc_unknown_attr ensures allocationg new element for
804
+ * the link list of unknown attributes.
805
+ * 
806
+ * Return value: pointer to new element of link list in positive case
807
+ * 				 NULL if there is some enviroment error such as insufficiency
808
+ * 						of memory
809
+ */
810
+struct stun_unknown_att* stun_alloc_unknown_attr(USHORT_T type)
811
+{
812
+	struct stun_unknown_att* attr;
813
+
814
+	attr = (struct stun_unknown_att *) pkg_malloc(sizeof(struct stun_unknown_att));
815
+	if (attr == NULL) {
816
+		LOG(L_ERR, "ERROR: STUN: out of memory\n");
817
+		return NULL;
818
+	}
819
+	
820
+	attr->type = type;
821
+	attr->next = NULL;
822
+	
823
+	return attr;
824
+}
825
+
826
+/*
827
+ * stun_delete_unknown_attrs()
828
+ * 			- unknown: link list of unknown attributes
829
+ * 
830
+ * The function stun_delete_unknown_attrs ensures deleting of link list
831
+ * 
832
+ * Return value: none
833
+ */
834
+void stun_delete_unknown_attrs(struct stun_unknown_att* unknown)
835
+{
836
+	struct stun_unknown_att* tmp_unknown;
837
+	
838
+	if (unknown == NULL) {
839
+		return;
840
+	}
841
+	
842
+	while(unknown->next) {
843
+		tmp_unknown = unknown->next;
844
+		unknown->next = tmp_unknown->next;
845
+		pkg_free(tmp_unknown);		
846
+	}
847
+	pkg_free(unknown);
848
+}
849
+
850
+/*
851
+ * validate_fingerprint()
852
+ * 			- req: structure representing request message
853
+ * 			- error_code: indication of any protocol error
854
+ * 
855
+ * The function validate_fingerprint ensures validation of FINGERPRINT
856
+ * attribute.
857
+ * 
858
+ * Return value:	0	if there is no environment error
859
+ * 					-1	if there is some enviroment error such as insufficiency
860
+ * 						of memory
861
+ */
862
+int validate_fingerprint(struct stun_msg* req, USHORT_T* error_code)
863
+{
864
+	UCHAR_T	msg_digest[SHA_DIGEST_LENGTH];
865
+	UINT_T	buf_len; 
866
+	
867
+	buf_len = req->hdr.len+sizeof(struct stun_hdr);
868
+	
869
+	if (SHA1((UCHAR_T *) req->msg.buf.s, buf_len, msg_digest) == 0) {
870
+		LOG(L_ERR, "ERROR: STUN: SHA-1 algorithm failed.\n");
871
+		return FATAL_ERROR;
872
+	} 
873
+	
874
+	if (memcmp((void *)req->fp, (void *)&msg_digest, SHA_DIGEST_LENGTH) != 0) {
875
+		*error_code = BAD_REQUEST_ERR;
876
+	}
877
+	
878
+	return 0;	
879
+}
880
+
881
+/*
882
+ * buf_copy()
883
+ * 			- msg: buffer where the data will be copy to
884
+ * 			- source: source data buffer
885
+ * 			- len: number of bytes that should be copied
886
+ * 
887
+ * The function buf_copy copies "len" bytes from source into msg buffer
888
+ * 
889
+ * Return value:	0	if there is no environment error
890
+ * 					-1	if there is some enviroment error such as insufficiency
891
+ * 						of memory
892
+ */
893
+int buf_copy(struct stun_buffer* msg, void* source, UINT_T len)
894
+{
895
+	if (msg->empty < len) {
896
+		if (reallock_buffer(msg, len) != 0) {
897
+			return FATAL_ERROR;
898
+		}
899
+	}
900
+	
901
+	memcpy(&msg->buf.s[msg->buf.len], source, len);
902
+	msg->buf.len += len;
903
+	msg->empty -= len;
904
+	
905
+	return 0;
906
+}
907
+
908
+/*
909
+ * reallock_buffer()
910
+ * 			- buffer: original buffer
911
+ * 			- len: represents minimum of bytes that must be available after 
912
+ * 					reallocation
913
+ * 
914
+ * The function reallock_buffer reallocks buffer. New buffer's length will be 
915
+ * original length plus bigger from len and STUN_MSG_LEN constant.
916
+ * 
917
+ * Return value:	0	if there is no environment error
918
+ * 					-1	if there is some enviroment error such as insufficiency
919
+ * 						of memory
920
+ */
921
+int reallock_buffer(struct stun_buffer* buffer, UINT_T len)
922
+{
923
+	char*	tmp_buf;
924
+	UINT_T	new_len;
925
+	
926
+	new_len = (STUN_MSG_LEN < len) ? STUN_MSG_LEN+len : STUN_MSG_LEN;
927
+	
928
+	tmp_buf = (char *) pkg_realloc(buffer->buf.s, 
929
+								   buffer->buf.len + buffer->empty + new_len);
930
+	if (tmp_buf == 0) {
931
+		LOG(L_ERR, "ERROR: STUN: out of memory\n");
932
+		return FATAL_ERROR;
933
+	}
934
+	
935
+	buffer->buf.s = tmp_buf;
936
+	buffer->empty += new_len;
937
+
938
+	return 0;
939
+}
940
+
941
+/*
942
+ * clean_memory()
943
+ * 			- res: structure representing response message
944
+ * 			- unknown: link list of unknown attributes
945
+ * 
946
+ * The function clean_memory should free dynamic allocated memory.
947
+ * 
948
+ * Return value: none
949
+ */
950
+void clean_memory(struct stun_msg* req,
951
+				struct stun_msg* res,	struct stun_unknown_att* unknown)
952
+{
953
+#ifdef DYN_BUF
954
+	pkg_free(req->msg.buf.s);
955
+#endif
956
+
957
+	if (res->msg.buf.s != NULL) {
958
+		pkg_free(res->msg.buf.s);
959
+	}
960
+	stun_delete_unknown_attrs(unknown);
961
+}
962
+
963
+/*
964
+ * stun_add_common_integer_attr()
965
+ * 			- res: structure representing response
966
+ * 			- type: type of attribute
967
+ * 			- value: attribute's value
968
+ * 
969
+ * The function stun_add_common_integer_attr copy attribute with integer value 
970
+ * into response buffer.
971
+ * 
972
+ * Return value:	0	if there is no environment error
973
+ * 					-1	if there is some enviroment error such as insufficiency
974
+ * 						of memory
975
+ */
976
+int stun_add_common_integer_attr(struct stun_msg* res, 
977
+								 USHORT_T type, 
978
+								 UINT_T value)
979
+{
980
+	struct stun_attr attr;
981
+	
982
+	attr.type = htons(type);
983
+	attr.len = htons(sizeof(UINT_T));
984
+	
985
+	if (buf_copy(&res->msg, (void *) &attr, sizeof(struct stun_attr)) != 0) {
986
+		return FATAL_ERROR;
987
+	}
988
+	
989
+	value = htonl(value);
990
+	if (buf_copy(&res->msg, (void *) &value, sizeof(UINT_T)) != 0) {
991
+		return FATAL_ERROR;
992
+	}
993
+	
994
+	return 0;
995
+}
996
+
997
+/*
998
+ * stun_add_common_text_attr()
999
+ * 			- res: structure representing response
1000
+ * 			- type: type of attribute
1001
+ * 			- value: attribute's value
1002
+ * 			- pad: size of pad
1003
+ * 
1004
+ * The function stun_add_common_text_attr copy attribute with string value 
1005
+ * into response buffer.
1006
+ * 
1007
+ * Return value:	0	if there is no environment error
1008
+ * 					-1	if there is some enviroment error such as insufficiency
1009
+ * 						of memory
1010
+ */
1011
+int stun_add_common_text_attr(struct stun_msg* res, 
1012
+							  USHORT_T type, 
1013
+							  char* value, 
1014
+							  USHORT_T pad)
1015
+{
1016
+	struct stun_attr attr;
1017
+	
1018
+	if (value == NULL) {
1019
+		LOG(L_INFO, "INFO: stun_add_common_text_attr: value is NULL\n");
1020
+		return 0;
1021
+	}
1022
+	
1023
+	attr.type = htons(type);
1024
+	attr.len = htons(strlen(value));
1025
+	
1026
+	if (buf_copy(&res->msg, (void *) &attr, sizeof(struct stun_attr)) != 0) {
1027
+		return FATAL_ERROR;
1028
+	}
1029
+	
1030
+	if (copy_str_to_buffer(res, value, pad) < 0) {
1031
+		return FATAL_ERROR;
1032
+	}
1033
+	
1034
+	return 0;
1035
+	
1036
+}
1037
+
1038
+#endif  /* USE_STUN */
1039
+
1040
+
1041
+
1042
+
1043
+
1044
+
1045
+
1046
+
1047
+
1048
+
1049
+
1050
+
1051
+
1052
+
1053
+
1054
+
1055
+
1056
+
1057
+
1058
+
1059
+
1060
+
1061
+
1062
+
1063
+
1064
+
1065
+
1066
+
1067
+
1068
+
1069
+
1070
+
1071
+
1072
+
1073
+
1074
+
1075
+
1076
+
1077
+
1078
+
1079
+
0 1080
new file mode 100644
... ...
@@ -0,0 +1,184 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * Copyright (C) 2001-2003 FhG Fokus
4
+ *
5
+ * This file is part of ser, a free SIP server.
6
+ *
7
+ * ser is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version
11
+ *
12
+ * For a license to use the ser software under conditions
13
+ * other than those described here, or to purchase support for this
14
+ * software, please contact iptel.org by e-mail at the following addresses:
15
+ *    info@iptel.org
16
+ *
17
+ * ser is distributed in the hope that it will be useful,
18
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
+ * GNU General Public License for more details.
21
+ *
22
+ * You should have received a copy of the GNU General Public License
23
+ * along with this program; if not, write to the Free Software
24
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25
+ *
26
+ *
27
+ * History:
28
+ * --------
29
+ *  2006-10-13  created (vlada)
30
+ */
31
+
32
+
33
+#ifndef _ser_stun_h
34
+#define _ser_stun_h
35
+
36
+#ifdef USE_STUN
37
+
38
+#include <openssl/sha.h>
39
+
40
+#include "str.h"
41
+#include "tcp_conn.h"
42
+#include "ip_addr.h"
43
+
44
+/* type redefinition */
45
+typedef unsigned char	UCHAR_T;
46
+typedef unsigned short USHORT_T;
47
+typedef unsigned int	UINT_T;
48
+typedef unsigned long	ULONG_T;
49
+
50
+/* STUN message types supported by SER */
51
+#define BINDING_REQUEST			0x0001
52
+#define BINDING_RESPONSE		0x0101
53
+#define BINDING_ERROR_RESPONSE	0x0111
54
+
55
+/* common STUN attributes */
56
+#define MAPPED_ADDRESS_ATTR		0x0001
57
+#define USERNAME_ATTR			0x0006
58
+#define PASSWORD_ATTR			0x0007
59
+#define MESSAGE_INTEGRITY_ATTR	0x0008
60
+#define ERROR_CODE_ATTR			0x0009
61
+#define UNKNOWN_ATTRIBUTES_ATTR	0x000A
62
+
63
+/* STUN attributes defined by rfc3489bis */
64
+#define REALM_ATTR				0x0014
65
+#define NONCE_ATTR				0x0015
66
+#define XOR_MAPPED_ADDRESS_ATTR	0x0020 
67
+#define FINGERPRINT_ATTR		0x0023
68
+#define SERVER_ATTR				0x8022
69
+#define ALTERNATE_SERVER_ATTR	0x8023
70
+#define REFRESH_INTERVAL_ATTR	0x8024
71
+
72
+/* STUN attributes defined by rfc3489 */
73
+#define RESPONSE_ADDRESS_ATTR	0x0002
74
+#define CHANGE_REQUEST_ATTR		0x0003
75
+#define SOURCE_ADDRESS_ATTR		0x0004
76
+#define CHANGED_ADDRESS_ATTR	0x0005
77
+#define REFLECTED_FROM_ATTR		0x000b
78
+
79
+/* STUN error codes supported by SER */
80
+#define RESPONSE_OK				200
81
+#define TRY_ALTERNATE_ERR		300
82
+#define BAD_REQUEST_ERR			400
83
+#define UNAUTHORIZED_ERR		401
84
+#define UNKNOWN_ATTRIBUTE_ERR	420
85
+#define STALE_CREDENTIALS_ERR	430
86
+#define INTEGRITY_CHECK_ERR		431
87
+#define MISSING_USERNAME_ERR	432
88
+#define USE_TLS_ERR				433
89
+#define MISSING_REALM_ERR		434
90
+#define MISSING_NONCE_ERR		435
91
+#define UNKNOWN_USERNAME_ERR	436
92
+#define STALE_NONCE_ERR			438
93
+#define SERVER_ERROR_ERR		500
94
+#define GLOBAL_FAILURE_ERR		600
95
+
96
+#define TRY_ALTERNATE_TXT 		"The client should contact an alternate server for this request."
97
+#define BAD_REQUEST_TXT			"The request was malformed. The client should not retry the request without modification from the previous attempt."
98
+#define UNAUTHORIZED_TXT		"The request did not contain a MESSAGE-INTEGRITY attribute."
99
+#define UNKNOWN_ATTRIBUTE_TXT	"The server did not understand a mandatory attribute in the request."
100
+#define STALE_CREDENTIALS_TXT	"The request did contain a MESSAGE-INTEGRITY attribute, but it used a shared secret that has expired. The client should obtain a new shared secret and try again."
101
+#define INTEGRITY_CHECK_TXT		"The request contained a MESSAGE-INTEGRITY attribute, but the HMAC failed verification. This could be a sign of a potential attack, or client implementation error."
102
+#define MISSING_USERNAME_TXT	"The request contained a MESSAGE-INTEGRITY attribute, but not a USERNAME attribute.  Both USERNAME and MESSAGE-INTEGRITY must be present for integrity checks."
103
+#define USE_TLS_TXT				"The Shared Secret request has to be sent over TLS, but was not received over TLS."
104
+#define MISSING_REALM_TXT		"The REALM attribute was not present in the request."
105
+#define MISSING_NONCE_TXT		"The NONCE attribute was not present in the request."
106
+#define UNKNOWN_USERNAME_TXT	"The USERNAME supplied in the request is not known or is not known to the server."
107
+#define STALE_NONCE_TXT			"The NONCE attribute was present in the request but wasn't valid."
108
+#define SERVER_ERROR_TXT		"The server has suffered a temporary error. The client should try again."
109
+#define GLOBAL_FAILURE_TXT		"The server is refusing to fulfill the request. The client should not retry."
110
+
111
+
112
+/* other stuff */
113
+#define MAGIC_COOKIE	0x2112A442
114
+#define MAGIC_COOKIE_2B 0x2112	/* because of XOR for port */
115
+#define MANDATORY_ATTR	0x7fff
116
+#define PAD4			4
117
+#define PAD64			64
118
+#define STUN_MSG_LEN	516
119
+#define IPV4_LEN		4
120
+#define IPV6_LEN		16
121
+#define IPV4_FAMILY		0x0001
122
+#define IPV6_FAMILY		0x0002
123
+#define	FATAL_ERROR		-1
124
+#define IP_ADDR			4
125
+#define XOR				1
126
+#define TRANSACTION_ID	12
127
+
128
+#define PADDED_TO_FOUR(len) (len == 0) ? 0 : len + (PAD4 - len%PAD4)
129
+#define PADDED_TO_SIXTYFOUR(len) (len == 0) ? 0 : len + (PAD64 - len%PAD64)
130
+
131
+struct transaction_id {
132
+	UINT_T	magic_cookie;
133
+	UCHAR_T	id[TRANSACTION_ID];
134
+};
135
+
136
+struct stun_hdr {
137
+	USHORT_T				type;
138
+	USHORT_T				len;
139
+	struct transaction_id	id;
140
+};
141
+
142
+struct stun_ip_addr {
143
+	USHORT_T	family; /* 0x01: IPv4; 0x02: IPv6 */
144
+	USHORT_T	port;
145
+	UINT_T		ip[IP_ADDR];
146
+};
147
+
148
+struct stun_buffer {
149
+	str			buf;
150
+	USHORT_T	empty;	/* number of free bytes in buf before 
151
+						 * it'll be necessary to realloc the buf 
152
+						 */
153
+};
154
+
155
+struct stun_unknown_att {
156
+	USHORT_T					type;
157
+	struct stun_unknown_att*	next;
158
+};
159
+
160
+struct stun_attr {
161
+	USHORT_T	type;
162
+	USHORT_T	len;
163
+};
164
+
165
+struct stun_msg {
166
+	struct stun_hdr			hdr;
167
+	struct stun_ip_addr		ip_addr;		/* XOR values for rfc3489bis, 
168
+											normal values for rfc3489 */
169
+	char					fp[SHA_DIGEST_LENGTH];		/* fingerprint value */
170
+	struct stun_buffer		msg;
171
+	UCHAR_T					old;		/* true: the format of message is in 
172
+										accordance with rfc3489 */ 
173
+};
174
+
175
+
176
+/*
177
+ * stun functions called from ser
178
+ */
179
+int stun_process_msg(char* buf, unsigned len, struct receive_info* ri);
180
+
181
+#endif /* USE_STUN */
182
+