1 /**
2  * @file openssl/tls_udp.c DTLS backend using OpenSSL
3  *
4  * Copyright (C) 2010 Creytiv.com
5  */
6 
7 #include <sys/time.h>
8 #include <openssl/ssl.h>
9 #include <openssl/err.h>
10 #include <re_types.h>
11 #include <re_fmt.h>
12 #include <re_mem.h>
13 #include <re_mbuf.h>
14 #include <re_list.h>
15 #include <re_hash.h>
16 #include <re_sa.h>
17 #include <re_srtp.h>
18 #include <re_udp.h>
19 #include <re_tmr.h>
20 #include <re_tls.h>
21 #include "tls.h"
22 
23 
24 #define DEBUG_MODULE "dtls"
25 #define DEBUG_LEVEL 5
26 #include <re_dbg.h>
27 
28 
29 enum {
30 	MTU_DEFAULT  = 1400,
31 	MTU_FALLBACK = 548,
32 };
33 
34 
35 struct dtls_sock {
36 	struct sa peer;
37 	struct udp_helper *uh;
38 	struct udp_sock *us;
39 	struct hash *ht;
40 	struct mbuf *mb;
41 	dtls_conn_h *connh;
42 	void *arg;
43 	size_t mtu;
44 };
45 
46 
47 /* NOTE: shadow struct defined in tls_*.c */
48 struct tls_conn {
49 	SSL *ssl;             /* inheritance */
50 #ifdef TLS_BIO_OPAQUE
51 	BIO_METHOD *biomet;
52 #endif
53 	BIO *sbio_out;
54 	BIO *sbio_in;
55 	struct tmr tmr;
56 	struct sa peer;
57 	struct le he;
58 	struct dtls_sock *sock;
59 	dtls_estab_h *estabh;
60 	dtls_recv_h *recvh;
61 	dtls_close_h *closeh;
62 	void *arg;
63 	bool active;
64 	bool up;
65 };
66 
67 
bio_create(BIO * b)68 static int bio_create(BIO *b)
69 {
70 #ifdef TLS_BIO_OPAQUE
71 	BIO_set_init(b, 1);
72 	BIO_set_data(b, NULL);
73 	BIO_set_flags(b, 0);
74 #else
75 	b->init  = 1;
76 	b->num   = 0;
77 	b->ptr   = NULL;
78 	b->flags = 0;
79 #endif
80 
81 	return 1;
82 }
83 
84 
bio_destroy(BIO * b)85 static int bio_destroy(BIO *b)
86 {
87 	if (!b)
88 		return 0;
89 
90 #ifdef TLS_BIO_OPAQUE
91 	BIO_set_init(b, 0);
92 	BIO_set_data(b, NULL);
93 	BIO_set_flags(b, 0);
94 #else
95 	b->ptr   = NULL;
96 	b->init  = 0;
97 	b->flags = 0;
98 #endif
99 
100 	return 1;
101 }
102 
103 
bio_write(BIO * b,const char * buf,int len)104 static int bio_write(BIO *b, const char *buf, int len)
105 {
106 #ifdef TLS_BIO_OPAQUE
107 	struct tls_conn *tc = BIO_get_data(b);
108 #else
109 	struct tls_conn *tc = b->ptr;
110 #endif
111 	struct mbuf *mb;
112 	enum {SPACE = 4};
113 	int err;
114 
115 	mb = mbuf_alloc(SPACE + len);
116 	if (!mb)
117 		return -1;
118 
119 	mb->pos = SPACE;
120 	(void)mbuf_write_mem(mb, (void *)buf, len);
121 	mb->pos = SPACE;
122 
123 	err = udp_send_helper(tc->sock->us, &tc->peer, mb, tc->sock->uh);
124 
125 	mem_deref(mb);
126 
127 	return err ? -1 : len;
128 }
129 
130 
bio_ctrl(BIO * b,int cmd,long num,void * ptr)131 static long bio_ctrl(BIO *b, int cmd, long num, void *ptr)
132 {
133 #ifdef TLS_BIO_OPAQUE
134 	struct tls_conn *tc = BIO_get_data(b);
135 #else
136 	struct tls_conn *tc = b->ptr;
137 #endif
138 	(void)num;
139 	(void)ptr;
140 
141 	switch (cmd) {
142 
143 	case BIO_CTRL_FLUSH:
144 		/* The OpenSSL library needs this */
145 		return 1;
146 
147 #if defined (BIO_CTRL_DGRAM_QUERY_MTU)
148 	case BIO_CTRL_DGRAM_QUERY_MTU:
149 		return tc ? tc->sock->mtu : MTU_DEFAULT;
150 #endif
151 
152 #if defined (BIO_CTRL_DGRAM_GET_FALLBACK_MTU)
153 	case BIO_CTRL_DGRAM_GET_FALLBACK_MTU:
154 		return MTU_FALLBACK;
155 #endif
156 	}
157 
158 	return 0;
159 }
160 
161 
162 #ifdef TLS_BIO_OPAQUE
163 
bio_method_udp(void)164 static BIO_METHOD *bio_method_udp(void)
165 {
166 	BIO_METHOD *method;
167 
168 	method = BIO_meth_new(BIO_TYPE_SOURCE_SINK, "udp_send");
169 	if (!method) {
170 		DEBUG_WARNING("alloc: BIO_meth_new() failed\n");
171 		ERR_clear_error();
172 		return NULL;
173 	}
174 
175 	BIO_meth_set_write(method, bio_write);
176 	BIO_meth_set_ctrl(method, bio_ctrl);
177 	BIO_meth_set_create(method, bio_create);
178 	BIO_meth_set_destroy(method, bio_destroy);
179 
180 	return method;
181 }
182 
183 #else
184 
185 static struct bio_method_st bio_udp_send = {
186 	BIO_TYPE_SOURCE_SINK,
187 	"udp_send",
188 	bio_write,
189 	0,
190 	0,
191 	0,
192 	bio_ctrl,
193 	bio_create,
194 	bio_destroy,
195 	0
196 };
197 
198 #endif
199 
200 
tls_close(struct tls_conn * tc)201 static void tls_close(struct tls_conn *tc)
202 {
203 	int r;
204 
205 	if (!tc->ssl)
206 		return;
207 
208 	r = SSL_shutdown(tc->ssl);
209 	if (r <= 0)
210 		ERR_clear_error();
211 
212 	SSL_free(tc->ssl);
213 	tc->ssl = NULL;
214 }
215 
216 
conn_destructor(void * arg)217 static void conn_destructor(void *arg)
218 {
219 	struct tls_conn *tc = arg;
220 
221 	hash_unlink(&tc->he);
222 	tmr_cancel(&tc->tmr);
223 	tls_close(tc);
224 
225 #ifdef TLS_BIO_OPAQUE
226 	if (tc->biomet)
227 		BIO_meth_free(tc->biomet);
228 #endif
229 
230 	mem_deref(tc->sock);
231 }
232 
233 
conn_close(struct tls_conn * tc,int err)234 static void conn_close(struct tls_conn *tc, int err)
235 {
236 	tmr_cancel(&tc->tmr);
237 	tls_close(tc);
238 	tc->up = false;
239 
240 	if (tc->closeh)
241 		tc->closeh(err, tc->arg);
242 }
243 
244 
245 #if defined (DTLS_CTRL_HANDLE_TIMEOUT) && defined(DTLS_CTRL_GET_TIMEOUT)
246 
247 static void check_timer(struct tls_conn *tc);
248 
249 
timeout(void * arg)250 static void timeout(void *arg)
251 {
252 	struct tls_conn *tc = arg;
253 
254 	DEBUG_INFO("timeout\n");
255 
256 	if (0 <= DTLSv1_handle_timeout(tc->ssl)) {
257 
258 		check_timer(tc);
259 	}
260 	else {
261 		ERR_clear_error();
262 		conn_close(tc, ETIMEDOUT);
263 	}
264 }
265 
266 
check_timer(struct tls_conn * tc)267 static void check_timer(struct tls_conn *tc)
268 {
269 	struct timeval tv = {0, 0};
270 
271 	if (1 == DTLSv1_get_timeout(tc->ssl, &tv)) {
272 
273 		tmr_start(&tc->tmr, tv.tv_sec * 1000 + tv.tv_usec / 1000,
274 			  timeout, tc);
275 	}
276 	else {
277 		tmr_cancel(&tc->tmr);
278 	}
279 }
280 
281 #else
282 
check_timer(struct tls_conn * tc)283 static void check_timer(struct tls_conn *tc)
284 {
285 	(void)tc;
286 }
287 
288 #endif
289 
290 
tls_connect(struct tls_conn * tc)291 static int tls_connect(struct tls_conn *tc)
292 {
293 	int r;
294 
295 	ERR_clear_error();
296 
297 	r = SSL_connect(tc->ssl);
298 	if (r <= 0) {
299 		const int ssl_err = SSL_get_error(tc->ssl, r);
300 
301 		tls_flush_error();
302 
303 		switch (ssl_err) {
304 
305 		case SSL_ERROR_WANT_READ:
306 			break;
307 
308 		default:
309 			DEBUG_WARNING("connect error: %i\n", ssl_err);
310 			return EPROTO;
311 		}
312 	}
313 
314 	check_timer(tc);
315 
316 	return 0;
317 }
318 
319 
tls_accept(struct tls_conn * tc)320 static int tls_accept(struct tls_conn *tc)
321 {
322 	int r;
323 
324 	ERR_clear_error();
325 
326 	r = SSL_accept(tc->ssl);
327 	if (r <= 0) {
328 		const int ssl_err = SSL_get_error(tc->ssl, r);
329 
330 		tls_flush_error();
331 
332 		switch (ssl_err) {
333 
334 		case SSL_ERROR_WANT_READ:
335 			break;
336 
337 		default:
338 			DEBUG_WARNING("accept error: %i\n", ssl_err);
339 			return EPROTO;
340 		}
341 	}
342 
343 	check_timer(tc);
344 
345 	return 0;
346 }
347 
348 
conn_recv(struct tls_conn * tc,struct mbuf * mb)349 static void conn_recv(struct tls_conn *tc, struct mbuf *mb)
350 {
351 	int err, r;
352 
353 	if (!tc->ssl)
354 		return;
355 
356 	/* feed SSL data to the BIO */
357 	r = BIO_write(tc->sbio_in, mbuf_buf(mb), (int)mbuf_get_left(mb));
358 	if (r <= 0) {
359 		DEBUG_WARNING("receive bio write error: %i\n", r);
360 		ERR_clear_error();
361 		conn_close(tc, ENOMEM);
362 		return;
363 	}
364 
365 	if (SSL_state(tc->ssl) != SSL_ST_OK) {
366 
367 		if (tc->up) {
368 			conn_close(tc, EPROTO);
369 			return;
370 		}
371 
372 		if (tc->active) {
373 			err = tls_connect(tc);
374 		}
375 		else {
376 			err = tls_accept(tc);
377 		}
378 
379 		if (err) {
380 			conn_close(tc, err);
381 			return;
382 		}
383 
384 		DEBUG_INFO("%s: state=0x%04x\n",
385 			   tc->active ? "client" : "server",
386 			   SSL_state(tc->ssl));
387 
388 		/* TLS connection is established */
389 		if (SSL_state(tc->ssl) != SSL_ST_OK)
390 			return;
391 
392 		tc->up = true;
393 
394 		if (tc->estabh) {
395 			uint32_t nrefs;
396 
397 			mem_ref(tc);
398 
399 			tc->estabh(tc->arg);
400 
401                         nrefs = mem_nrefs(tc);
402                         mem_deref(tc);
403 
404                         /* check if connection was deref'd from handler */
405                         if (nrefs == 1)
406                                 return;
407 		}
408 	}
409 
410 	mbuf_set_pos(mb, 0);
411 
412 	for (;;) {
413 		int n;
414 
415 		if (mbuf_get_space(mb) < 4096) {
416 			err = mbuf_resize(mb, mb->size + 8192);
417 			if (err) {
418 				conn_close(tc, err);
419 				return;
420 			}
421 		}
422 
423 		ERR_clear_error();
424 
425 		n = SSL_read(tc->ssl, mbuf_buf(mb), (int)mbuf_get_space(mb));
426 		if (n <= 0) {
427 			const int ssl_err = SSL_get_error(tc->ssl, n);
428 
429 			ERR_clear_error();
430 
431 			switch (ssl_err) {
432 
433 			case SSL_ERROR_WANT_READ:
434 				break;
435 
436 			case SSL_ERROR_ZERO_RETURN:
437 				conn_close(tc, ECONNRESET);
438 				return;
439 
440 			default:
441 				DEBUG_WARNING("read error: %i\n", ssl_err);
442 				conn_close(tc, EPROTO);
443 				return;
444 			}
445 
446 			break;
447 		}
448 
449 		mb->pos += n;
450 	}
451 
452 	mbuf_set_end(mb, mb->pos);
453 	mbuf_set_pos(mb, 0);
454 
455 	if (tc->recvh && mbuf_get_left(mb) > 0)
456 		tc->recvh(mb, tc->arg);
457 
458 	return;
459 }
460 
461 
conn_alloc(struct tls_conn ** ptc,struct tls * tls,struct dtls_sock * sock,const struct sa * peer,dtls_estab_h * estabh,dtls_recv_h * recvh,dtls_close_h * closeh,void * arg)462 static int conn_alloc(struct tls_conn **ptc, struct tls *tls,
463 		      struct dtls_sock *sock, const struct sa *peer,
464 		      dtls_estab_h *estabh, dtls_recv_h *recvh,
465 		      dtls_close_h *closeh, void *arg)
466 {
467 	struct tls_conn *tc;
468 	int err = 0;
469 
470 	tc = mem_zalloc(sizeof(*tc), conn_destructor);
471 	if (!tc)
472 		return ENOMEM;
473 
474 	hash_append(sock->ht, sa_hash(peer, SA_ALL), &tc->he, tc);
475 
476 	tc->sock   = mem_ref(sock);
477 	tc->peer   = *peer;
478 	tc->estabh = estabh;
479 	tc->recvh  = recvh;
480 	tc->closeh = closeh;
481 	tc->arg    = arg;
482 
483 #ifdef TLS_BIO_OPAQUE
484 	tc->biomet = bio_method_udp();
485 	if (!tc->biomet) {
486 		err = ENOMEM;
487 		goto out;
488 	}
489 #endif
490 
491 	/* Connect the SSL socket */
492 	tc->ssl = SSL_new(tls->ctx);
493 	if (!tc->ssl) {
494 		DEBUG_WARNING("ssl new failed: %i\n",
495 			      ERR_GET_REASON(ERR_get_error()));
496 		ERR_clear_error();
497 		err = ENOMEM;
498 		goto out;
499 	}
500 
501 	tc->sbio_in = BIO_new(BIO_s_mem());
502 	if (!tc->sbio_in) {
503 		ERR_clear_error();
504 		err = ENOMEM;
505 		goto out;
506 	}
507 
508 #ifdef TLS_BIO_OPAQUE
509 	tc->sbio_out = BIO_new(tc->biomet);
510 #else
511 	tc->sbio_out = BIO_new(&bio_udp_send);
512 #endif
513 	if (!tc->sbio_out) {
514 		ERR_clear_error();
515 		BIO_free(tc->sbio_in);
516 		err = ENOMEM;
517 		goto out;
518 	}
519 
520 #ifdef TLS_BIO_OPAQUE
521 	BIO_set_data(tc->sbio_out, tc);
522 #else
523 	tc->sbio_out->ptr = tc;
524 #endif
525 
526 	SSL_set_bio(tc->ssl, tc->sbio_in, tc->sbio_out);
527 
528 	SSL_set_read_ahead(tc->ssl, 1);
529 
530  out:
531 	if (err)
532 		mem_deref(tc);
533 	else
534 		*ptc = tc;
535 
536 	return err;
537 }
538 
539 
540 /**
541  * DTLS Connect
542  *
543  * @param ptc    Pointer to allocated DTLS connection
544  * @param tls    TLS Context
545  * @param sock   DTLS Socket
546  * @param peer   Peer address
547  * @param estabh Establish handler
548  * @param recvh  Receive handler
549  * @param closeh Close handler
550  * @param arg    Handler argument
551  *
552  * @return 0 if success, otherwise errorcode
553  */
dtls_connect(struct tls_conn ** ptc,struct tls * tls,struct dtls_sock * sock,const struct sa * peer,dtls_estab_h * estabh,dtls_recv_h * recvh,dtls_close_h * closeh,void * arg)554 int dtls_connect(struct tls_conn **ptc, struct tls *tls,
555 		 struct dtls_sock *sock, const struct sa *peer,
556 		 dtls_estab_h *estabh, dtls_recv_h *recvh,
557 		 dtls_close_h *closeh, void *arg)
558 {
559 	struct tls_conn *tc;
560 	int err;
561 
562 	if (!ptc || !tls || !sock || !peer)
563 		return EINVAL;
564 
565 	err = conn_alloc(&tc, tls, sock, peer, estabh, recvh, closeh, arg);
566 	if (err)
567 		return err;
568 
569 	tc->active = true;
570 
571 	err = tls_connect(tc);
572 	if (err)
573 		goto out;
574 
575  out:
576 	if (err)
577 		mem_deref(tc);
578 	else
579 		*ptc = tc;
580 
581 	return err;
582 }
583 
584 
585 /**
586  * DTLS Accept
587  *
588  * @param ptc    Pointer to allocated DTLS connection
589  * @param tls    TLS Context
590  * @param sock   DTLS Socket
591  * @param estabh Establish handler
592  * @param recvh  Receive handler
593  * @param closeh Close handler
594  * @param arg    Handler argument
595  *
596  * @return 0 if success, otherwise errorcode
597  */
dtls_accept(struct tls_conn ** ptc,struct tls * tls,struct dtls_sock * sock,dtls_estab_h * estabh,dtls_recv_h * recvh,dtls_close_h * closeh,void * arg)598 int dtls_accept(struct tls_conn **ptc, struct tls *tls,
599 		struct dtls_sock *sock,
600 		dtls_estab_h *estabh, dtls_recv_h *recvh,
601 		dtls_close_h *closeh, void *arg)
602 {
603 	struct tls_conn *tc;
604 	int err, r;
605 
606 	if (!ptc || !tls || !sock || !sock->mb)
607 		return EINVAL;
608 
609 	err = conn_alloc(&tc, tls, sock, &sock->peer, estabh, recvh, closeh,
610 			 arg);
611 	if (err)
612 		return err;
613 
614 	tc->active = false;
615 
616 	r = BIO_write(tc->sbio_in, mbuf_buf(sock->mb),
617 		      (int)mbuf_get_left(sock->mb));
618 	if (r <= 0) {
619 		DEBUG_WARNING("accept bio write error: %i\n", r);
620 		ERR_clear_error();
621 		err = ENOMEM;
622 		goto out;
623 	}
624 
625 	err = tls_accept(tc);
626 	if (err)
627 		goto out;
628 
629 	sock->mb = mem_deref(sock->mb);
630 
631  out:
632 	if (err)
633 		mem_deref(tc);
634 	else
635 		*ptc = tc;
636 
637 	return err;
638 }
639 
640 
641 /**
642  * Send data on a DTLS connection
643  *
644  * @param tc DTLS connection
645  * @param mb Buffer to send
646  *
647  * @return 0 if success, otherwise errorcode
648  */
dtls_send(struct tls_conn * tc,struct mbuf * mb)649 int dtls_send(struct tls_conn *tc, struct mbuf *mb)
650 {
651 	int r;
652 
653 	if (!tc || !mb)
654 		return EINVAL;
655 
656 	if (!tc->up || !tc->ssl)
657 		return ENOTCONN;
658 
659 	ERR_clear_error();
660 
661 	r = SSL_write(tc->ssl, mbuf_buf(mb), (int)mbuf_get_left(mb));
662 	if (r <= 0) {
663 		DEBUG_WARNING("write error: %i\n", SSL_get_error(tc->ssl, r));
664 		ERR_clear_error();
665 		return EPROTO;
666 	}
667 
668 	return 0;
669 }
670 
671 
672 /**
673  * Set handlers on a DTLS Connection
674  *
675  * @param tc     DTLS Connection
676  * @param estabh DTLS Connection Established handler
677  * @param recvh  DTLS Connection Receive data handler
678  * @param closeh DTLS Connection Close handler
679  * @param arg    Handler argument
680  */
dtls_set_handlers(struct tls_conn * tc,dtls_estab_h * estabh,dtls_recv_h * recvh,dtls_close_h * closeh,void * arg)681 void dtls_set_handlers(struct tls_conn *tc, dtls_estab_h *estabh,
682 		       dtls_recv_h *recvh, dtls_close_h *closeh, void *arg)
683 {
684 	if (!tc)
685 		return;
686 
687 	tc->estabh = estabh;
688 	tc->recvh  = recvh;
689 	tc->closeh = closeh;
690 	tc->arg    = arg;
691 }
692 
693 
694 /**
695  * Get the remote peer of a DTLS Connection
696  *
697  * @param tc DTLS Connection
698  *
699  * @return Remote peer
700  */
dtls_peer(const struct tls_conn * tc)701 const struct sa *dtls_peer(const struct tls_conn *tc)
702 {
703 	return tc ? &tc->peer : NULL;
704 }
705 
706 
707 /**
708  * Set the remote peer of a DTLS Connection
709  *
710  * @param tc     DTLS Connection
711  * @param peer   Peer address
712  */
dtls_set_peer(struct tls_conn * tc,const struct sa * peer)713 void dtls_set_peer(struct tls_conn *tc, const struct sa *peer)
714 {
715 	if (!tc || !peer)
716 		return;
717 
718 	hash_unlink(&tc->he);
719 	hash_append(tc->sock->ht, sa_hash(peer, SA_ALL), &tc->he, tc);
720 
721 	tc->peer = *peer;
722 }
723 
724 
sock_destructor(void * arg)725 static void sock_destructor(void *arg)
726 {
727 	struct dtls_sock *sock = arg;
728 
729 	hash_clear(sock->ht);
730 	mem_deref(sock->uh);
731 	mem_deref(sock->us);
732 	mem_deref(sock->ht);
733 	mem_deref(sock->mb);
734 }
735 
736 
cmp_handler(struct le * le,void * arg)737 static bool cmp_handler(struct le *le, void *arg)
738 {
739 	struct tls_conn *tc = le->data;
740 
741 	return sa_cmp(&tc->peer, arg, SA_ALL);
742 }
743 
744 
conn_lookup(struct dtls_sock * sock,const struct sa * peer)745 static struct tls_conn *conn_lookup(struct dtls_sock *sock,
746 				    const struct sa *peer)
747 {
748 	return list_ledata(hash_lookup(sock->ht, sa_hash(peer, SA_ALL),
749                                        cmp_handler, (void *)peer));
750 }
751 
752 
recv_handler(struct sa * src,struct mbuf * mb,void * arg)753 static bool recv_handler(struct sa *src, struct mbuf *mb, void *arg)
754 {
755 	struct dtls_sock *sock = arg;
756 	struct tls_conn *tc;
757 	uint8_t b;
758 
759 	if (mbuf_get_left(mb) < 1)
760 		return false;
761 
762 	b = mb->buf[mb->pos];
763 	if (b < 20 || b > 63)
764 		return false;
765 
766 	tc = conn_lookup(sock, src);
767 	if (tc) {
768 		conn_recv(tc, mb);
769 		return true;
770 	}
771 
772 	if (sock->connh) {
773 
774 		mem_deref(sock->mb);
775 		sock->mb   = mem_ref(mb);
776 		sock->peer = *src;
777 
778 		sock->connh(src, sock->arg);
779 	}
780 
781 	return true;
782 }
783 
784 
785 /**
786  * Create DTLS Socket
787  *
788  * @param sockp  Pointer to returned DTLS Socket
789  * @param laddr  Local listen address (optional)
790  * @param us     External UDP socket (optional)
791  * @param htsize Connection hash table size
792  * @param layer  UDP protocol layer
793  * @param connh  Connect handler
794  * @param arg    Handler argument
795  *
796  * @return 0 if success, otherwise errorcode
797  */
dtls_listen(struct dtls_sock ** sockp,const struct sa * laddr,struct udp_sock * us,uint32_t htsize,int layer,dtls_conn_h * connh,void * arg)798 int dtls_listen(struct dtls_sock **sockp, const struct sa *laddr,
799 		struct udp_sock *us, uint32_t htsize, int layer,
800 		dtls_conn_h *connh, void *arg)
801 {
802 	struct dtls_sock *sock;
803 	int err;
804 
805 	if (!sockp)
806 		return EINVAL;
807 
808 	sock = mem_zalloc(sizeof(*sock), sock_destructor);
809 	if (!sock)
810 		return ENOMEM;
811 
812 	if (us) {
813 		sock->us = mem_ref(us);
814 	}
815 	else {
816 		err = udp_listen(&sock->us, laddr, NULL, NULL);
817 		if (err)
818 			goto out;
819 	}
820 
821 	err = udp_register_helper(&sock->uh, sock->us, layer,
822 				  NULL, recv_handler, sock);
823 	if (err)
824 		goto out;
825 
826 	err = hash_alloc(&sock->ht, hash_valid_size(htsize));
827 	if (err)
828 		goto out;
829 
830 	sock->mtu   = MTU_DEFAULT;
831 	sock->connh = connh;
832 	sock->arg   = arg;
833 
834  out:
835 	if (err)
836 		mem_deref(sock);
837 	else
838 		*sockp = sock;
839 
840 	return err;
841 }
842 
843 
844 /**
845  * Get the underlying UDP socket of a DTLS Socket
846  *
847  * @param sock DTLS Socket
848  *
849  * @return UDP Socket
850  */
dtls_udp_sock(struct dtls_sock * sock)851 struct udp_sock *dtls_udp_sock(struct dtls_sock *sock)
852 {
853 	return sock ? sock->us : NULL;
854 }
855 
856 
857 /**
858  * Set MTU on a DTLS Socket
859  *
860  * @param sock DTLS Socket
861  * @param mtu  MTU value
862  */
dtls_set_mtu(struct dtls_sock * sock,size_t mtu)863 void dtls_set_mtu(struct dtls_sock *sock, size_t mtu)
864 {
865 	if (!sock)
866 		return;
867 
868 	sock->mtu = mtu;
869 }
870 
871 
dtls_recv_packet(struct dtls_sock * sock,const struct sa * src,struct mbuf * mb)872 void dtls_recv_packet(struct dtls_sock *sock, const struct sa *src,
873 		      struct mbuf *mb)
874 {
875 	struct sa addr;
876 
877 	if (!sock || !src || !mb)
878 		return;
879 
880 	addr = *src;
881 
882 	recv_handler(&addr, mb, sock);
883 }
884