1 /*
2  * Copyright (c) 2015 Intel Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /* Various utility functions taken from libcoap with this license:
18 
19 Copyright (c) 2010--2015, Olaf Bergmann
20 All rights reserved.
21 
22 Redistribution and use in source and binary forms, with or without
23 modification, are permitted provided that the following conditions are
24 met:
25 
26   o Redistributions of source code must retain the above copyright
27     notice, this list of conditions and the following disclaimer.
28 
29   o Redistributions in binary form must reproduce the above copyright
30     notice, this list of conditions and the following disclaimer in
31     the documentation and/or other materials provided with the
32     distribution.
33 
34 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
35 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
36 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
37 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
38 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
39 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
40 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
41 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
42 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
43 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
44 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45 */
46 
47 #include <stdio.h>
48 #include <sys/socket.h>
49 #include <netinet/in.h>
50 #include <poll.h>
51 #include <errno.h>
52 #include <arpa/inet.h>
53 #include <stdlib.h>
54 #include <string.h>
55 #include <stdbool.h>
56 #include <net/if.h>
57 #include <linux/sockios.h>
58 #include <ifaddrs.h>
59 #include <signal.h>
60 #include <sys/ioctl.h>
61 #include <unistd.h>
62 
63 #include <tinydtls.h>
64 #include <global.h>
65 #include <debug.h>
66 #include <dtls.h>
67 
68 /* tinyDTLS and libcoap have same preprocessor symbols defined in their
69  * include files so undef conflicting symbols here.
70  */
71 #undef PACKAGE_BUGREPORT
72 #undef PACKAGE_NAME
73 #undef PACKAGE_STRING
74 #undef PACKAGE_TARNAME
75 #undef PACKAGE_URL
76 #undef PACKAGE_VERSION
77 #undef UTHASH_VERSION
78 #undef HASH_FIND
79 #undef HASH_ADD
80 #undef HASH_ADD_KEYPTR
81 #undef HASH_DELETE
82 #undef HASH_FIND_STR
83 #undef HASH_ADD_STR
84 #undef HASH_BER
85 #undef HASH_FNV
86 #undef HASH_JEN
87 #undef HASH_SFH
88 #undef HASH_FIND_IN_BKT
89 #undef HASH_SRT
90 #undef HASH_CLEAR
91 #undef UTLIST_VERSION
92 #undef _NEXT
93 #undef _NEXTASGN
94 #undef _PREVASGN
95 #undef LL_SORT
96 #undef DL_SORT
97 #undef CDL_SORT
98 #undef LL_PREPEND
99 #undef LL_APPEND
100 #undef LL_DELETE
101 #undef LL_APPEND_VS2008
102 #undef LL_DELETE_VS2008
103 #undef LL_FOREACH
104 #undef LL_FOREACH_SAFE
105 #undef LL_SEARCH_SCALAR
106 #undef LL_SEARCH
107 #undef DL_PREPEND
108 #undef DL_APPEND
109 #undef DL_DELETE
110 #undef DL_FOREACH
111 #undef DL_FOREACH_SAFE
112 #undef CDL_PREPEND
113 #undef CDL_DELETE
114 #undef CDL_FOREACH
115 #undef CDL_FOREACH_SAFE
116 #undef CDL_SEARCH_SCALAR
117 #undef CDL_SEARCH
118 #define UTHASH_H
119 
120 #include <coap/coap.h>
121 
122 typedef struct coap_list_t {
123 	struct coap_list_t *next;
124 	char data[];
125 } coap_list_t;
126 
127 #ifdef __GNUC__
128 #define UNUSED_PARAM __attribute__((unused))
129 #else
130 #define UNUSED_PARAM
131 #endif /* __GNUC__ */
132 
133 #define SERVER_PORT        5683
134 #define SERVER_SECURE_PORT 5684
135 
136 #define CLIENT_PORT  8484
137 #define MAX_BUF_SIZE 1280	/* min IPv6 MTU, the actual data is smaller */
138 #define MAX_TIMEOUT  6		/* in seconds */
139 
140 static bool debug;
141 static int renegotiate = -1;
142 static session_t session;
143 static bool no_dtls;
144 static const char *target;
145 static int family;
146 
147 static coap_block_t block = {
148 	.num = 0,
149 	.m = 0,
150 	.szx = 6
151 };
152 static unsigned int wait_seconds = MAX_TIMEOUT; /* default timeout in secs */
153 static coap_tick_t max_wait;
154 static unsigned int obs_seconds = MAX_TIMEOUT * 2; /* default observe time */
155 static coap_tick_t obs_wait = 0;	/* timeout for current subscription */
156 static int ready = 0;
157 static coap_list_t *optlist;
158 static unsigned char _token_data[8];
159 static str the_token = { 0, _token_data };
160 typedef unsigned char method_t;
161 static str payload = { 0, NULL }; /* optional payload to send */
162 static int flags = 0;
163 #define FLAGS_BLOCK 0x01
164 static method_t method;
165 
166 static coap_pdu_t *coap_new_request(coap_context_t *ctx,
167 				    method_t m,
168 				    coap_list_t **options,
169 				    const unsigned char *data,
170 				    size_t length,
171 				    int msgtype);
172 
173 #define ENTRY(desc, entry, expect_result, method, test_data, length, mid,\
174 	      confirmed)						\
175 	{								\
176 		.description = #desc ,					\
177 		.len = sizeof(entry),					\
178 		.buf = entry,						\
179 		.expecting_reply = expect_result,			\
180 		.data = test_data,					\
181 		.data_len = length,					\
182 		.coap_method = COAP_REQUEST_ ## method,			\
183 		.check_mid = mid,					\
184 		.message_type = confirmed,				\
185 	}
186 
187 #define ENTRY2(desc, entry, expect_result, method, test_data, length, \
188 	       test_payload, test_payload_len, mid, confirmed)		\
189 	{								\
190 		.description = #desc ,					\
191 		.len = sizeof(entry),					\
192 		.buf = entry,						\
193 		.expecting_reply = expect_result,			\
194 		.data = test_data,					\
195 		.data_len = length,					\
196 		.payload = test_payload,				\
197 		.payload_len = test_payload_len,			\
198 		.coap_method = COAP_REQUEST_ ## method,			\
199 		.check_mid = mid,					\
200 		.message_type = confirmed,				\
201 	}
202 
203 #define ENTRY3(desc, entry, expect_result, method, test_data, length, mid,\
204 	      confirmed)						\
205 	{								\
206 		.description = #desc ,					\
207 		.len = sizeof(entry),					\
208 		.buf = entry,						\
209 		.expecting_reply = expect_result,			\
210 		.data = test_data,					\
211 		.data_len = length,					\
212 		.coap_method = COAP_REQUEST_ ## method,			\
213 		.check_mid = mid,					\
214 		.message_type = confirmed,				\
215 		.add_token = true,					\
216 	}
217 
218 #define ENTRY4(desc, entry, expect_result, method, test_data, length, \
219 	       test_payload, test_payload_len, mid, confirmed)		\
220 	{								\
221 		.description = #desc ,					\
222 		.len = sizeof(entry),					\
223 		.buf = entry,						\
224 		.expecting_reply = expect_result,			\
225 		.data = test_data,					\
226 		.data_len = length,					\
227 		.payload = test_payload,				\
228 		.payload_len = test_payload_len,			\
229 		.coap_method = COAP_REQUEST_ ## method,			\
230 		.check_mid = mid,					\
231 		.message_type = confirmed,				\
232 		.add_token = true,					\
233 	}
234 
235 #define GET_CON(desc, e, r, c) ENTRY(desc, e, true, GET, r, sizeof(r), c, \
236 				 COAP_MESSAGE_CON)
237 #define POST_CON(desc, e, r, c) ENTRY(desc, e, true, POST, r, sizeof(r), c, \
238 				  COAP_MESSAGE_CON)
239 #define PUT_CON(desc, e, d, p, c) ENTRY2(desc, e, true, PUT, d, sizeof(d), \
240 					p, sizeof(p), c, COAP_MESSAGE_CON)
241 #define DELETE_CON(desc,e, r, c) ENTRY(desc, e, true, DELETE, r, sizeof(r), c,\
242 				   COAP_MESSAGE_CON)
243 
244 #define GET_NON(desc, e, r, c) ENTRY(desc, e, true, GET, r, sizeof(r), c, \
245 				     COAP_MESSAGE_NON)
246 #define POST_NON(desc, e, r, c) ENTRY(desc, e, true, POST, r, sizeof(r), c, \
247 				      COAP_MESSAGE_NON)
248 #define PUT_NON(desc, e, d, p, c) ENTRY2(desc, e, true, PUT, d, sizeof(d), \
249 					 p, sizeof(p), c, COAP_MESSAGE_NON)
250 #define DELETE_NON(desc,e, r, c) ENTRY(desc, e, true, DELETE, r, sizeof(r), c,\
251 				       COAP_MESSAGE_NON)
252 
253 #define GET_CON_TOKEN(desc, e, r, c) ENTRY3(desc, e, true, GET, r, sizeof(r), \
254 					    c, COAP_MESSAGE_CON)
255 #define POST_CON_TOKEN(desc, e, r, c) ENTRY3(desc, e, true, POST, r,	\
256 					     sizeof(r), c, COAP_MESSAGE_CON)
257 #define PUT_CON_TOKEN(desc, e, d, p, c) ENTRY4(desc, e, true, PUT, d, \
258 					       sizeof(d), p, sizeof(p), c,\
259 					       COAP_MESSAGE_CON)
260 #define DELETE_CON_TOKEN(desc,e, r, c) ENTRY3(desc, e, true, DELETE, r, \
261 					      sizeof(r), c, COAP_MESSAGE_CON)
262 
263 #define GET_CON_PAYLOAD(desc, e, d, p, c) ENTRY2(desc, e, true, GET, \
264 						 d, sizeof(d), \
265 						 p, sizeof(p), c, \
266 						 COAP_MESSAGE_CON)
267 
268 #define RES(var, path)	\
269 	static const char res_ ## var [] = path ;
270 
271 #define DATA_ARRAY(var, data, ...) \
272 	static const char var [] = { data, __VA_ARGS__ } ;
273 
274 #define DATA_STRING(var, data) \
275 	static const char var [] = data;
276 
277 RES(core, ".well-known/core");
278 RES(test, "test");
279 RES(seg, "seg1/seg2/seg3");
280 RES(query, "query");
281 
282 /* See this test specification document for different test descriptions
283  * http://www.etsi.org/plugtests/CoAP/Document/CoAP_TestDescriptions_v015.pdf
284  */
285 DATA_STRING(get_con, "Type: 0\nCode: 1\n");
286 DATA_STRING(post_con, "Type: 0\nCode: 2\n");
287 DATA_STRING(put_con, "Type: 0\nCode: 3\n");
288 DATA_STRING(delete_con, "Type: 0\nCode: 4\n");
289 DATA_STRING(get_non, "Type: 1\nCode: 1\n");
290 DATA_STRING(post_non, "Type: 1\nCode: 2\n");
291 DATA_STRING(put_non, "Type: 1\nCode: 3\n");
292 DATA_STRING(delete_non, "Type: 1\nCode: 4\n");
293 
294 /* Generated by http://www.lipsum.com/
295  * 1202 bytes of Lorem Ipsum.
296  *
297  * This is the maximum we can send with encryption.
298  */
299 static const char lorem_ipsum[] =
300 	"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin congue orci et lectus ultricies, sed elementum urna finibus. Nam bibendum, massa id sollicitudin finibus, massa ante pharetra lacus, nec semper felis metus eu massa. Curabitur gravida, neque a pulvinar suscipit, felis massa maximus neque, eu sagittis felis enim nec justo. Suspendisse sit amet sem a magna aliquam tincidunt. Mauris consequat ante in consequat auctor. Nam eu congue mauris, congue aliquet metus. Etiam elit ipsum, vehicula et lectus at, dignissim accumsan turpis. Sed magna nisl, tempor ut dolor sed, feugiat pharetra velit. Nulla sed purus at elit dapibus lobortis. In hac habitasse platea dictumst. Praesent quis libero id enim aliquet viverra eleifend non urna. Vivamus metus justo, dignissim eget libero molestie, tincidunt pellentesque purus. Quisque pulvinar, nisi sed egestas vestibulum, ante felis elementum justo, ut viverra nisl est sagittis leo. Curabitur pharetra eros at felis ultricies efficitur."
301 	"\n"
302 	"Ut rutrum urna vitae neque rhoncus, id dictum ex dictum. Suspendisse venenatis vel mauris sed maximus. Sed malesuada elit vel neque hendrerit, in accumsan odio sodales. Aliquam erat volutpat. Praesent non situ.\n";
303 
304 static const char lorem_ipsum_short[] = "Lorem ipsum dolor sit amet.";
305 
306 static struct data {
307 	const char *description;
308 	int len;
309 	method_t coap_method;
310 	const unsigned char *buf;
311 	bool expecting_reply;
312 	const unsigned char *data; /* data to be sent */
313 	int data_len;
314 	const unsigned char *payload; /* possible payload to be sent */
315 	int payload_len;
316 	bool check_mid;
317 	int expected_mid; /* message id we sent */
318 	int message_type;
319 	bool add_token;
320 } data[] = {
321 	GET_CON(TD_COAP_CORE_01, res_test, get_con, true),
322 	POST_CON(TD_COAP_CORE_02, res_test, post_con, false),
323 	PUT_CON(TD_COAP_CORE_03, res_test, put_con, lorem_ipsum, false),
324 	DELETE_CON(TD_COAP_CORE_04, res_test, delete_con, false),
325 
326 	GET_NON(TD_COAP_CORE_05, res_test, get_non, true),
327 	POST_NON(TD_COAP_CORE_06, res_test, post_non, false),
328 	PUT_NON(TD_COAP_CORE_07, res_test, put_non, lorem_ipsum, false),
329 	DELETE_NON(TD_COAP_CORE_08, res_test, delete_non, false),
330 
331 	/* /separate not supported atm */
332 	//GET_CON(TD_COAP_CORE_09, res_separate, get_con, true),
333 
334 	GET_CON_TOKEN(TD_COAP_CORE_10, res_test, get_con, true),
335 
336 	/* Isn't test case 11 same as test case 01? */
337 	GET_CON(TD_COAP_CORE_11, res_test, get_con, true),
338 
339 	GET_CON(TD_COAP_CORE_12, res_seg, get_con, true),
340 	GET_CON(TD_COAP_CORE_13, res_query, get_con, true),
341 
342 	/* Test 14 & 15 are for testing gateway scenario so not used here */
343 	// TD_COAP_CORE_14
344 	// TD_COAP_CORE_15
345 
346 	/* /separate not supported atm */
347 	//GET_NON(TD_COAP_CORE_16, res_separate, get_con, true),
348 
349 #if TO_BE_DONE
350 	GET_CON(TD_COAP_LINK_01, res_core, get_con, true),
351 	//TD_COAP_LINK_02
352 
353 	// TD_COAP_BLOCK_01
354 	// TD_COAP_BLOCK_02
355 	// TD_COAP_BLOCK_03
356 	// TD_COAP_BLOCK_04
357 
358 	// TD_COAP_OBS_01
359 	// TD_COAP_OBS_02
360 	// TD_COAP_OBS_03
361 	// TD_COAP_OBS_04
362 	// TD_COAP_OBS_05
363 #endif
364 
365 	{ 0, 0 }
366 };
367 
368 struct client_data {
369 	bool fail;
370 	int fd;
371 	int index; /* position in data[] */
372 	int ifindex; /* network interface index */
373 	coap_context_t *coap_ctx;
374 	coap_address_t coap_dst;
375 	int len;
376 #define MAX_READ_BUF 2000
377 	uint8 buf[MAX_READ_BUF];
378 };
379 static struct client_data *test_context;
380 
set_coap_timeout(coap_tick_t * timer,const unsigned int seconds)381 static void set_coap_timeout(coap_tick_t *timer, const unsigned int seconds)
382 {
383 	coap_ticks(timer);
384 	*timer += seconds * COAP_TICKS_PER_SECOND;
385 }
386 
get_ifindex(const char * name)387 static int get_ifindex(const char *name)
388 {
389 	struct ifreq ifr;
390 	int sk, err;
391 
392 	if (!name)
393 		return -1;
394 
395 	sk = socket(PF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
396 	if (sk < 0)
397 		return -1;
398 
399 	memset(&ifr, 0, sizeof(ifr));
400 	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name) - 1);
401 
402 	err = ioctl(sk, SIOCGIFINDEX, &ifr);
403 
404 	close(sk);
405 
406 	if (err < 0)
407 		return -1;
408 
409 	return ifr.ifr_ifindex;
410 }
411 
find_address(int family,struct ifaddrs * if_address,const char * if_name,void * address)412 static int find_address(int family, struct ifaddrs *if_address,
413 			const char *if_name, void *address)
414 {
415 	struct ifaddrs *tmp;
416 	struct sockaddr_in6 *ll = NULL;
417 	int error = -ENOENT;
418 
419 	for (tmp = if_address; tmp; tmp = tmp->ifa_next) {
420 		if (tmp->ifa_addr &&
421 		    !strncmp(tmp->ifa_name, if_name, IF_NAMESIZE) &&
422 		    tmp->ifa_addr->sa_family == family) {
423 
424 			switch (family) {
425 			case AF_INET: {
426 				struct sockaddr_in *in4 =
427 					(struct sockaddr_in *)tmp->ifa_addr;
428 				if (in4->sin_addr.s_addr == INADDR_ANY)
429 					continue;
430 				if ((in4->sin_addr.s_addr & IN_CLASSB_NET) ==
431 						((in_addr_t)0xa9fe0000))
432 					continue;
433 				memcpy(address, &in4->sin_addr,
434 				       sizeof(struct in_addr));
435 				error = 0;
436 				goto out;
437 			}
438 			case AF_INET6: {
439 				struct sockaddr_in6 *in6 =
440 					(struct sockaddr_in6 *)tmp->ifa_addr;
441 				if (!memcmp(&in6->sin6_addr, &in6addr_any,
442 					    sizeof(struct in6_addr)))
443 					continue;
444 				if (IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr)) {
445 					ll = in6;
446 					continue;
447 				}
448 
449 				memcpy(address, &in6->sin6_addr,
450 				       sizeof(struct in6_addr));
451 				error = 0;
452 				goto out;
453 			}
454 			default:
455 				error = -EINVAL;
456 				goto out;
457 			}
458 		}
459 	}
460 
461 out:
462 	if (error < 0 && ll) {
463 		/* As a last resort use link local address */
464 		memcpy(address, &ll->sin6_addr, sizeof(struct in6_addr));
465 		error = 0;
466 	}
467 
468 	return error;
469 }
470 
get_address(const char * if_name,int family,void * address)471 static int get_address(const char *if_name, int family, void *address)
472 {
473 	struct ifaddrs *if_address;
474 	int err;
475 
476 	if (getifaddrs(&if_address) < 0) {
477 		err = -errno;
478 		fprintf(stderr, "Cannot get interface addresses for "
479 			"interface %s error %d/%s",
480 			if_name, err, strerror(-err));
481 		return err;
482 	}
483 
484 	err = find_address(family, if_address, if_name, address);
485 
486 	freeifaddrs(if_address);
487 
488 	return err;
489 }
490 
491 #define PSK_DEFAULT_IDENTITY "Client_identity"
492 #define PSK_DEFAULT_KEY      "secretPSK"
493 #define PSK_OPTIONS          "i:k:"
494 
495 static bool quit = false;
496 static dtls_context_t *dtls_context;
497 
498 static const unsigned char ecdsa_priv_key[] = {
499 			0x41, 0xC1, 0xCB, 0x6B, 0x51, 0x24, 0x7A, 0x14,
500 			0x43, 0x21, 0x43, 0x5B, 0x7A, 0x80, 0xE7, 0x14,
501 			0x89, 0x6A, 0x33, 0xBB, 0xAD, 0x72, 0x94, 0xCA,
502 			0x40, 0x14, 0x55, 0xA1, 0x94, 0xA9, 0x49, 0xFA};
503 
504 static const unsigned char ecdsa_pub_key_x[] = {
505 			0x36, 0xDF, 0xE2, 0xC6, 0xF9, 0xF2, 0xED, 0x29,
506 			0xDA, 0x0A, 0x9A, 0x8F, 0x62, 0x68, 0x4E, 0x91,
507 			0x63, 0x75, 0xBA, 0x10, 0x30, 0x0C, 0x28, 0xC5,
508 			0xE4, 0x7C, 0xFB, 0xF2, 0x5F, 0xA5, 0x8F, 0x52};
509 
510 static const unsigned char ecdsa_pub_key_y[] = {
511 			0x71, 0xA0, 0xD4, 0xFC, 0xDE, 0x1A, 0xB8, 0x78,
512 			0x5A, 0x3C, 0x78, 0x69, 0x35, 0xA7, 0xCF, 0xAB,
513 			0xE9, 0x3F, 0x98, 0x72, 0x09, 0xDA, 0xED, 0x0B,
514 			0x4F, 0xAB, 0xC3, 0x6F, 0xC7, 0x72, 0xF8, 0x29};
515 
516 #ifdef DTLS_PSK
517 /* The PSK information for DTLS */
518 #define PSK_ID_MAXLEN 256
519 #define PSK_MAXLEN 256
520 static unsigned char psk_id[PSK_ID_MAXLEN];
521 static size_t psk_id_length = 0;
522 static unsigned char psk_key[PSK_MAXLEN];
523 static size_t psk_key_length = 0;
524 
525 /* This function is the "key store" for tinyDTLS. It is called to
526  * retrieve a key for the given identity within this particular
527  * session. */
get_psk_info(struct dtls_context_t * ctx UNUSED_PARAM,const session_t * session UNUSED_PARAM,dtls_credentials_type_t type,const unsigned char * id,size_t id_len,unsigned char * result,size_t result_length)528 static int get_psk_info(struct dtls_context_t *ctx UNUSED_PARAM,
529 			const session_t *session UNUSED_PARAM,
530 			dtls_credentials_type_t type,
531 			const unsigned char *id, size_t id_len,
532 			unsigned char *result, size_t result_length)
533 {
534 	switch (type) {
535 	case DTLS_PSK_IDENTITY:
536 		if (id_len) {
537 			dtls_debug("got psk_identity_hint: '%.*s'\n", id_len,
538 				   id);
539 		}
540 
541 		if (result_length < psk_id_length) {
542 			dtls_warn("cannot set psk_identity -- buffer too small\n");
543 			return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
544 		}
545 
546 		memcpy(result, psk_id, psk_id_length);
547 		return psk_id_length;
548 
549 	case DTLS_PSK_KEY:
550 		if (id_len != psk_id_length || memcmp(psk_id, id, id_len) != 0) {
551 			dtls_warn("PSK for unknown id requested, exiting\n");
552 			return dtls_alert_fatal_create(DTLS_ALERT_ILLEGAL_PARAMETER);
553 		} else if (result_length < psk_key_length) {
554 			dtls_warn("cannot set psk -- buffer too small\n");
555 			return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
556 		}
557 
558 		memcpy(result, psk_key, psk_key_length);
559 		return psk_key_length;
560 
561 	default:
562 		dtls_warn("unsupported request type: %d\n", type);
563 	}
564 
565 	return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
566 }
567 #endif /* DTLS_PSK */
568 
569 #ifdef DTLS_ECC
get_ecdsa_key(struct dtls_context_t * ctx,const session_t * session,const dtls_ecdsa_key_t ** result)570 static int get_ecdsa_key(struct dtls_context_t *ctx,
571 			 const session_t *session,
572 			 const dtls_ecdsa_key_t **result)
573 {
574 	static const dtls_ecdsa_key_t ecdsa_key = {
575 		.curve = DTLS_ECDH_CURVE_SECP256R1,
576 		.priv_key = ecdsa_priv_key,
577 		.pub_key_x = ecdsa_pub_key_x,
578 		.pub_key_y = ecdsa_pub_key_y
579 	};
580 
581 	*result = &ecdsa_key;
582 	return 0;
583 }
584 
verify_ecdsa_key(struct dtls_context_t * ctx,const session_t * session,const unsigned char * other_pub_x,const unsigned char * other_pub_y,size_t key_size)585 static int verify_ecdsa_key(struct dtls_context_t *ctx,
586 			    const session_t *session,
587 			    const unsigned char *other_pub_x,
588 			    const unsigned char *other_pub_y,
589 			    size_t key_size)
590 {
591 	return 0;
592 }
593 #endif /* DTLS_ECC */
594 
print_data(const unsigned char * packet,int length)595 static void print_data(const unsigned char *packet, int length)
596 {
597 	int n = 0;
598 
599 	while (length--) {
600 		if (n % 16 == 0)
601 			printf("%X: ", n);
602 
603 		printf("%X ", *packet++);
604 
605 		n++;
606 		if (n % 8 == 0) {
607 			if (n % 16 == 0)
608 				printf("\n");
609 			else
610 				printf(" ");
611 		}
612 	}
613 	printf("\n");
614 }
615 
new_option_node(unsigned short key,unsigned int length,unsigned char * data)616 static coap_list_t *new_option_node(unsigned short key,
617 				    unsigned int length,
618 				    unsigned char *data)
619 {
620 	coap_list_t *node;
621 
622 	node = coap_malloc(sizeof(coap_list_t) + sizeof(coap_option) + length);
623 
624 	if (node) {
625 		coap_option *option = (coap_option *)(node->data);
626 
627 		COAP_OPTION_KEY(*option) = key;
628 		COAP_OPTION_LENGTH(*option) = length;
629 		memcpy(COAP_OPTION_DATA(*option), data, length);
630 	} else {
631 		coap_log(LOG_DEBUG, "new_option_node: malloc\n");
632 	}
633 
634 	return node;
635 }
636 
coap_insert(coap_list_t ** head,coap_list_t * node)637 static int coap_insert(coap_list_t **head, coap_list_t *node)
638 {
639 	if (!node) {
640 		coap_log(LOG_WARNING, "cannot create option Proxy-Uri\n");
641 	} else {
642 		LL_APPEND((*head), node);
643 	}
644 
645 	return node != NULL;
646 }
647 
coap_delete(coap_list_t * node)648 static int coap_delete(coap_list_t *node)
649 {
650 	if (node) {
651 		coap_free(node);
652 	}
653 	return 1;
654 }
655 
coap_delete_list(coap_list_t * queue)656 static void coap_delete_list(coap_list_t *queue)
657 {
658 	coap_list_t *elt, *tmp;
659 
660 	if (!queue)
661 		return;
662 
663 	LL_FOREACH_SAFE(queue, elt, tmp) {
664 		coap_delete(elt);
665 	}
666 }
667 
parse_uri(const char * arg)668 static coap_list_t *parse_uri(const char *arg)
669 {
670 	coap_uri_t uri;
671 	coap_list_t *opts = NULL;
672 #define BUFSIZE 40
673 	unsigned char _buf[BUFSIZE];
674 	unsigned char *buf = _buf;
675 	size_t buflen;
676 	int res;
677 
678 	coap_split_uri((unsigned char *)arg, strlen(arg), &uri );
679 
680 	if (uri.path.length) {
681 		buflen = BUFSIZE;
682 		res = coap_split_path(uri.path.s, uri.path.length,
683 				      buf, &buflen);
684 
685 		while (res--) {
686 			coap_insert(&opts,
687 				    new_option_node(COAP_OPTION_URI_PATH,
688 						    COAP_OPT_LENGTH(buf),
689 						    COAP_OPT_VALUE(buf)));
690 
691 			buf += COAP_OPT_SIZE(buf);
692 		}
693 	}
694 
695 	if (uri.query.length) {
696 		buflen = BUFSIZE;
697 		buf = _buf;
698 		res = coap_split_query(uri.query.s, uri.query.length,
699 				       buf, &buflen);
700 
701 		while (res--) {
702 			coap_insert(&opts,
703 				    new_option_node(COAP_OPTION_URI_QUERY,
704 						    COAP_OPT_LENGTH(buf),
705 						    COAP_OPT_VALUE(buf)));
706 
707 			buf += COAP_OPT_SIZE(buf);
708 		}
709 	}
710 
711 	return opts;
712 }
713 
clone_option(coap_list_t * item)714 static coap_list_t *clone_option(coap_list_t *item)
715 {
716 	coap_list_t *node;
717 	coap_option *option = (coap_option *)(item->data);
718 
719 	node = coap_malloc(sizeof(coap_list_t) + sizeof(coap_option) +
720 			   option->length);
721 	if (node) {
722 		memcpy(node->data, option,
723 		       sizeof(coap_option) + option->length);
724 		return node;
725 	} else
726 		return NULL;
727 }
728 
create_uri(char * uri,int len,const char * target,struct client_data * user_data)729 static char *create_uri(char *uri, int len, const char *target,
730 			struct client_data *user_data)
731 {
732 	snprintf(uri, len, "coap://%s%s%s/%s",
733 		 family == AF_INET6 ? "[" : "",
734 		 target,
735 		 family == AF_INET6 ? "]" : "",
736 		 data[user_data->index].buf);
737 
738 	if (debug)
739 		print_data(uri, data[user_data->index].len);
740 
741 	return uri;
742 }
743 
create_pdu(struct client_data * user_data)744 static coap_pdu_t *create_pdu(struct client_data *user_data)
745 {
746 	coap_pdu_t *pdu;
747 	coap_list_t *opts;
748 	coap_list_t *elt, *tmp;
749 #define MAX_URI 256
750 	char uri_buf[MAX_URI], *uri;
751 	const unsigned char *send_data = NULL;
752 	int send_data_len = 0;
753 
754 	uri = create_uri(uri_buf, MAX_URI, target, user_data);
755 	opts = parse_uri(uri);
756 
757 	LL_FOREACH_SAFE(optlist, elt, tmp) {
758 		coap_insert(&opts,
759 			    clone_option(elt));
760 	}
761 
762 	if (data[user_data->index].data) {
763 		send_data = data[user_data->index].data;
764 		send_data_len = data[user_data->index].data_len;
765 		if (send_data[send_data_len] == '\0')
766 			send_data_len--; /* skip the null at the end */
767 	}
768 	pdu = coap_new_request(user_data->coap_ctx,
769 			       data[user_data->index].coap_method,
770 			       &opts,
771 			       send_data, send_data_len,
772 			       data[user_data->index].message_type);
773 	if (pdu) {
774 		if (data[user_data->index].check_mid)
775 			data[user_data->index].expected_mid = ntohs(pdu->hdr->id);
776 	}
777 	coap_delete_list(opts);
778 
779 	return pdu;
780 }
781 
send_packets(struct client_data * user_data)782 static void send_packets(struct client_data *user_data)
783 {
784 	int ret;
785 	coap_pdu_t *pdu;
786 	coap_tid_t tid;
787 
788 	printf("%s: sending [%d] %d bytes\n",
789 	       data[user_data->index].description,
790 	       user_data->index, data[user_data->index].len);
791 
792 	test_context = user_data;
793 
794 	pdu = create_pdu(user_data);
795 	if (!pdu) {
796 		/* Failure */
797 		quit = true;
798 		user_data->fail = true;
799 		printf("Cannot allocate pdu\n");
800 		return;
801 	}
802 
803 	method = data[user_data->index].coap_method;
804 
805 	if (coap_get_log_level() >= LOG_DEBUG) {
806 		printf("sending CoAP request:\n");
807 		coap_show_pdu(pdu);
808 	}
809 
810 	if (pdu->hdr->type == COAP_MESSAGE_CON)
811 		tid = coap_send_confirmed(user_data->coap_ctx,
812 					  user_data->coap_ctx->endpoint,
813 					  &user_data->coap_dst,
814 					  pdu);
815 	else
816 		tid = coap_send(user_data->coap_ctx,
817 				user_data->coap_ctx->endpoint,
818 				&user_data->coap_dst,
819 				pdu);
820 
821 	if (pdu->hdr->type != COAP_MESSAGE_CON || tid == COAP_INVALID_TID)
822 		coap_delete_pdu(pdu);
823 
824 	set_coap_timeout(&max_wait, wait_seconds);
825 
826 	if (debug)
827 		printf("timeout is set to %d seconds\n", wait_seconds);
828 }
829 
try_send(struct dtls_context_t * ctx)830 static void try_send(struct dtls_context_t *ctx)
831 {
832 	struct client_data *user_data =
833 			(struct client_data *)dtls_get_app_data(ctx);
834 	int ret;
835 	coap_pdu_t *pdu;
836 	coap_tid_t tid;
837 
838 	printf("%s: sending [%d] %d bytes\n",
839 	       data[user_data->index].description,
840 	       user_data->index, data[user_data->index].len);
841 
842 	test_context = user_data;
843 
844 	pdu = create_pdu(user_data);
845 	if (!pdu) {
846 		/* Failure */
847 		quit = true;
848 		user_data->fail = true;
849 		printf("Cannot allocate pdu\n");
850 		return;
851 	}
852 
853 	method = data[user_data->index].coap_method;
854 
855 	if (coap_get_log_level() >= LOG_DEBUG) {
856 		printf("sending CoAP request:\n");
857 		coap_show_pdu(pdu);
858 	}
859 
860 	if (pdu->hdr->type == COAP_MESSAGE_CON)
861 		tid = coap_send_confirmed(user_data->coap_ctx,
862 					  user_data->coap_ctx->endpoint,
863 					  &user_data->coap_dst,
864 					  pdu);
865 	else
866 		tid = coap_send(user_data->coap_ctx,
867 				user_data->coap_ctx->endpoint,
868 				&user_data->coap_dst,
869 				pdu);
870 
871 	if (pdu->hdr->type != COAP_MESSAGE_CON || tid == COAP_INVALID_TID)
872 		coap_delete_pdu(pdu);
873 
874 	set_coap_timeout(&max_wait, wait_seconds);
875 
876 	if (debug)
877 		printf("timeout is set to %d seconds\n", wait_seconds);
878 }
879 
dispatch_data(char * buf,ssize_t bytes_read,coap_context_t * ctx,coap_address_t * src)880 static int dispatch_data(char *buf, ssize_t bytes_read,
881 			 coap_context_t *ctx, coap_address_t *src)
882 {
883 	coap_hdr_t *pdu;
884 	coap_queue_t *node;
885 
886 	pdu = (coap_hdr_t *)buf;
887 
888 	if ((size_t)bytes_read < sizeof(coap_hdr_t)) {
889 		printf("coap_read: discarded invalid frame\n");
890 		goto error_early;
891 	}
892 
893 	if (pdu->version != COAP_DEFAULT_VERSION) {
894 		printf("coap_read: unknown protocol version\n");
895 		goto error_early;
896 	}
897 
898 	node = coap_new_node();
899 	if (!node)
900 		goto error_early;
901 
902 	node->pdu = coap_pdu_init(0, 0, 0, bytes_read);
903 
904 	if (!node->pdu)
905 		goto error;
906 
907 	coap_ticks(&node->t);
908 	memcpy(&node->local_if, ctx->endpoint, sizeof(coap_endpoint_t));
909 	memcpy(&node->remote, src, sizeof(coap_address_t));
910 
911 	if (!coap_pdu_parse((unsigned char *)buf, bytes_read, node->pdu)) {
912 		printf("discard malformed PDU");
913 		goto error;
914 	}
915 
916 	coap_transaction_id(&node->remote, node->pdu, &node->id);
917 
918 	if (coap_get_log_level() >= LOG_DEBUG) {
919 		unsigned char addr[INET6_ADDRSTRLEN+8];
920 
921 		if (coap_print_addr(src, addr, INET6_ADDRSTRLEN+8))
922 			printf("** received %d bytes from %s:\n",
923 			       (int)bytes_read, addr);
924 		coap_show_pdu(node->pdu);
925 	}
926 
927 	coap_dispatch(ctx, node);
928 	return 0;
929 
930 error:
931 	coap_delete_node(node);
932 error_early:
933 	return -1;
934 }
935 
read_from_peer(struct dtls_context_t * ctx,session_t * session,uint8 * read_data,size_t read_len)936 static int read_from_peer(struct dtls_context_t *ctx,
937 			  session_t *session,
938 			  uint8 *read_data, size_t read_len)
939 {
940 	struct client_data *user_data =
941 			(struct client_data *)dtls_get_app_data(ctx);
942 	coap_address_t addr;
943 
944 	printf("%s: read [%u] from peer %zu bytes\n",
945 	       data[user_data->index].description, user_data->index, read_len);
946 
947 	memcpy(&(addr.addr), &(session->addr), session->size);
948 	addr.size = session->size;
949 
950 	/* Process the received CoAP packet */
951 	if (dispatch_data(read_data, read_len, user_data->coap_ctx,
952 			  &addr) < 0) {
953 		printf("Cannot parse received CoAP packet.\n");
954 		quit = true;
955 		user_data->fail = true;
956 		return 0;
957 	}
958 
959 	if (debug)
960 		print_data(read_data, read_len);
961 
962 	if (!data[user_data->index + 1].buf) {
963 		/* last entry, just bail out */
964 		quit = true;
965 		return 0;
966 	}
967 
968 	if (user_data->index == renegotiate) {
969 		printf("Starting to renegotiate keys\n");
970 		dtls_renegotiate(ctx, session);
971 		return 1;
972 	}
973 
974 	try_send(ctx);
975 
976 	return 0;
977 }
978 
sleep_ms(int ms)979 static inline void sleep_ms(int ms)
980 {
981 	struct timeval tv;
982 
983 	tv.tv_sec = 0;
984 	tv.tv_usec = ms * 1000;
985 
986 	select(1, NULL, NULL, NULL, &tv);
987 }
988 
send_to_peer(struct dtls_context_t * ctx,session_t * session,uint8 * data,size_t len)989 static int send_to_peer(struct dtls_context_t *ctx,
990 			session_t *session,
991 			uint8 *data, size_t len)
992 {
993 	struct client_data *user_data =
994 			(struct client_data *)dtls_get_app_data(ctx);
995 
996 	/* The Qemu uart driver can loose chars if sent too fast.
997 	 * So before sending more data, sleep a while.
998 	 */
999 	sleep_ms(200);
1000 
1001 	printf("Sending to peer encrypted data %p len %zu\n", data, len);
1002 
1003 	return sendto(user_data->fd, data, len, 0,
1004 		      &session->addr.sa, session->size);
1005 }
1006 
dtls_handle_read(struct dtls_context_t * ctx)1007 static int dtls_handle_read(struct dtls_context_t *ctx)
1008 {
1009 	struct client_data *user_data;
1010 
1011 	user_data = (struct client_data *)dtls_get_app_data(ctx);
1012 
1013 	if (!user_data || !user_data->fd)
1014 		return -1;
1015 
1016 	memset(&session, 0, sizeof(session_t));
1017 	session.size = sizeof(session.addr);
1018 	user_data->len = recvfrom(user_data->fd, user_data->buf, MAX_READ_BUF,
1019 				  0, &session.addr.sa, &session.size);
1020 	if (user_data->len < 0) {
1021 		perror("recvfrom");
1022 		return -1;
1023 	} else {
1024 		dtls_dsrv_log_addr(DTLS_LOG_DEBUG, "peer", &session);
1025 		dtls_debug_dump("bytes from peer", user_data->buf,
1026 				user_data->len);
1027 	}
1028 
1029 	return dtls_handle_message(ctx, &session, user_data->buf,
1030 				   user_data->len);
1031 }
1032 
handle_event(struct dtls_context_t * ctx,session_t * session,dtls_alert_level_t level,unsigned short code)1033 static int handle_event(struct dtls_context_t *ctx, session_t *session,
1034 			dtls_alert_level_t level, unsigned short code)
1035 {
1036 	struct client_data *user_data;
1037 
1038 	user_data = (struct client_data *)dtls_get_app_data(ctx);
1039 
1040 	if (debug)
1041 		printf("event: level %d code %d\n", level, code);
1042 
1043 	if (level > 0) {
1044 		/* alert code, quit */
1045 		quit = true;
1046 		user_data->fail = true;
1047 	} else if (level == 0) {
1048 		/* internal event */
1049 		if (code == DTLS_EVENT_CONNECTED) {
1050 			/* We can send data now */
1051 			try_send(ctx);
1052 		}
1053 	}
1054 
1055 	return 0;
1056 }
1057 
1058 static dtls_handler_t cb = {
1059 	.write = send_to_peer,
1060 	.read  = read_from_peer,
1061 	.event = handle_event,
1062 #ifdef DTLS_PSK
1063 	.get_psk_info = get_psk_info,
1064 #endif /* DTLS_PSK */
1065 #ifdef DTLS_ECC
1066 	.get_ecdsa_key = get_ecdsa_key,
1067 	.verify_ecdsa_key = verify_ecdsa_key
1068 #endif /* DTLS_ECC */
1069 };
1070 
read_data_from_net(struct client_data * user_data)1071 static int read_data_from_net(struct client_data *user_data)
1072 {
1073 	coap_packet_t *packet;
1074 	coap_address_t addr;
1075 
1076 	if (!user_data || !user_data->fd)
1077 		return -1;
1078 
1079 	return coap_read(user_data->coap_ctx);
1080 }
1081 
signal_handler(int signum)1082 void signal_handler(int signum)
1083 {
1084 	switch (signum) {
1085 	case SIGINT:
1086 	case SIGTERM:
1087 		quit = true;
1088 		break;
1089 	}
1090 }
1091 
check_token(coap_pdu_t * received)1092 static inline int check_token(coap_pdu_t *received)
1093 {
1094 	return received->hdr->token_length == the_token.length &&
1095 		memcmp(received->hdr->token, the_token.s,
1096 		       the_token.length) == 0;
1097 }
1098 
is_our_own(coap_context_t * coap_ctx,const coap_address_t * remote,coap_pdu_t * sent,coap_pdu_t * received)1099 static bool is_our_own(coap_context_t *coap_ctx,
1100 		       const coap_address_t *remote,
1101 		       coap_pdu_t *sent,
1102 		       coap_pdu_t *received)
1103 {
1104 	if (data[test_context->index].add_token && !check_token(received)) {
1105 		if (!sent &&
1106 		    (received->hdr->type == COAP_MESSAGE_CON ||
1107 		     received->hdr->type == COAP_MESSAGE_NON))
1108 			coap_send_rst(coap_ctx, coap_ctx->endpoint, remote,
1109 				      received);
1110 		return false;
1111 	}
1112 
1113 	return true;
1114 }
1115 
add_options(coap_pdu_t * pdu)1116 static void add_options(coap_pdu_t *pdu)
1117 {
1118 	coap_list_t *option;
1119 
1120 	for (option = optlist; option; option = option->next ) {
1121 		switch (COAP_OPTION_KEY(*(coap_option *)option->data)) {
1122 		case COAP_OPTION_URI_HOST :
1123 		case COAP_OPTION_URI_PORT :
1124 		case COAP_OPTION_URI_PATH :
1125 		case COAP_OPTION_CONTENT_FORMAT :
1126 		case COAP_OPTION_URI_QUERY :
1127 			coap_add_option(pdu,
1128 				COAP_OPTION_KEY(*(coap_option *)option->data),
1129 				COAP_OPTION_LENGTH(*(coap_option *)option->data),
1130 				COAP_OPTION_DATA(*(coap_option *)option->data));
1131 			break;
1132 		default:
1133 			break;
1134 		}
1135 	}
1136 }
1137 
order_opts(void * a,void * b)1138 static int order_opts(void *a, void *b)
1139 {
1140 	coap_option *o1, *o2;
1141 
1142 	if (!a || !b)
1143 		return a < b ? -1 : 1;
1144 
1145 	o1 = (coap_option *)(((coap_list_t *)a)->data);
1146 	o2 = (coap_option *)(((coap_list_t *)b)->data);
1147 
1148 	return (COAP_OPTION_KEY(*o1) < COAP_OPTION_KEY(*o2)) ? -1
1149 		: (COAP_OPTION_KEY(*o1) != COAP_OPTION_KEY(*o2));
1150 }
1151 
coap_new_request(coap_context_t * ctx,method_t m,coap_list_t ** options,const unsigned char * req,size_t length,int msgtype)1152 static coap_pdu_t *coap_new_request(coap_context_t *ctx,
1153 				    method_t m,
1154 				    coap_list_t **options,
1155 				    const unsigned char *req,
1156 				    size_t length,
1157 				    int msgtype)
1158 {
1159 	coap_pdu_t *pdu;
1160 	coap_list_t *opt;
1161 
1162 	if (!(pdu = coap_new_pdu()))
1163 		return NULL;
1164 
1165 	pdu->hdr->type = msgtype;
1166 	pdu->hdr->id = coap_new_message_id(ctx);
1167 	pdu->hdr->code = m;
1168 
1169 	if (data[test_context->index].add_token) {
1170 		pdu->hdr->token_length = the_token.length;
1171 		if (!coap_add_token(pdu, the_token.length, the_token.s)) {
1172 			printf("cannot add token to request\n");
1173 			test_context->fail = true;
1174 			quit = true;
1175 			return NULL;
1176 		}
1177 	}
1178 
1179 	coap_show_pdu(pdu);
1180 
1181 	if (options) {
1182 		LL_SORT((*options), order_opts);
1183 
1184 		LL_FOREACH((*options), opt) {
1185 			coap_option *o = (coap_option *)(opt->data);
1186 			coap_add_option(pdu,
1187 					COAP_OPTION_KEY(*o),
1188 					COAP_OPTION_LENGTH(*o),
1189 					COAP_OPTION_DATA(*o));
1190 		}
1191 	}
1192 
1193 	if (length) {
1194 		if ((flags & FLAGS_BLOCK) == 0)
1195 			coap_add_data(pdu, length, req);
1196 		else
1197 			coap_add_block(pdu, length, req,
1198 				       block.num, block.szx);
1199 	}
1200 
1201 	return pdu;
1202 }
1203 
read_blocks(coap_context_t * coap_ctx,const coap_endpoint_t * endpoint,const coap_address_t * remote,coap_opt_iterator_t * opt_iter,coap_pdu_t * received,coap_opt_t * block_opt)1204 static coap_pdu_t *read_blocks(coap_context_t *coap_ctx,
1205 			       const coap_endpoint_t *endpoint,
1206 			       const coap_address_t *remote,
1207 			       coap_opt_iterator_t *opt_iter,
1208 			       coap_pdu_t *received,
1209 			       coap_opt_t *block_opt)
1210 {
1211 	unsigned short blktype = opt_iter->type;
1212 	size_t len;
1213 	unsigned char *databuf;
1214 	coap_pdu_t *pdu = NULL;
1215 	unsigned char buf[4];
1216 	coap_tid_t tid;
1217 
1218 	if (coap_get_data(received, &len, &databuf))
1219 		printf("Received: databuf %p len %zu\n", databuf, len);
1220 
1221 	if (COAP_OPT_BLOCK_MORE(block_opt)) {
1222 		printf("found the M bit, block size is %u, block nr. %u\n",
1223 		       COAP_OPT_BLOCK_SZX(block_opt),
1224 		       coap_opt_block_num(block_opt));
1225 
1226 		pdu = coap_new_request(coap_ctx, method, NULL, NULL, 0,
1227 				       COAP_MESSAGE_CON);
1228 		if (pdu) {
1229 			add_options(pdu);
1230 
1231 			printf("query block %d\n",
1232 			       (coap_opt_block_num(block_opt) + 1));
1233 
1234 			coap_add_option(pdu, blktype,
1235 				coap_encode_var_bytes(buf,
1236 				   ((coap_opt_block_num(block_opt) + 1) << 4) |
1237 			             COAP_OPT_BLOCK_SZX(block_opt)), buf);
1238 
1239 			if (received->hdr->type == COAP_MESSAGE_CON)
1240 				tid = coap_send_confirmed(coap_ctx,
1241 							  endpoint,
1242 							  remote,
1243 							  pdu);
1244 			else
1245 				tid = coap_send(coap_ctx,
1246 						endpoint,
1247 						remote,
1248 						pdu);
1249 
1250 			if (tid == COAP_INVALID_TID) {
1251 				printf("error sending new request\n");
1252 				coap_delete_pdu(pdu);
1253 			} else {
1254 				set_coap_timeout(&max_wait, wait_seconds);
1255 				if (received->hdr->type != COAP_MESSAGE_CON) {
1256 					coap_delete_pdu(pdu);
1257 					return NULL;
1258 				}
1259 			}
1260 		}
1261 	}
1262 
1263 	return pdu;
1264 }
1265 
get_block(coap_pdu_t * pdu,coap_opt_iterator_t * opt_iter)1266 static  coap_opt_t *get_block(coap_pdu_t *pdu, coap_opt_iterator_t *opt_iter)
1267 {
1268 	coap_opt_filter_t f;
1269 
1270 	memset(f, 0, sizeof(coap_opt_filter_t));
1271 	coap_option_setb(f, COAP_OPTION_BLOCK1);
1272 	coap_option_setb(f, COAP_OPTION_BLOCK2);
1273 
1274 	coap_option_iterator_init(pdu, opt_iter, f);
1275 	return coap_option_next(opt_iter);
1276 }
1277 
check_mid(const unsigned char * databuf,int len,int test_case)1278 static bool check_mid(const unsigned char *databuf, int len,
1279 		      int test_case)
1280 {
1281 	unsigned char buf[2048];
1282 
1283 	snprintf(buf, sizeof(buf), "%sMID: %d", data[test_case].data,
1284 		 data[test_case].expected_mid);
1285 	if (!memcmp(databuf, buf, strlen(buf)))
1286 		return true;
1287 	else {
1288 		printf("FAIL:\n  received %d bytes\n>>>>\n%.*s\n<<<<\n", len,
1289 		       len, databuf);
1290 		printf(" expected %zu bytes\n>>>>\n%s\n<<<<\n", strlen(buf), buf);
1291 		return false;
1292 	}
1293 }
1294 
receive_data(coap_pdu_t * received)1295 static void receive_data(coap_pdu_t *received)
1296 {
1297 	size_t len;
1298 	unsigned char *databuf;
1299 
1300 	if (coap_get_data(received, &len, &databuf)) {
1301 		if (!test_context)
1302 			return;
1303 
1304 		if (data[test_context->index].check_mid &&
1305 		    !check_mid(databuf, len, test_context->index)) {
1306 			printf("Test %d failed\n",
1307 			       test_context->index);
1308 			test_context->fail = true;
1309 			quit = true;
1310 		} else {
1311 			if (!data[test_context->index + 1].buf) {
1312 				/* last entry, just bail out */
1313 				quit = true;
1314 			} else
1315 				test_context->index++;
1316 		}
1317 	} else {
1318 		if (!test_context)
1319 			return;
1320 
1321 		if (data[test_context->index].check_mid) {
1322 			printf("Packet error\n");
1323 			quit = true;
1324 			test_context->fail = true;
1325 		} else {
1326 			if (!data[test_context->index + 1].buf) {
1327 				/* last entry, just bail out */
1328 				quit = true;
1329 			} else
1330 				test_context->index++;
1331 		}
1332 	}
1333 }
1334 
coap_message_handler(struct coap_context_t * coap_ctx,const coap_endpoint_t * endpoint,const coap_address_t * remote,coap_pdu_t * sent,coap_pdu_t * received,const coap_tid_t id)1335 static void coap_message_handler(struct coap_context_t *coap_ctx,
1336 				 const coap_endpoint_t *endpoint,
1337 				 const coap_address_t *remote,
1338 				 coap_pdu_t *sent,
1339 				 coap_pdu_t *received,
1340 				 const coap_tid_t id)
1341 {
1342 	coap_pdu_t *pdu = NULL;
1343 	coap_opt_t *block_opt;
1344 	coap_opt_iterator_t opt_iter;
1345 	size_t len;
1346 	unsigned char *databuf;
1347 
1348 	if (coap_get_log_level() >= LOG_DEBUG) {
1349 		printf("process incoming %d.%02d response:\n",
1350 		      (received->hdr->code >> 5), received->hdr->code & 0x1F);
1351 		coap_show_pdu(received);
1352 	}
1353 
1354 	if (!is_our_own(coap_ctx, remote, sent, received))
1355 		return;
1356 
1357 	switch (received->hdr->type) {
1358 	case COAP_MESSAGE_CON:
1359 		coap_send_ack(coap_ctx, endpoint, remote, received);
1360 		break;
1361 	case COAP_MESSAGE_RST:
1362 		printf("CoAP RST\n");
1363 		return;
1364 	default:
1365 		break;
1366 	}
1367 
1368 	if (COAP_RESPONSE_CLASS(received->hdr->code) == 2) {
1369 
1370 		if (sent && coap_check_option(received,
1371 					      COAP_OPTION_SUBSCRIPTION,
1372 					      &opt_iter)) {
1373 			printf("observation timeout set to %d\n", obs_seconds);
1374 			set_coap_timeout(&obs_wait, obs_seconds);
1375 		}
1376 
1377 		block_opt = get_block(received, &opt_iter);
1378 		if (block_opt)
1379 			pdu = read_blocks(coap_ctx,
1380 					  endpoint,
1381 					  remote,
1382 					  &opt_iter,
1383 					  received,
1384 					  block_opt);
1385 		else {
1386 			block_opt = coap_check_option(received,
1387 						      COAP_OPTION_BLOCK1,
1388 						      &opt_iter);
1389 			if (block_opt) { /* handle Block1 */
1390 				unsigned char buf[4];
1391 				coap_tid_t tid;
1392 
1393 				block.szx = COAP_OPT_BLOCK_SZX(block_opt);
1394 				block.num = coap_opt_block_num(block_opt);
1395 
1396 				debug("found Block1, block size is %u, "
1397 				      "block nr. %u\n",
1398 				      block.szx, block.num);
1399 
1400 				if (payload.length <= (block.num+1) *
1401 				    (1 << (block.szx + 4))) {
1402 					debug("upload ready\n");
1403 					ready = 1;
1404 					return;
1405 				}
1406 
1407 				/* create pdu with request for next block */
1408 				pdu = coap_new_request(coap_ctx, method, NULL,
1409 						       NULL, 0, COAP_MESSAGE_CON);
1410 				if (pdu) {
1411 					/* add URI components from optlist */
1412 					add_options(pdu);
1413 
1414 					block.num++;
1415 					block.m = ((block.num+1) *
1416 						   (1 << (block.szx + 4)) <
1417 						   payload.length);
1418 
1419 					debug("send block %d\n", block.num);
1420 					coap_add_option(pdu,
1421 							COAP_OPTION_BLOCK1,
1422 							coap_encode_var_bytes(buf,
1423 							      (block.num << 4) |
1424 							      (block.m << 3) |
1425 							      block.szx), buf);
1426 
1427 					coap_add_block(pdu,
1428 						       payload.length,
1429 						       payload.s,
1430 						       block.num,
1431 						       block.szx);
1432 					coap_show_pdu(pdu);
1433 					if (pdu->hdr->type == COAP_MESSAGE_CON)
1434 						tid = coap_send_confirmed(coap_ctx,
1435 						  endpoint, remote, pdu);
1436 					else
1437 						tid = coap_send(coap_ctx,
1438 						  endpoint, remote, pdu);
1439 
1440 					if (tid == COAP_INVALID_TID) {
1441 						debug("message_handler: error "
1442 						      "sending new request");
1443 						coap_delete_pdu(pdu);
1444 					} else {
1445 						set_coap_timeout(&max_wait, wait_seconds);
1446 						if (pdu->hdr->type != COAP_MESSAGE_CON)
1447 							coap_delete_pdu(pdu);
1448 					}
1449 
1450 					return;
1451 				}
1452 			} else {
1453 				/* There is no block option set, just read the data and we are done. */
1454 				receive_data(received);
1455 			}
1456 		}
1457 	} else {
1458 		if (COAP_RESPONSE_CLASS(received->hdr->code) >= 4) {
1459 			fprintf(stderr, "ERROR %d.%02d",
1460 				(received->hdr->code >> 5),
1461 				received->hdr->code & 0x1F);
1462 			if (coap_get_data(received, &len, &databuf)) {
1463 				fprintf(stderr, " ");
1464 				while(len--)
1465 					fprintf(stderr, "%c", *databuf++);
1466 			}
1467 			fprintf(stderr, "\n");
1468 
1469 			if (test_context)
1470 				test_context->fail = true;
1471 			quit = true;
1472 		}
1473 	}
1474 
1475 	if (pdu && coap_send(coap_ctx, endpoint,
1476 			     remote, pdu) == COAP_INVALID_TID)
1477 		printf("error sending response\n");
1478 
1479 	coap_delete_pdu(pdu);
1480 
1481 	ready = coap_check_option(received, COAP_OPTION_SUBSCRIPTION,
1482 				  &opt_iter) == NULL;
1483 }
1484 
set_blocksize(void)1485 static void set_blocksize(void)
1486 {
1487 	static unsigned char buf[4];
1488 	unsigned short opt;
1489 	unsigned int opt_length;
1490 
1491 	if (method != COAP_REQUEST_DELETE) {
1492 		opt = method == COAP_REQUEST_GET ? COAP_OPTION_BLOCK2 :
1493 							COAP_OPTION_BLOCK1;
1494 
1495 		block.m = (opt == COAP_OPTION_BLOCK1) &&
1496 			((1u << (block.szx + 4)) < payload.length);
1497 
1498 		opt_length = coap_encode_var_bytes(buf,
1499 				(block.num << 4 | block.m << 3 | block.szx));
1500 
1501 		coap_insert(&optlist, new_option_node(opt, opt_length, buf));
1502 	}
1503 }
1504 
my_coap_network_send(struct coap_context_t * ctx,const coap_endpoint_t * endpoint,const coap_address_t * dst,unsigned char * data,size_t datalen)1505 static ssize_t my_coap_network_send(struct coap_context_t *ctx,
1506 				    const coap_endpoint_t *endpoint,
1507 				    const coap_address_t *dst,
1508 				    unsigned char *data,
1509 				    size_t datalen)
1510 {
1511 	ssize_t bytes_written = dtls_write(dtls_context, &session,
1512 					   data, datalen);
1513 	if (bytes_written <= 0) {
1514 		coap_log(LOG_CRIT, "coap_send: sendto\n");
1515 	}
1516 
1517 	return bytes_written;
1518 }
1519 
my_coap_network_read(coap_endpoint_t * endpoint,coap_packet_t ** packet)1520 static ssize_t my_coap_network_read(coap_endpoint_t *endpoint,
1521 				    coap_packet_t **packet)
1522 {
1523 	printf("*** We should not get here if we are using DTLS ***\n");
1524 
1525 	return -EINVAL;
1526 }
1527 
get_coap_context(struct sockaddr * ipaddr,int ipaddrlen)1528 static coap_context_t *get_coap_context(struct sockaddr *ipaddr, int ipaddrlen)
1529 {
1530 	coap_address_t addr;
1531 	coap_context_t *ctx;
1532 
1533 	coap_address_init(&addr);
1534 	addr.size = ipaddrlen;
1535 	memcpy(&addr.addr, ipaddr, ipaddrlen);
1536 
1537 	ctx = coap_new_context(&addr);
1538 	if (!ctx)
1539 		return NULL;
1540 
1541 	if (!no_dtls) {
1542 		ctx->network_send = my_coap_network_send;
1543 		ctx->network_read = my_coap_network_read;
1544 	}
1545 
1546 	return ctx;
1547 }
1548 
set_token(char * arg)1549 static inline void set_token(char *arg)
1550 {
1551 	strncpy((char *)the_token.s, arg, min(sizeof(_token_data),
1552 					      strlen(arg)));
1553 	the_token.length = strlen(arg);
1554 }
1555 
1556 
1557 extern int optind, opterr, optopt;
1558 extern char *optarg;
1559 
1560 /* The application returns:
1561  *    < 0 : connection or similar error
1562  *      0 : no errors, all tests passed
1563  *    > 0 : could not send all the data to server
1564  */
main(int argc,char ** argv)1565 int main(int argc, char**argv)
1566 {
1567 	int c, ret, fd, timeout = 0;
1568 	struct sockaddr_in6 addr6_send = { 0 }, addr6_recv = { 0 };
1569 	struct sockaddr_in addr4_send = { 0 }, addr4_recv = { 0 };
1570 	struct sockaddr *addr_send, *addr_recv;
1571 	int addr_len;
1572 	const struct in6_addr any = IN6ADDR_ANY_INIT;
1573 	const char *interface = NULL;
1574 	fd_set rfds;
1575 	struct timeval tv = {};
1576 	int ifindex = -1, on, port;
1577 	void *address = NULL;
1578 	session_t dst;
1579 	struct client_data user_data = {};
1580 
1581 	coap_tid_t tid = COAP_INVALID_TID;
1582 	coap_context_t *coap_ctx;
1583 	coap_tick_t now;
1584 	coap_queue_t *nextpdu;
1585 	coap_pdu_t  *pdu;
1586 
1587 #ifdef DTLS_PSK
1588 	psk_id_length = strlen(PSK_DEFAULT_IDENTITY);
1589 	psk_key_length = strlen(PSK_DEFAULT_KEY);
1590 	memcpy(psk_id, PSK_DEFAULT_IDENTITY, psk_id_length);
1591 	memcpy(psk_key, PSK_DEFAULT_KEY, psk_key_length);
1592 #endif /* DTLS_PSK */
1593 
1594 	opterr = 0;
1595 
1596 	while ((c = getopt(argc, argv, "i:Drb:n")) != -1) {
1597 		switch (c) {
1598 		case 'i':
1599 			interface = optarg;
1600 			break;
1601 		case 'n':
1602 			no_dtls = true;
1603 			break;
1604 		case 'r':
1605 			/* Do a renegotiate once during the test run. */
1606 			srandom(time(0));
1607 			renegotiate = random() %
1608 				(sizeof(data) / sizeof(struct data) - 1);
1609 			printf("Renegotating after %d messages.\n", renegotiate);
1610 			break;
1611 		case 'D':
1612 			debug = true;
1613 			break;
1614 		case 'h':
1615 			goto usage;
1616 		}
1617 	}
1618 
1619 	if (optind < argc)
1620 		target = argv[optind];
1621 
1622 	if (!target) {
1623 	usage:
1624 		printf("usage: %s [-i tun0] [-D] [-r] [-n]"
1625 		       "<IPv{6|4} address of the dtls-server>\n",
1626 		       argv[0]);
1627 		printf("\t-i Use this network interface.\n");
1628 		printf("\t-n Do not use DTLS\n");
1629 		printf("\t-r Renegoating keys once during the test run.\n");
1630 		printf("\t-D Activate debugging.\n");
1631 		exit(-EINVAL);
1632 	}
1633 
1634 	if (inet_pton(AF_INET6, target, &addr6_send.sin6_addr) != 1) {
1635 		if (inet_pton(AF_INET, target, &addr4_send.sin_addr) != 1) {
1636 			printf("Invalid address family\n");
1637 			exit(-EINVAL);
1638 		} else {
1639 			addr_send = (struct sockaddr *)&addr4_send;
1640 			addr_recv = (struct sockaddr *)&addr4_recv;
1641 			if (no_dtls)
1642 				addr4_send.sin_port = port = htons(SERVER_PORT);
1643 			else
1644 				addr4_send.sin_port = port = htons(SERVER_SECURE_PORT);
1645 			addr4_recv.sin_family = AF_INET;
1646 			addr4_recv.sin_addr.s_addr = INADDR_ANY;
1647 			addr4_recv.sin_port = htons(CLIENT_PORT);
1648 			family = AF_INET;
1649 			addr_len = sizeof(addr4_send);
1650 			address = &addr4_recv.sin_addr;
1651 		}
1652 	} else {
1653 		addr_send = (struct sockaddr *)&addr6_send;
1654 		addr_recv = (struct sockaddr *)&addr6_recv;
1655 		if (no_dtls)
1656 			addr6_send.sin6_port = port = htons(SERVER_PORT);
1657 		else
1658 			addr6_send.sin6_port = port = htons(SERVER_SECURE_PORT);
1659 		addr6_recv.sin6_family = AF_INET6;
1660 		addr6_recv.sin6_addr = any;
1661 		addr6_recv.sin6_port = htons(CLIENT_PORT);
1662 		family = AF_INET6;
1663 		addr_len = sizeof(addr6_send);
1664 		address = &addr6_recv.sin6_addr;
1665 	}
1666 
1667 	addr_send->sa_family = family;
1668 	addr_recv->sa_family = family;
1669 
1670 	fd = socket(family, SOCK_DGRAM, IPPROTO_UDP);
1671 	if (fd < 0) {
1672 		perror("socket");
1673 		exit(-errno);
1674 	}
1675 
1676 	if (interface) {
1677 		struct ifreq ifr;
1678 		char addr_buf[INET6_ADDRSTRLEN];
1679 
1680 		memset(&ifr, 0, sizeof(ifr));
1681 		snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", interface);
1682 
1683 		if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,
1684 			       (void *)&ifr, sizeof(ifr)) < 0) {
1685 			perror("SO_BINDTODEVICE");
1686 			exit(-errno);
1687 		}
1688 
1689 		ifindex = get_ifindex(interface);
1690 		if (ifindex < 0) {
1691 			printf("Invalid interface %s\n", interface);
1692 			exit(-EINVAL);
1693 		}
1694 
1695 		ret = get_address(interface, family, address);
1696 		if (ret < 0) {
1697 			printf("Cannot find suitable source address "
1698 			       "for interface %s [%d/%s]\n",
1699 			       interface, ret, strerror(-ret));
1700 		}
1701 
1702 		printf("Binding to %s\n", inet_ntop(family, address,
1703 					    addr_buf, sizeof(addr_buf)));
1704 	}
1705 
1706 	coap_ctx = get_coap_context(addr_recv, addr_len);
1707 	if (!coap_ctx) {
1708 		printf("\nCannot get CoAP context\n");
1709 		exit(-1);
1710 	}
1711 
1712 	/* We do not use libcoap fd but our own so we can bind to this
1713 	 * specific interface. Done like this so that we do not need
1714 	 * to modify libcoap.
1715 	 */
1716 	close(coap_ctx->endpoint->handle.fd);
1717 
1718 	ret = bind(fd, addr_recv, addr_len);
1719 	if (ret < 0) {
1720 		perror("bind");
1721 		exit(-errno);
1722 	}
1723 
1724 	on = 1;
1725 #ifdef IPV6_RECVPKTINFO
1726 	if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on,
1727 		       sizeof(on) ) < 0) {
1728 #else /* IPV6_RECVPKTINFO */
1729 	if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &on,
1730 		       sizeof(on) ) < 0) {
1731 #endif /* IPV6_RECVPKTINFO */
1732 		printf("setsockopt IPV6_PKTINFO: %s\n", strerror(errno));
1733 	}
1734 	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) ) < 0) {
1735 		printf("setsockopt SO_REUSEADDR: %s\n", strerror(errno));
1736 	}
1737 
1738 	signal(SIGINT, signal_handler);
1739 	signal(SIGTERM, signal_handler);
1740 
1741 	user_data.fd = fd;
1742 	user_data.index = 0;
1743 	user_data.ifindex = ifindex;
1744 
1745 	user_data.coap_ctx = coap_ctx;
1746 	coap_ctx->endpoint->handle.fd = fd;
1747 
1748 	coap_address_init(&user_data.coap_dst);
1749 	memcpy(&user_data.coap_dst.addr, addr_send, addr_len);
1750 	user_data.coap_dst.size = addr_len;
1751 
1752 	if (debug)
1753 		coap_set_log_level(LOG_DEBUG);
1754 
1755 	coap_register_option(coap_ctx, COAP_OPTION_BLOCK2);
1756 	coap_register_response_handler(coap_ctx, coap_message_handler);
1757 	set_coap_timeout(&max_wait, wait_seconds);
1758 	printf("CoAP timeout is set to %d seconds\n", wait_seconds);
1759 
1760 	coap_insert(&optlist,
1761                     new_option_node(COAP_OPTION_URI_HOST,
1762 				    strlen(target),
1763 				    (char *)target));
1764 
1765 	if (port) {
1766 		unsigned char p[2];
1767 		p[0] = ntohs(port) >> 8;
1768 		p[1] = ntohs(port) & 0xff;
1769 		coap_insert(&optlist,
1770 			    new_option_node(COAP_OPTION_URI_PORT,
1771 					    2, p));
1772 	}
1773 
1774 	printf("Connecting to port %d\n", ntohs(port));
1775 
1776 	if (!no_dtls) {
1777 		dtls_init();
1778 
1779 		memset(&dst, 0, sizeof(dst));
1780 		memcpy(&dst.addr.sa, addr_send, addr_len);
1781 		dst.size = addr_len;
1782 
1783 		dtls_context = dtls_new_context(&user_data);
1784 		if (!dtls_context) {
1785 			dtls_emerg("cannot create context\n");
1786 			exit(-EINVAL);
1787 		}
1788 
1789 		dtls_set_handler(dtls_context, &cb);
1790 
1791 		if (debug)
1792 			dtls_set_log_level(DTLS_LOG_DEBUG);
1793 
1794 		dtls_connect(dtls_context, &dst);
1795 	}
1796 
1797 	set_token("07162534");
1798 
1799 	do {
1800 		FD_ZERO(&rfds);
1801 		FD_SET(fd, &rfds);
1802 		tv.tv_sec = MAX_TIMEOUT;
1803 		tv.tv_usec = 0;
1804 
1805 		if (no_dtls)
1806 			send_packets(&user_data);
1807 
1808 		if (quit || user_data.fail)
1809 			break;
1810 
1811 		nextpdu = coap_peek_next(coap_ctx);
1812 
1813 		coap_ticks(&now);
1814 		while (nextpdu && nextpdu->t <=
1815 		       (now - coap_ctx->sendqueue_basetime)) {
1816 			coap_retransmit(coap_ctx, coap_pop_next(coap_ctx));
1817 			nextpdu = coap_peek_next(coap_ctx);
1818 		}
1819 
1820 		if (nextpdu && nextpdu->t < min(obs_wait ? obs_wait : max_wait,
1821 						max_wait) - now) {
1822 			tv.tv_usec = ((nextpdu->t) % COAP_TICKS_PER_SECOND) *
1823 				1000000 / COAP_TICKS_PER_SECOND;
1824 			tv.tv_sec = (nextpdu->t) / COAP_TICKS_PER_SECOND;
1825 		} else {
1826 			if (obs_wait && obs_wait < max_wait) {
1827 				tv.tv_usec = ((obs_wait - now) %
1828 					    COAP_TICKS_PER_SECOND) * 1000000 /
1829 							COAP_TICKS_PER_SECOND;
1830 				tv.tv_sec = (obs_wait - now) /
1831 							COAP_TICKS_PER_SECOND;
1832 			} else {
1833 				tv.tv_usec = ((max_wait - now) %
1834 					    COAP_TICKS_PER_SECOND) * 1000000 /
1835 							COAP_TICKS_PER_SECOND;
1836 				tv.tv_sec = (max_wait - now) /
1837 							COAP_TICKS_PER_SECOND;
1838 			}
1839 		}
1840 
1841 		ret = select(fd + 1, &rfds, NULL, NULL, &tv);
1842 		if (ret < 0) {
1843 			perror("select");
1844 			break;
1845 		} else if (ret == 0) {
1846 			if (quit)
1847 				break;
1848 
1849 			if (user_data.index >
1850 			    (sizeof(data) / sizeof(struct data)) - 1)
1851 				break;
1852 
1853 			if (!data[user_data.index].expecting_reply) {
1854 				printf("Did not expect a reply, send next entry.\n");
1855 				user_data.index++;
1856 				if (!data[user_data.index].buf) {
1857 					user_data.fail = true;
1858 					break;
1859 				}
1860 				continue;
1861 			}
1862 
1863 			fprintf(stderr,	"Timeout [%d] while waiting len %d\n",
1864 				user_data.index, data[user_data.index].len);
1865 			ret = user_data.index + 1;
1866 			user_data.fail = true;
1867 			break;
1868 		} else if (!FD_ISSET(fd, &rfds)) {
1869 			fprintf(stderr, "Invalid fd in read, quitting.\n");
1870 			ret = user_data.index + 1;
1871 			user_data.fail = true;
1872 			break;
1873 		}
1874 
1875 		if (!no_dtls) {
1876 			if (dtls_handle_read(dtls_context) < 0) {
1877 				fprintf(stderr, "Peer connection failed.\n");
1878 				ret = user_data.index + 1;
1879 				user_data.fail = true;
1880 				break;
1881 			}
1882 		} else {
1883 			user_data.fd = fd;
1884 			if (read_data_from_net(&user_data) < 0) {
1885 				fprintf(stderr, "Packet read error.\n");
1886 				ret = user_data.index + 1;
1887 				user_data.fail = true;
1888 				break;
1889 			}
1890 		}
1891 
1892 	} while(!quit);
1893 
1894 	printf("\n");
1895 
1896 	if (!no_dtls)
1897 		dtls_close(dtls_context, &dst);
1898 
1899 	dtls_free_context(dtls_context);
1900 
1901 	close(fd);
1902 
1903 	if (!user_data.fail) {
1904 		if (debug)
1905 			printf("Weird: No failures but error code (%d) "
1906 			       "indicates error\n", ret);
1907 		ret = 0;
1908 	}
1909 
1910 	exit(ret);
1911 }
1912