OpenCoverage

bss_dgram.c

Absolute File Name:/home/opencoverage/opencoverage/guest-scripts/openssl/src/crypto/bio/bss_dgram.c
Source codeSwitch to Preprocessed file
LineSourceCount
1/*-
2 * Copyright 2005-2018 The OpenSSL Project Authors. All Rights Reserved.-
3 *-
4 * Licensed under the OpenSSL license (the "License"). You may not use-
5 * this file except in compliance with the License. You can obtain a copy-
6 * in the file LICENSE in the source distribution or at-
7 * https://www.openssl.org/source/license.html-
8 */-
9-
10#include <stdio.h>-
11#include <errno.h>-
12-
13#include "bio_lcl.h"-
14#ifndef OPENSSL_NO_DGRAM-
15-
16# ifndef OPENSSL_NO_SCTP-
17# include <netinet/sctp.h>-
18# include <fcntl.h>-
19# define OPENSSL_SCTP_DATA_CHUNK_TYPE 0x00-
20# define OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE 0xc0-
21# endif-
22-
23# if defined(OPENSSL_SYS_LINUX) && !defined(IP_MTU)-
24# define IP_MTU 14 /* linux is lame */-
25# endif-
26-
27# if OPENSSL_USE_IPV6 && !defined(IPPROTO_IPV6)-
28# define IPPROTO_IPV6 41 /* windows is lame */-
29# endif-
30-
31# if defined(__FreeBSD__) && defined(IN6_IS_ADDR_V4MAPPED)-
32/* Standard definition causes type-punning problems. */-
33# undef IN6_IS_ADDR_V4MAPPED-
34# define s6_addr32 __u6_addr.__u6_addr32-
35# define IN6_IS_ADDR_V4MAPPED(a) \-
36 (((a)->s6_addr32[0] == 0) && \-
37 ((a)->s6_addr32[1] == 0) && \-
38 ((a)->s6_addr32[2] == htonl(0x0000ffff)))-
39# endif-
40-
41static int dgram_write(BIO *h, const char *buf, int num);-
42static int dgram_read(BIO *h, char *buf, int size);-
43static int dgram_puts(BIO *h, const char *str);-
44static long dgram_ctrl(BIO *h, int cmd, long arg1, void *arg2);-
45static int dgram_new(BIO *h);-
46static int dgram_free(BIO *data);-
47static int dgram_clear(BIO *bio);-
48-
49# ifndef OPENSSL_NO_SCTP-
50static int dgram_sctp_write(BIO *h, const char *buf, int num);-
51static int dgram_sctp_read(BIO *h, char *buf, int size);-
52static int dgram_sctp_puts(BIO *h, const char *str);-
53static long dgram_sctp_ctrl(BIO *h, int cmd, long arg1, void *arg2);-
54static int dgram_sctp_new(BIO *h);-
55static int dgram_sctp_free(BIO *data);-
56# ifdef SCTP_AUTHENTICATION_EVENT-
57static void dgram_sctp_handle_auth_free_key_event(BIO *b, union sctp_notification-
58 *snp);-
59# endif-
60# endif-
61-
62static int BIO_dgram_should_retry(int s);-
63-
64static void get_current_time(struct timeval *t);-
65-
66static const BIO_METHOD methods_dgramp = {-
67 BIO_TYPE_DGRAM,-
68 "datagram socket",-
69 /* TODO: Convert to new style write function */-
70 bwrite_conv,-
71 dgram_write,-
72 /* TODO: Convert to new style read function */-
73 bread_conv,-
74 dgram_read,-
75 dgram_puts,-
76 NULL, /* dgram_gets, */-
77 dgram_ctrl,-
78 dgram_new,-
79 dgram_free,-
80 NULL, /* dgram_callback_ctrl */-
81};-
82-
83# ifndef OPENSSL_NO_SCTP-
84static const BIO_METHOD methods_dgramp_sctp = {-
85 BIO_TYPE_DGRAM_SCTP,-
86 "datagram sctp socket",-
87 /* TODO: Convert to new style write function */-
88 bwrite_conv,-
89 dgram_sctp_write,-
90 /* TODO: Convert to new style write function */-
91 bread_conv,-
92 dgram_sctp_read,-
93 dgram_sctp_puts,-
94 NULL, /* dgram_gets, */-
95 dgram_sctp_ctrl,-
96 dgram_sctp_new,-
97 dgram_sctp_free,-
98 NULL, /* dgram_callback_ctrl */-
99};-
100# endif-
101-
102typedef struct bio_dgram_data_st {-
103 BIO_ADDR peer;-
104 unsigned int connected;-
105 unsigned int _errno;-
106 unsigned int mtu;-
107 struct timeval next_timeout;-
108 struct timeval socket_timeout;-
109 unsigned int peekmode;-
110} bio_dgram_data;-
111-
112# ifndef OPENSSL_NO_SCTP-
113typedef struct bio_dgram_sctp_save_message_st {-
114 BIO *bio;-
115 char *data;-
116 int length;-
117} bio_dgram_sctp_save_message;-
118-
119typedef struct bio_dgram_sctp_data_st {-
120 BIO_ADDR peer;-
121 unsigned int connected;-
122 unsigned int _errno;-
123 unsigned int mtu;-
124 struct bio_dgram_sctp_sndinfo sndinfo;-
125 struct bio_dgram_sctp_rcvinfo rcvinfo;-
126 struct bio_dgram_sctp_prinfo prinfo;-
127 void (*handle_notifications) (BIO *bio, void *context, void *buf);-
128 void *notification_context;-
129 int in_handshake;-
130 int ccs_rcvd;-
131 int ccs_sent;-
132 int save_shutdown;-
133 int peer_auth_tested;-
134} bio_dgram_sctp_data;-
135# endif-
136-
137const BIO_METHOD *BIO_s_datagram(void)-
138{-
139 return &methods_dgramp;
never executed: return &methods_dgramp;
0
140}-
141-
142BIO *BIO_new_dgram(int fd, int close_flag)-
143{-
144 BIO *ret;-
145-
146 ret = BIO_new(BIO_s_datagram());-
147 if (ret == NULL)
ret == ((void *)0)Description
TRUEnever evaluated
FALSEnever evaluated
0
148 return NULL;
never executed: return ((void *)0) ;
0
149 BIO_set_fd(ret, fd, close_flag);-
150 return ret;
never executed: return ret;
0
151}-
152-
153static int dgram_new(BIO *bi)-
154{-
155 bio_dgram_data *data = OPENSSL_zalloc(sizeof(*data));-
156-
157 if (data == NULL)
data == ((void *)0)Description
TRUEnever evaluated
FALSEnever evaluated
0
158 return 0;
never executed: return 0;
0
159 bi->ptr = data;-
160 return 1;
never executed: return 1;
0
161}-
162-
163static int dgram_free(BIO *a)-
164{-
165 bio_dgram_data *data;-
166-
167 if (a == NULL)
a == ((void *)0)Description
TRUEnever evaluated
FALSEnever evaluated
0
168 return 0;
never executed: return 0;
0
169 if (!dgram_clear(a))
!dgram_clear(a)Description
TRUEnever evaluated
FALSEnever evaluated
0
170 return 0;
never executed: return 0;
0
171-
172 data = (bio_dgram_data *)a->ptr;-
173 OPENSSL_free(data);-
174-
175 return 1;
never executed: return 1;
0
176}-
177-
178static int dgram_clear(BIO *a)-
179{-
180 if (a == NULL)
a == ((void *)0)Description
TRUEnever evaluated
FALSEnever evaluated
0
181 return 0;
never executed: return 0;
0
182 if (a->shutdown) {
a->shutdownDescription
TRUEnever evaluated
FALSEnever evaluated
0
183 if (a->init) {
a->initDescription
TRUEnever evaluated
FALSEnever evaluated
0
184 BIO_closesocket(a->num);-
185 }
never executed: end of block
0
186 a->init = 0;-
187 a->flags = 0;-
188 }
never executed: end of block
0
189 return 1;
never executed: return 1;
0
190}-
191-
192static void dgram_adjust_rcv_timeout(BIO *b)-
193{-
194# if defined(SO_RCVTIMEO)-
195 bio_dgram_data *data = (bio_dgram_data *)b->ptr;-
196 union {-
197 size_t s;-
198 int i;-
199 } sz = {-
200 0-
201 };-
202-
203 /* Is a timer active? */-
204 if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0) {
data->next_timeout.tv_sec > 0Description
TRUEnever evaluated
FALSEnever evaluated
data->next_timeout.tv_usec > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
205 struct timeval timenow, timeleft;-
206-
207 /* Read current socket timeout */-
208# ifdef OPENSSL_SYS_WINDOWS-
209 int timeout;-
210-
211 sz.i = sizeof(timeout);-
212 if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,-
213 (void *)&timeout, &sz.i) < 0) {-
214 perror("getsockopt");-
215 } else {-
216 data->socket_timeout.tv_sec = timeout / 1000;-
217 data->socket_timeout.tv_usec = (timeout % 1000) * 1000;-
218 }-
219# else-
220 sz.i = sizeof(data->socket_timeout);-
221 if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
getsockopt(b->...oid *)&sz) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
222 &(data->socket_timeout), (void *)&sz) < 0) {
getsockopt(b->...oid *)&sz) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
223 perror("getsockopt");-
224 } else if (sizeof(sz.s) != sizeof(sz.i) && sz.i == 0)
never executed: end of block
sizeof(sz.s) != sizeof(sz.i)Description
TRUEnever evaluated
FALSEnever evaluated
sz.i == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
225 OPENSSL_assert(sz.s <= sizeof(data->socket_timeout));
never executed: (void)((sz.s <= sizeof(data->socket_timeout)) ? 0 : (OPENSSL_die("assertion failed: " "sz.s <= sizeof(data->socket_timeout)", __FILE__, 225), 1));
0
226# endif-
227-
228 /* Get current time */-
229 get_current_time(&timenow);-
230-
231 /* Calculate time left until timer expires */-
232 memcpy(&timeleft, &(data->next_timeout), sizeof(struct timeval));-
233 if (timeleft.tv_usec < timenow.tv_usec) {
timeleft.tv_us...imenow.tv_usecDescription
TRUEnever evaluated
FALSEnever evaluated
0
234 timeleft.tv_usec = 1000000 - timenow.tv_usec + timeleft.tv_usec;-
235 timeleft.tv_sec--;-
236 } else {
never executed: end of block
0
237 timeleft.tv_usec -= timenow.tv_usec;-
238 }
never executed: end of block
0
239 if (timeleft.tv_sec < timenow.tv_sec) {
timeleft.tv_se...timenow.tv_secDescription
TRUEnever evaluated
FALSEnever evaluated
0
240 timeleft.tv_sec = 0;-
241 timeleft.tv_usec = 1;-
242 } else {
never executed: end of block
0
243 timeleft.tv_sec -= timenow.tv_sec;-
244 }
never executed: end of block
0
245-
246 /*-
247 * Adjust socket timeout if next handshake message timer will expire-
248 * earlier.-
249 */-
250 if ((data->socket_timeout.tv_sec == 0
data->socket_t...ut.tv_sec == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
251 && data->socket_timeout.tv_usec == 0)
data->socket_t...t.tv_usec == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
252 || (data->socket_timeout.tv_sec > timeleft.tv_sec)
(data->socket_...meleft.tv_sec)Description
TRUEnever evaluated
FALSEnever evaluated
0
253 || (data->socket_timeout.tv_sec == timeleft.tv_sec
data->socket_t...imeleft.tv_secDescription
TRUEnever evaluated
FALSEnever evaluated
0
254 && data->socket_timeout.tv_usec >= timeleft.tv_usec)) {
data->socket_t...meleft.tv_usecDescription
TRUEnever evaluated
FALSEnever evaluated
0
255# ifdef OPENSSL_SYS_WINDOWS-
256 timeout = timeleft.tv_sec * 1000 + timeleft.tv_usec / 1000;-
257 if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,-
258 (void *)&timeout, sizeof(timeout)) < 0) {-
259 perror("setsockopt");-
260 }-
261# else-
262 if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, &timeleft,
setsockopt(b->... timeval)) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
263 sizeof(struct timeval)) < 0) {
setsockopt(b->... timeval)) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
264 perror("setsockopt");-
265 }
never executed: end of block
0
266# endif-
267 }
never executed: end of block
0
268 }
never executed: end of block
0
269# endif-
270}
never executed: end of block
0
271-
272static void dgram_reset_rcv_timeout(BIO *b)-
273{-
274# if defined(SO_RCVTIMEO)-
275 bio_dgram_data *data = (bio_dgram_data *)b->ptr;-
276-
277 /* Is a timer active? */-
278 if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0) {
data->next_timeout.tv_sec > 0Description
TRUEnever evaluated
FALSEnever evaluated
data->next_timeout.tv_usec > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
279# ifdef OPENSSL_SYS_WINDOWS-
280 int timeout = data->socket_timeout.tv_sec * 1000 +-
281 data->socket_timeout.tv_usec / 1000;-
282 if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,-
283 (void *)&timeout, sizeof(timeout)) < 0) {-
284 perror("setsockopt");-
285 }-
286# else-
287 if (setsockopt
setsockopt (b-... timeval)) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
288 (b->num, SOL_SOCKET, SO_RCVTIMEO, &(data->socket_timeout),
setsockopt (b-... timeval)) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
289 sizeof(struct timeval)) < 0) {
setsockopt (b-... timeval)) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
290 perror("setsockopt");-
291 }
never executed: end of block
0
292# endif-
293 }
never executed: end of block
0
294# endif-
295}
never executed: end of block
0
296-
297static int dgram_read(BIO *b, char *out, int outl)-
298{-
299 int ret = 0;-
300 bio_dgram_data *data = (bio_dgram_data *)b->ptr;-
301 int flags = 0;-
302-
303 BIO_ADDR peer;-
304 socklen_t len = sizeof(peer);-
305-
306 if (out != NULL) {
out != ((void *)0)Description
TRUEnever evaluated
FALSEnever evaluated
0
307 clear_socket_error();-
308 memset(&peer, 0, sizeof(peer));-
309 dgram_adjust_rcv_timeout(b);-
310 if (data->peekmode)
data->peekmodeDescription
TRUEnever evaluated
FALSEnever evaluated
0
311 flags = MSG_PEEK;
never executed: flags = MSG_PEEK ;
0
312 ret = recvfrom(b->num, out, outl, flags,-
313 BIO_ADDR_sockaddr_noconst(&peer), &len);-
314-
315 if (!data->connected && ret >= 0)
!data->connectedDescription
TRUEnever evaluated
FALSEnever evaluated
ret >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
316 BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, &peer);
never executed: BIO_ctrl(b, 44, 0, &peer);
0
317-
318 BIO_clear_retry_flags(b);-
319 if (ret < 0) {
ret < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
320 if (BIO_dgram_should_retry(ret)) {
BIO_dgram_should_retry(ret)Description
TRUEnever evaluated
FALSEnever evaluated
0
321 BIO_set_retry_read(b);-
322 data->_errno = get_last_socket_error();-
323 }
never executed: end of block
0
324 }
never executed: end of block
0
325-
326 dgram_reset_rcv_timeout(b);-
327 }
never executed: end of block
0
328 return ret;
never executed: return ret;
0
329}-
330-
331static int dgram_write(BIO *b, const char *in, int inl)-
332{-
333 int ret;-
334 bio_dgram_data *data = (bio_dgram_data *)b->ptr;-
335 clear_socket_error();-
336-
337 if (data->connected)
data->connectedDescription
TRUEnever evaluated
FALSEnever evaluated
0
338 ret = writesocket(b->num, in, inl);
never executed: ret = write((b->num),(in),(inl));
0
339 else {-
340 int peerlen = BIO_ADDR_sockaddr_size(&data->peer);-
341-
342 ret = sendto(b->num, in, inl, 0,-
343 BIO_ADDR_sockaddr(&data->peer), peerlen);-
344 }
never executed: end of block
0
345-
346 BIO_clear_retry_flags(b);-
347 if (ret <= 0) {
ret <= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
348 if (BIO_dgram_should_retry(ret)) {
BIO_dgram_should_retry(ret)Description
TRUEnever evaluated
FALSEnever evaluated
0
349 BIO_set_retry_write(b);-
350 data->_errno = get_last_socket_error();-
351 }
never executed: end of block
0
352 }
never executed: end of block
0
353 return ret;
never executed: return ret;
0
354}-
355-
356static long dgram_get_mtu_overhead(bio_dgram_data *data)-
357{-
358 long ret;-
359-
360 switch (BIO_ADDR_family(&data->peer)) {-
361 case AF_INET:
never executed: case 2 :
0
362 /*-
363 * Assume this is UDP - 20 bytes for IP, 8 bytes for UDP-
364 */-
365 ret = 28;-
366 break;
never executed: break;
0
367# if OPENSSL_USE_IPV6-
368 case AF_INET6:
never executed: case 10 :
0
369 {-
370# ifdef IN6_IS_ADDR_V4MAPPED-
371 struct in6_addr tmp_addr;-
372 if (BIO_ADDR_rawaddress(&data->peer, &tmp_addr, NULL)
BIO_ADDR_rawad... ((void *)0) )Description
TRUEnever evaluated
FALSEnever evaluated
0
373 && IN6_IS_ADDR_V4MAPPED(&tmp_addr))
(__extension__... (0xffff); }))Description
TRUEnever evaluated
FALSEnever evaluated
0
374 /*-
375 * Assume this is UDP - 20 bytes for IP, 8 bytes for UDP-
376 */-
377 ret = 28;
never executed: ret = 28;
0
378 else-
379# endif-
380 /*-
381 * Assume this is UDP - 40 bytes for IP, 8 bytes for UDP-
382 */-
383 ret = 48;
never executed: ret = 48;
0
384 }-
385 break;
never executed: break;
0
386# endif-
387 default:
never executed: default:
0
388 /* We don't know. Go with the historical default */-
389 ret = 28;-
390 break;
never executed: break;
0
391 }-
392 return ret;
never executed: return ret;
0
393}-
394-
395static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)-
396{-
397 long ret = 1;-
398 int *ip;-
399 bio_dgram_data *data = NULL;-
400 int sockopt_val = 0;-
401 int d_errno;-
402# if defined(OPENSSL_SYS_LINUX) && (defined(IP_MTU_DISCOVER) || defined(IP_MTU))-
403 socklen_t sockopt_len; /* assume that system supporting IP_MTU is-
404 * modern enough to define socklen_t */-
405 socklen_t addr_len;-
406 BIO_ADDR addr;-
407# endif-
408-
409 data = (bio_dgram_data *)b->ptr;-
410-
411 switch (cmd) {-
412 case BIO_CTRL_RESET:
never executed: case 1:
0
413 num = 0;-
414 ret = 0;-
415 break;
never executed: break;
0
416 case BIO_CTRL_INFO:
never executed: case 3:
0
417 ret = 0;-
418 break;
never executed: break;
0
419 case BIO_C_SET_FD:
never executed: case 104:
0
420 dgram_clear(b);-
421 b->num = *((int *)ptr);-
422 b->shutdown = (int)num;-
423 b->init = 1;-
424 break;
never executed: break;
0
425 case BIO_C_GET_FD:
never executed: case 105:
0
426 if (b->init) {
b->initDescription
TRUEnever evaluated
FALSEnever evaluated
0
427 ip = (int *)ptr;-
428 if (ip != NULL)
ip != ((void *)0)Description
TRUEnever evaluated
FALSEnever evaluated
0
429 *ip = b->num;
never executed: *ip = b->num;
0
430 ret = b->num;-
431 } else
never executed: end of block
0
432 ret = -1;
never executed: ret = -1;
0
433 break;
never executed: break;
0
434 case BIO_CTRL_GET_CLOSE:
never executed: case 8:
0
435 ret = b->shutdown;-
436 break;
never executed: break;
0
437 case BIO_CTRL_SET_CLOSE:
never executed: case 9:
0
438 b->shutdown = (int)num;-
439 break;
never executed: break;
0
440 case BIO_CTRL_PENDING:
never executed: case 10:
0
441 case BIO_CTRL_WPENDING:
never executed: case 13:
0
442 ret = 0;-
443 break;
never executed: break;
0
444 case BIO_CTRL_DUP:
never executed: case 12:
0
445 case BIO_CTRL_FLUSH:
never executed: case 11:
0
446 ret = 1;-
447 break;
never executed: break;
0
448 case BIO_CTRL_DGRAM_CONNECT:
never executed: case 31:
0
449 BIO_ADDR_make(&data->peer, BIO_ADDR_sockaddr((BIO_ADDR *)ptr));-
450 break;
never executed: break;
0
451 /* (Linux)kernel sets DF bit on outgoing IP packets */-
452 case BIO_CTRL_DGRAM_MTU_DISCOVER:
never executed: case 39:
0
453# if defined(OPENSSL_SYS_LINUX) && defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO)-
454 addr_len = (socklen_t) sizeof(addr);-
455 memset(&addr, 0, sizeof(addr));-
456 if (getsockname(b->num, &addr.sa, &addr_len) < 0) {
getsockname(b-...&addr_len) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
457 ret = 0;-
458 break;
never executed: break;
0
459 }-
460 switch (addr.sa.sa_family) {-
461 case AF_INET:
never executed: case 2 :
0
462 sockopt_val = IP_PMTUDISC_DO;-
463 if ((ret = setsockopt(b->num, IPPROTO_IP, IP_MTU_DISCOVER,
(ret = setsock...opt_val))) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
464 &sockopt_val, sizeof(sockopt_val))) < 0)
(ret = setsock...opt_val))) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
465 perror("setsockopt");
never executed: perror("setsockopt");
0
466 break;
never executed: break;
0
467# if OPENSSL_USE_IPV6 && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO)-
468 case AF_INET6:
never executed: case 10 :
0
469 sockopt_val = IPV6_PMTUDISC_DO;-
470 if ((ret = setsockopt(b->num, IPPROTO_IPV6, IPV6_MTU_DISCOVER,
(ret = setsock...opt_val))) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
471 &sockopt_val, sizeof(sockopt_val))) < 0)
(ret = setsock...opt_val))) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
472 perror("setsockopt");
never executed: perror("setsockopt");
0
473 break;
never executed: break;
0
474# endif-
475 default:
never executed: default:
0
476 ret = -1;-
477 break;
never executed: break;
0
478 }-
479# else-
480 ret = -1;-
481# endif-
482 break;
never executed: break;
0
483 case BIO_CTRL_DGRAM_QUERY_MTU:
never executed: case 40:
0
484# if defined(OPENSSL_SYS_LINUX) && defined(IP_MTU)-
485 addr_len = (socklen_t) sizeof(addr);-
486 memset(&addr, 0, sizeof(addr));-
487 if (getsockname(b->num, &addr.sa, &addr_len) < 0) {
getsockname(b-...&addr_len) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
488 ret = 0;-
489 break;
never executed: break;
0
490 }-
491 sockopt_len = sizeof(sockopt_val);-
492 switch (addr.sa.sa_family) {-
493 case AF_INET:
never executed: case 2 :
0
494 if ((ret =
(ret = getsock...kopt_len)) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
495 getsockopt(b->num, IPPROTO_IP, IP_MTU, (void *)&sockopt_val,
(ret = getsock...kopt_len)) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
496 &sockopt_len)) < 0 || sockopt_val < 0) {
(ret = getsock...kopt_len)) < 0Description
TRUEnever evaluated
FALSEnever evaluated
sockopt_val < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
497 ret = 0;-
498 } else {
never executed: end of block
0
499 /*-
500 * we assume that the transport protocol is UDP and no IP-
501 * options are used.-
502 */-
503 data->mtu = sockopt_val - 8 - 20;-
504 ret = data->mtu;-
505 }
never executed: end of block
0
506 break;
never executed: break;
0
507# if OPENSSL_USE_IPV6 && defined(IPV6_MTU)-
508 case AF_INET6:
never executed: case 10 :
0
509 if ((ret =
(ret = getsock...kopt_len)) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
510 getsockopt(b->num, IPPROTO_IPV6, IPV6_MTU,
(ret = getsock...kopt_len)) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
511 (void *)&sockopt_val, &sockopt_len)) < 0
(ret = getsock...kopt_len)) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
512 || sockopt_val < 0) {
sockopt_val < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
513 ret = 0;-
514 } else {
never executed: end of block
0
515 /*-
516 * we assume that the transport protocol is UDP and no IPV6-
517 * options are used.-
518 */-
519 data->mtu = sockopt_val - 8 - 40;-
520 ret = data->mtu;-
521 }
never executed: end of block
0
522 break;
never executed: break;
0
523# endif-
524 default:
never executed: default:
0
525 ret = 0;-
526 break;
never executed: break;
0
527 }-
528# else-
529 ret = 0;-
530# endif-
531 break;
never executed: break;
0
532 case BIO_CTRL_DGRAM_GET_FALLBACK_MTU:
never executed: case 47:
0
533 ret = -dgram_get_mtu_overhead(data);-
534 switch (BIO_ADDR_family(&data->peer)) {-
535 case AF_INET:
never executed: case 2 :
0
536 ret += 576;-
537 break;
never executed: break;
0
538# if OPENSSL_USE_IPV6-
539 case AF_INET6:
never executed: case 10 :
0
540 {-
541# ifdef IN6_IS_ADDR_V4MAPPED-
542 struct in6_addr tmp_addr;-
543 if (BIO_ADDR_rawaddress(&data->peer, &tmp_addr, NULL)
BIO_ADDR_rawad... ((void *)0) )Description
TRUEnever evaluated
FALSEnever evaluated
0
544 && IN6_IS_ADDR_V4MAPPED(&tmp_addr))
(__extension__... (0xffff); }))Description
TRUEnever evaluated
FALSEnever evaluated
0
545 ret += 576;
never executed: ret += 576;
0
546 else-
547# endif-
548 ret += 1280;
never executed: ret += 1280;
0
549 }-
550 break;
never executed: break;
0
551# endif-
552 default:
never executed: default:
0
553 ret += 576;-
554 break;
never executed: break;
0
555 }-
556 break;
never executed: break;
0
557 case BIO_CTRL_DGRAM_GET_MTU:
never executed: case 41:
0
558 return data->mtu;
never executed: return data->mtu;
0
559 case BIO_CTRL_DGRAM_SET_MTU:
never executed: case 42:
0
560 data->mtu = num;-
561 ret = num;-
562 break;
never executed: break;
0
563 case BIO_CTRL_DGRAM_SET_CONNECTED:
never executed: case 32:
0
564 if (ptr != NULL) {
ptr != ((void *)0)Description
TRUEnever evaluated
FALSEnever evaluated
0
565 data->connected = 1;-
566 BIO_ADDR_make(&data->peer, BIO_ADDR_sockaddr((BIO_ADDR *)ptr));-
567 } else {
never executed: end of block
0
568 data->connected = 0;-
569 memset(&data->peer, 0, sizeof(data->peer));-
570 }
never executed: end of block
0
571 break;
never executed: break;
0
572 case BIO_CTRL_DGRAM_GET_PEER:
never executed: case 46:
0
573 ret = BIO_ADDR_sockaddr_size(&data->peer);-
574 /* FIXME: if num < ret, we will only return part of an address.-
575 That should bee an error, no? */-
576 if (num == 0 || num > ret)
num == 0Description
TRUEnever evaluated
FALSEnever evaluated
num > retDescription
TRUEnever evaluated
FALSEnever evaluated
0
577 num = ret;
never executed: num = ret;
0
578 memcpy(ptr, &data->peer, (ret = num));-
579 break;
never executed: break;
0
580 case BIO_CTRL_DGRAM_SET_PEER:
never executed: case 44:
0
581 BIO_ADDR_make(&data->peer, BIO_ADDR_sockaddr((BIO_ADDR *)ptr));-
582 break;
never executed: break;
0
583 case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
never executed: case 45:
0
584 memcpy(&(data->next_timeout), ptr, sizeof(struct timeval));-
585 break;
never executed: break;
0
586# if defined(SO_RCVTIMEO)-
587 case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT:
never executed: case 33:
0
588# ifdef OPENSSL_SYS_WINDOWS-
589 {-
590 struct timeval *tv = (struct timeval *)ptr;-
591 int timeout = tv->tv_sec * 1000 + tv->tv_usec / 1000;-
592 if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,-
593 (void *)&timeout, sizeof(timeout)) < 0) {-
594 perror("setsockopt");-
595 ret = -1;-
596 }-
597 }-
598# else-
599 if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, ptr,
setsockopt(b->... timeval)) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
600 sizeof(struct timeval)) < 0) {
setsockopt(b->... timeval)) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
601 perror("setsockopt");-
602 ret = -1;-
603 }
never executed: end of block
0
604# endif-
605 break;
never executed: break;
0
606 case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT:
never executed: case 34:
0
607 {-
608 union {-
609 size_t s;-
610 int i;-
611 } sz = {-
612 0-
613 };-
614# ifdef OPENSSL_SYS_WINDOWS-
615 int timeout;-
616 struct timeval *tv = (struct timeval *)ptr;-
617-
618 sz.i = sizeof(timeout);-
619 if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,-
620 (void *)&timeout, &sz.i) < 0) {-
621 perror("getsockopt");-
622 ret = -1;-
623 } else {-
624 tv->tv_sec = timeout / 1000;-
625 tv->tv_usec = (timeout % 1000) * 1000;-
626 ret = sizeof(*tv);-
627 }-
628# else-
629 sz.i = sizeof(struct timeval);-
630 if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
getsockopt(b->...oid *)&sz) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
631 ptr, (void *)&sz) < 0) {
getsockopt(b->...oid *)&sz) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
632 perror("getsockopt");-
633 ret = -1;-
634 } else if (sizeof(sz.s) != sizeof(sz.i) && sz.i == 0) {
never executed: end of block
sizeof(sz.s) != sizeof(sz.i)Description
TRUEnever evaluated
FALSEnever evaluated
sz.i == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
635 OPENSSL_assert(sz.s <= sizeof(struct timeval));-
636 ret = (int)sz.s;-
637 } else
never executed: end of block
0
638 ret = sz.i;
never executed: ret = sz.i;
0
639# endif-
640 }-
641 break;
never executed: break;
0
642# endif-
643# if defined(SO_SNDTIMEO)-
644 case BIO_CTRL_DGRAM_SET_SEND_TIMEOUT:
never executed: case 35:
0
645# ifdef OPENSSL_SYS_WINDOWS-
646 {-
647 struct timeval *tv = (struct timeval *)ptr;-
648 int timeout = tv->tv_sec * 1000 + tv->tv_usec / 1000;-
649 if (setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO,-
650 (void *)&timeout, sizeof(timeout)) < 0) {-
651 perror("setsockopt");-
652 ret = -1;-
653 }-
654 }-
655# else-
656 if (setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, ptr,
setsockopt(b->... timeval)) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
657 sizeof(struct timeval)) < 0) {
setsockopt(b->... timeval)) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
658 perror("setsockopt");-
659 ret = -1;-
660 }
never executed: end of block
0
661# endif-
662 break;
never executed: break;
0
663 case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT:
never executed: case 36:
0
664 {-
665 union {-
666 size_t s;-
667 int i;-
668 } sz = {-
669 0-
670 };-
671# ifdef OPENSSL_SYS_WINDOWS-
672 int timeout;-
673 struct timeval *tv = (struct timeval *)ptr;-
674-
675 sz.i = sizeof(timeout);-
676 if (getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO,-
677 (void *)&timeout, &sz.i) < 0) {-
678 perror("getsockopt");-
679 ret = -1;-
680 } else {-
681 tv->tv_sec = timeout / 1000;-
682 tv->tv_usec = (timeout % 1000) * 1000;-
683 ret = sizeof(*tv);-
684 }-
685# else-
686 sz.i = sizeof(struct timeval);-
687 if (getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO,
getsockopt(b->...oid *)&sz) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
688 ptr, (void *)&sz) < 0) {
getsockopt(b->...oid *)&sz) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
689 perror("getsockopt");-
690 ret = -1;-
691 } else if (sizeof(sz.s) != sizeof(sz.i) && sz.i == 0) {
never executed: end of block
sizeof(sz.s) != sizeof(sz.i)Description
TRUEnever evaluated
FALSEnever evaluated
sz.i == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
692 OPENSSL_assert(sz.s <= sizeof(struct timeval));-
693 ret = (int)sz.s;-
694 } else
never executed: end of block
0
695 ret = sz.i;
never executed: ret = sz.i;
0
696# endif-
697 }-
698 break;
never executed: break;
0
699# endif-
700 case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP:
never executed: case 38:
0
701 /* fall-through */-
702 case BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP:
never executed: case 37:
0
703# ifdef OPENSSL_SYS_WINDOWS-
704 d_errno = (data->_errno == WSAETIMEDOUT);-
705# else-
706 d_errno = (data->_errno == EAGAIN);-
707# endif-
708 if (d_errno) {
d_errnoDescription
TRUEnever evaluated
FALSEnever evaluated
0
709 ret = 1;-
710 data->_errno = 0;-
711 } else
never executed: end of block
0
712 ret = 0;
never executed: ret = 0;
0
713 break;
never executed: break;
0
714# ifdef EMSGSIZE-
715 case BIO_CTRL_DGRAM_MTU_EXCEEDED:
never executed: case 43:
0
716 if (data->_errno == EMSGSIZE) {
data->_errno == 90Description
TRUEnever evaluated
FALSEnever evaluated
0
717 ret = 1;-
718 data->_errno = 0;-
719 } else
never executed: end of block
0
720 ret = 0;
never executed: ret = 0;
0
721 break;
never executed: break;
0
722# endif-
723 case BIO_CTRL_DGRAM_SET_DONT_FRAG:
never executed: case 48:
0
724 sockopt_val = num ? 1 : 0;
numDescription
TRUEnever evaluated
FALSEnever evaluated
0
725-
726 switch (data->peer.sa.sa_family) {-
727 case AF_INET:
never executed: case 2 :
0
728# if defined(IP_DONTFRAG)-
729 if ((ret = setsockopt(b->num, IPPROTO_IP, IP_DONTFRAG,-
730 &sockopt_val, sizeof(sockopt_val))) < 0) {-
731 perror("setsockopt");-
732 ret = -1;-
733 }-
734# elif defined(OPENSSL_SYS_LINUX) && defined(IP_MTU_DISCOVER) && defined (IP_PMTUDISC_PROBE)-
735 if ((sockopt_val = num ? IP_PMTUDISC_PROBE : IP_PMTUDISC_DONT),
(sockopt_val =...opt_val))) < 0Description
TRUEnever evaluated
FALSEnever evaluated
numDescription
TRUEnever evaluated
FALSEnever evaluated
0
736 (ret = setsockopt(b->num, IPPROTO_IP, IP_MTU_DISCOVER,
(sockopt_val =...opt_val))) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
737 &sockopt_val, sizeof(sockopt_val))) < 0) {
(sockopt_val =...opt_val))) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
738 perror("setsockopt");-
739 ret = -1;-
740 }
never executed: end of block
0
741# elif defined(OPENSSL_SYS_WINDOWS) && defined(IP_DONTFRAGMENT)-
742 if ((ret = setsockopt(b->num, IPPROTO_IP, IP_DONTFRAGMENT,-
743 (const char *)&sockopt_val,-
744 sizeof(sockopt_val))) < 0) {-
745 perror("setsockopt");-
746 ret = -1;-
747 }-
748# else-
749 ret = -1;-
750# endif-
751 break;
never executed: break;
0
752# if OPENSSL_USE_IPV6-
753 case AF_INET6:
never executed: case 10 :
0
754# if defined(IPV6_DONTFRAG)-
755 if ((ret = setsockopt(b->num, IPPROTO_IPV6, IPV6_DONTFRAG,
(ret = setsock...opt_val))) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
756 (const void *)&sockopt_val,
(ret = setsock...opt_val))) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
757 sizeof(sockopt_val))) < 0) {
(ret = setsock...opt_val))) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
758 perror("setsockopt");-
759 ret = -1;-
760 }
never executed: end of block
0
761# elif defined(OPENSSL_SYS_LINUX) && defined(IPV6_MTUDISCOVER)-
762 if ((sockopt_val = num ? IP_PMTUDISC_PROBE : IP_PMTUDISC_DONT),-
763 (ret = setsockopt(b->num, IPPROTO_IPV6, IPV6_MTU_DISCOVER,-
764 &sockopt_val, sizeof(sockopt_val))) < 0) {-
765 perror("setsockopt");-
766 ret = -1;-
767 }-
768# else-
769 ret = -1;-
770# endif-
771 break;
never executed: break;
0
772# endif-
773 default:
never executed: default:
0
774 ret = -1;-
775 break;
never executed: break;
0
776 }-
777 break;
never executed: break;
0
778 case BIO_CTRL_DGRAM_GET_MTU_OVERHEAD:
never executed: case 49:
0
779 ret = dgram_get_mtu_overhead(data);-
780 break;
never executed: break;
0
781-
782 /*-
783 * BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE is used here for compatibility-
784 * reasons. When BIO_CTRL_DGRAM_SET_PEEK_MODE was first defined its value-
785 * was incorrectly clashing with BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE. The-
786 * value has been updated to a non-clashing value. However to preserve-
787 * binary compatiblity we now respond to both the old value and the new one-
788 */-
789 case BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE:
never executed: case 50:
0
790 case BIO_CTRL_DGRAM_SET_PEEK_MODE:
never executed: case 71:
0
791 data->peekmode = (unsigned int)num;-
792 break;
never executed: break;
0
793 default:
never executed: default:
0
794 ret = 0;-
795 break;
never executed: break;
0
796 }-
797 return ret;
never executed: return ret;
0
798}-
799-
800static int dgram_puts(BIO *bp, const char *str)-
801{-
802 int n, ret;-
803-
804 n = strlen(str);-
805 ret = dgram_write(bp, str, n);-
806 return ret;
never executed: return ret;
0
807}-
808-
809# ifndef OPENSSL_NO_SCTP-
810const BIO_METHOD *BIO_s_datagram_sctp(void)-
811{-
812 return &methods_dgramp_sctp;-
813}-
814-
815BIO *BIO_new_dgram_sctp(int fd, int close_flag)-
816{-
817 BIO *bio;-
818 int ret, optval = 20000;-
819 int auth_data = 0, auth_forward = 0;-
820 unsigned char *p;-
821 struct sctp_authchunk auth;-
822 struct sctp_authchunks *authchunks;-
823 socklen_t sockopt_len;-
824# ifdef SCTP_AUTHENTICATION_EVENT-
825# ifdef SCTP_EVENT-
826 struct sctp_event event;-
827# else-
828 struct sctp_event_subscribe event;-
829# endif-
830# endif-
831-
832 bio = BIO_new(BIO_s_datagram_sctp());-
833 if (bio == NULL)-
834 return NULL;-
835 BIO_set_fd(bio, fd, close_flag);-
836-
837 /* Activate SCTP-AUTH for DATA and FORWARD-TSN chunks */-
838 auth.sauth_chunk = OPENSSL_SCTP_DATA_CHUNK_TYPE;-
839 ret =-
840 setsockopt(fd, IPPROTO_SCTP, SCTP_AUTH_CHUNK, &auth,-
841 sizeof(struct sctp_authchunk));-
842 if (ret < 0) {-
843 BIO_vfree(bio);-
844 BIOerr(BIO_F_BIO_NEW_DGRAM_SCTP, ERR_R_SYS_LIB);-
845 ERR_add_error_data(1, "Ensure SCTP AUTH chunks are enabled in kernel");-
846 return NULL;-
847 }-
848 auth.sauth_chunk = OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE;-
849 ret =-
850 setsockopt(fd, IPPROTO_SCTP, SCTP_AUTH_CHUNK, &auth,-
851 sizeof(struct sctp_authchunk));-
852 if (ret < 0) {-
853 BIO_vfree(bio);-
854 BIOerr(BIO_F_BIO_NEW_DGRAM_SCTP, ERR_R_SYS_LIB);-
855 ERR_add_error_data(1, "Ensure SCTP AUTH chunks are enabled in kernel");-
856 return NULL;-
857 }-
858-
859 /*-
860 * Test if activation was successful. When using accept(), SCTP-AUTH has-
861 * to be activated for the listening socket already, otherwise the-
862 * connected socket won't use it. Similarly with connect(): the socket-
863 * prior to connection must be activated for SCTP-AUTH-
864 */-
865 sockopt_len = (socklen_t) (sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t));-
866 authchunks = OPENSSL_zalloc(sockopt_len);-
867 if (authchunks == NULL) {-
868 BIO_vfree(bio);-
869 return NULL;-
870 }-
871 ret = getsockopt(fd, IPPROTO_SCTP, SCTP_LOCAL_AUTH_CHUNKS, authchunks,-
872 &sockopt_len);-
873 if (ret < 0) {-
874 OPENSSL_free(authchunks);-
875 BIO_vfree(bio);-
876 return NULL;-
877 }-
878-
879 for (p = (unsigned char *)authchunks->gauth_chunks;-
880 p < (unsigned char *)authchunks + sockopt_len;-
881 p += sizeof(uint8_t)) {-
882 if (*p == OPENSSL_SCTP_DATA_CHUNK_TYPE)-
883 auth_data = 1;-
884 if (*p == OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE)-
885 auth_forward = 1;-
886 }-
887-
888 OPENSSL_free(authchunks);-
889-
890 if (!auth_data || !auth_forward) {-
891 BIO_vfree(bio);-
892 BIOerr(BIO_F_BIO_NEW_DGRAM_SCTP, ERR_R_SYS_LIB);-
893 ERR_add_error_data(1,-
894 "Ensure SCTP AUTH chunks are enabled on the "-
895 "underlying socket");-
896 return NULL;-
897 }-
898-
899# ifdef SCTP_AUTHENTICATION_EVENT-
900# ifdef SCTP_EVENT-
901 memset(&event, 0, sizeof(event));-
902 event.se_assoc_id = 0;-
903 event.se_type = SCTP_AUTHENTICATION_EVENT;-
904 event.se_on = 1;-
905 ret =-
906 setsockopt(fd, IPPROTO_SCTP, SCTP_EVENT, &event,-
907 sizeof(struct sctp_event));-
908 if (ret < 0) {-
909 BIO_vfree(bio);-
910 return NULL;-
911 }-
912# else-
913 sockopt_len = (socklen_t) sizeof(struct sctp_event_subscribe);-
914 ret = getsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, &sockopt_len);-
915 if (ret < 0) {-
916 BIO_vfree(bio);-
917 return NULL;-
918 }-
919-
920 event.sctp_authentication_event = 1;-
921-
922 ret =-
923 setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event,-
924 sizeof(struct sctp_event_subscribe));-
925 if (ret < 0) {-
926 BIO_vfree(bio);-
927 return NULL;-
928 }-
929# endif-
930# endif-
931-
932 /*-
933 * Disable partial delivery by setting the min size larger than the max-
934 * record size of 2^14 + 2048 + 13-
935 */-
936 ret =-
937 setsockopt(fd, IPPROTO_SCTP, SCTP_PARTIAL_DELIVERY_POINT, &optval,-
938 sizeof(optval));-
939 if (ret < 0) {-
940 BIO_vfree(bio);-
941 return NULL;-
942 }-
943-
944 return bio;-
945}-
946-
947int BIO_dgram_is_sctp(BIO *bio)-
948{-
949 return (BIO_method_type(bio) == BIO_TYPE_DGRAM_SCTP);-
950}-
951-
952static int dgram_sctp_new(BIO *bi)-
953{-
954 bio_dgram_sctp_data *data = NULL;-
955-
956 bi->init = 0;-
957 bi->num = 0;-
958 if ((data = OPENSSL_zalloc(sizeof(*data))) == NULL) {-
959 BIOerr(BIO_F_DGRAM_SCTP_NEW, ERR_R_MALLOC_FAILURE);-
960 return 0;-
961 }-
962# ifdef SCTP_PR_SCTP_NONE-
963 data->prinfo.pr_policy = SCTP_PR_SCTP_NONE;-
964# endif-
965 bi->ptr = data;-
966-
967 bi->flags = 0;-
968 return 1;-
969}-
970-
971static int dgram_sctp_free(BIO *a)-
972{-
973 bio_dgram_sctp_data *data;-
974-
975 if (a == NULL)-
976 return 0;-
977 if (!dgram_clear(a))-
978 return 0;-
979-
980 data = (bio_dgram_sctp_data *) a->ptr;-
981 if (data != NULL)-
982 OPENSSL_free(data);-
983-
984 return 1;-
985}-
986-
987# ifdef SCTP_AUTHENTICATION_EVENT-
988void dgram_sctp_handle_auth_free_key_event(BIO *b,-
989 union sctp_notification *snp)-
990{-
991 int ret;-
992 struct sctp_authkey_event *authkeyevent = &snp->sn_auth_event;-
993-
994 if (authkeyevent->auth_indication == SCTP_AUTH_FREE_KEY) {-
995 struct sctp_authkeyid authkeyid;-
996-
997 /* delete key */-
998 authkeyid.scact_keynumber = authkeyevent->auth_keynumber;-
999 ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_DELETE_KEY,-
1000 &authkeyid, sizeof(struct sctp_authkeyid));-
1001 }-
1002}-
1003# endif-
1004-
1005static int dgram_sctp_read(BIO *b, char *out, int outl)-
1006{-
1007 int ret = 0, n = 0, i, optval;-
1008 socklen_t optlen;-
1009 bio_dgram_sctp_data *data = (bio_dgram_sctp_data *) b->ptr;-
1010 union sctp_notification *snp;-
1011 struct msghdr msg;-
1012 struct iovec iov;-
1013 struct cmsghdr *cmsg;-
1014 char cmsgbuf[512];-
1015-
1016 if (out != NULL) {-
1017 clear_socket_error();-
1018-
1019 do {-
1020 memset(&data->rcvinfo, 0, sizeof(data->rcvinfo));-
1021 iov.iov_base = out;-
1022 iov.iov_len = outl;-
1023 msg.msg_name = NULL;-
1024 msg.msg_namelen = 0;-
1025 msg.msg_iov = &iov;-
1026 msg.msg_iovlen = 1;-
1027 msg.msg_control = cmsgbuf;-
1028 msg.msg_controllen = 512;-
1029 msg.msg_flags = 0;-
1030 n = recvmsg(b->num, &msg, 0);-
1031-
1032 if (n <= 0) {-
1033 if (n < 0)-
1034 ret = n;-
1035 break;-
1036 }-
1037-
1038 if (msg.msg_controllen > 0) {-
1039 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg;-
1040 cmsg = CMSG_NXTHDR(&msg, cmsg)) {-
1041 if (cmsg->cmsg_level != IPPROTO_SCTP)-
1042 continue;-
1043# ifdef SCTP_RCVINFO-
1044 if (cmsg->cmsg_type == SCTP_RCVINFO) {-
1045 struct sctp_rcvinfo *rcvinfo;-
1046-
1047 rcvinfo = (struct sctp_rcvinfo *)CMSG_DATA(cmsg);-
1048 data->rcvinfo.rcv_sid = rcvinfo->rcv_sid;-
1049 data->rcvinfo.rcv_ssn = rcvinfo->rcv_ssn;-
1050 data->rcvinfo.rcv_flags = rcvinfo->rcv_flags;-
1051 data->rcvinfo.rcv_ppid = rcvinfo->rcv_ppid;-
1052 data->rcvinfo.rcv_tsn = rcvinfo->rcv_tsn;-
1053 data->rcvinfo.rcv_cumtsn = rcvinfo->rcv_cumtsn;-
1054 data->rcvinfo.rcv_context = rcvinfo->rcv_context;-
1055 }-
1056# endif-
1057# ifdef SCTP_SNDRCV-
1058 if (cmsg->cmsg_type == SCTP_SNDRCV) {-
1059 struct sctp_sndrcvinfo *sndrcvinfo;-
1060-
1061 sndrcvinfo =-
1062 (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);-
1063 data->rcvinfo.rcv_sid = sndrcvinfo->sinfo_stream;-
1064 data->rcvinfo.rcv_ssn = sndrcvinfo->sinfo_ssn;-
1065 data->rcvinfo.rcv_flags = sndrcvinfo->sinfo_flags;-
1066 data->rcvinfo.rcv_ppid = sndrcvinfo->sinfo_ppid;-
1067 data->rcvinfo.rcv_tsn = sndrcvinfo->sinfo_tsn;-
1068 data->rcvinfo.rcv_cumtsn = sndrcvinfo->sinfo_cumtsn;-
1069 data->rcvinfo.rcv_context = sndrcvinfo->sinfo_context;-
1070 }-
1071# endif-
1072 }-
1073 }-
1074-
1075 if (msg.msg_flags & MSG_NOTIFICATION) {-
1076 snp = (union sctp_notification *)out;-
1077 if (snp->sn_header.sn_type == SCTP_SENDER_DRY_EVENT) {-
1078# ifdef SCTP_EVENT-
1079 struct sctp_event event;-
1080# else-
1081 struct sctp_event_subscribe event;-
1082 socklen_t eventsize;-
1083# endif-
1084-
1085 /* disable sender dry event */-
1086# ifdef SCTP_EVENT-
1087 memset(&event, 0, sizeof(event));-
1088 event.se_assoc_id = 0;-
1089 event.se_type = SCTP_SENDER_DRY_EVENT;-
1090 event.se_on = 0;-
1091 i = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event,-
1092 sizeof(struct sctp_event));-
1093 if (i < 0) {-
1094 ret = i;-
1095 break;-
1096 }-
1097# else-
1098 eventsize = sizeof(struct sctp_event_subscribe);-
1099 i = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event,-
1100 &eventsize);-
1101 if (i < 0) {-
1102 ret = i;-
1103 break;-
1104 }-
1105-
1106 event.sctp_sender_dry_event = 0;-
1107-
1108 i = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event,-
1109 sizeof(struct sctp_event_subscribe));-
1110 if (i < 0) {-
1111 ret = i;-
1112 break;-
1113 }-
1114# endif-
1115 }-
1116# ifdef SCTP_AUTHENTICATION_EVENT-
1117 if (snp->sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)-
1118 dgram_sctp_handle_auth_free_key_event(b, snp);-
1119# endif-
1120-
1121 if (data->handle_notifications != NULL)-
1122 data->handle_notifications(b, data->notification_context,-
1123 (void *)out);-
1124-
1125 memset(out, 0, outl);-
1126 } else-
1127 ret += n;-
1128 }-
1129 while ((msg.msg_flags & MSG_NOTIFICATION) && (msg.msg_flags & MSG_EOR)-
1130 && (ret < outl));-
1131-
1132 if (ret > 0 && !(msg.msg_flags & MSG_EOR)) {-
1133 /* Partial message read, this should never happen! */-
1134-
1135 /*-
1136 * The buffer was too small, this means the peer sent a message-
1137 * that was larger than allowed.-
1138 */-
1139 if (ret == outl)-
1140 return -1;-
1141-
1142 /*-
1143 * Test if socket buffer can handle max record size (2^14 + 2048-
1144 * + 13)-
1145 */-
1146 optlen = (socklen_t) sizeof(int);-
1147 ret = getsockopt(b->num, SOL_SOCKET, SO_RCVBUF, &optval, &optlen);-
1148 if (ret >= 0)-
1149 OPENSSL_assert(optval >= 18445);-
1150-
1151 /*-
1152 * Test if SCTP doesn't partially deliver below max record size-
1153 * (2^14 + 2048 + 13)-
1154 */-
1155 optlen = (socklen_t) sizeof(int);-
1156 ret =-
1157 getsockopt(b->num, IPPROTO_SCTP, SCTP_PARTIAL_DELIVERY_POINT,-
1158 &optval, &optlen);-
1159 if (ret >= 0)-
1160 OPENSSL_assert(optval >= 18445);-
1161-
1162 /*-
1163 * Partially delivered notification??? Probably a bug....-
1164 */-
1165 OPENSSL_assert(!(msg.msg_flags & MSG_NOTIFICATION));-
1166-
1167 /*-
1168 * Everything seems ok till now, so it's most likely a message-
1169 * dropped by PR-SCTP.-
1170 */-
1171 memset(out, 0, outl);-
1172 BIO_set_retry_read(b);-
1173 return -1;-
1174 }-
1175-
1176 BIO_clear_retry_flags(b);-
1177 if (ret < 0) {-
1178 if (BIO_dgram_should_retry(ret)) {-
1179 BIO_set_retry_read(b);-
1180 data->_errno = get_last_socket_error();-
1181 }-
1182 }-
1183-
1184 /* Test if peer uses SCTP-AUTH before continuing */-
1185 if (!data->peer_auth_tested) {-
1186 int ii, auth_data = 0, auth_forward = 0;-
1187 unsigned char *p;-
1188 struct sctp_authchunks *authchunks;-
1189-
1190 optlen =-
1191 (socklen_t) (sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t));-
1192 authchunks = OPENSSL_malloc(optlen);-
1193 if (authchunks == NULL) {-
1194 BIOerr(BIO_F_DGRAM_SCTP_READ, ERR_R_MALLOC_FAILURE);-
1195 return -1;-
1196 }-
1197 memset(authchunks, 0, optlen);-
1198 ii = getsockopt(b->num, IPPROTO_SCTP, SCTP_PEER_AUTH_CHUNKS,-
1199 authchunks, &optlen);-
1200-
1201 if (ii >= 0)-
1202 for (p = (unsigned char *)authchunks->gauth_chunks;-
1203 p < (unsigned char *)authchunks + optlen;-
1204 p += sizeof(uint8_t)) {-
1205 if (*p == OPENSSL_SCTP_DATA_CHUNK_TYPE)-
1206 auth_data = 1;-
1207 if (*p == OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE)-
1208 auth_forward = 1;-
1209 }-
1210-
1211 OPENSSL_free(authchunks);-
1212-
1213 if (!auth_data || !auth_forward) {-
1214 BIOerr(BIO_F_DGRAM_SCTP_READ, BIO_R_CONNECT_ERROR);-
1215 return -1;-
1216 }-
1217-
1218 data->peer_auth_tested = 1;-
1219 }-
1220 }-
1221 return ret;-
1222}-
1223-
1224/*-
1225 * dgram_sctp_write - send message on SCTP socket-
1226 * @b: BIO to write to-
1227 * @in: data to send-
1228 * @inl: amount of bytes in @in to send-
1229 *-
1230 * Returns -1 on error or the sent amount of bytes on success-
1231 */-
1232static int dgram_sctp_write(BIO *b, const char *in, int inl)-
1233{-
1234 int ret;-
1235 bio_dgram_sctp_data *data = (bio_dgram_sctp_data *) b->ptr;-
1236 struct bio_dgram_sctp_sndinfo *sinfo = &(data->sndinfo);-
1237 struct bio_dgram_sctp_prinfo *pinfo = &(data->prinfo);-
1238 struct bio_dgram_sctp_sndinfo handshake_sinfo;-
1239 struct iovec iov[1];-
1240 struct msghdr msg;-
1241 struct cmsghdr *cmsg;-
1242# if defined(SCTP_SNDINFO) && defined(SCTP_PRINFO)-
1243 char cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndinfo)) +-
1244 CMSG_SPACE(sizeof(struct sctp_prinfo))];-
1245 struct sctp_sndinfo *sndinfo;-
1246 struct sctp_prinfo *prinfo;-
1247# else-
1248 char cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))];-
1249 struct sctp_sndrcvinfo *sndrcvinfo;-
1250# endif-
1251-
1252 clear_socket_error();-
1253-
1254 /*-
1255 * If we're send anything else than application data, disable all user-
1256 * parameters and flags.-
1257 */-
1258 if (in[0] != 23) {-
1259 memset(&handshake_sinfo, 0, sizeof(handshake_sinfo));-
1260# ifdef SCTP_SACK_IMMEDIATELY-
1261 handshake_sinfo.snd_flags = SCTP_SACK_IMMEDIATELY;-
1262# endif-
1263 sinfo = &handshake_sinfo;-
1264 }-
1265-
1266 /* We can only send a shutdown alert if the socket is dry */-
1267 if (data->save_shutdown) {-
1268 ret = BIO_dgram_sctp_wait_for_dry(b);-
1269 if (ret < 0)-
1270 return -1;-
1271 if (ret == 0) {-
1272 BIO_clear_retry_flags(b);-
1273 BIO_set_retry_write(b);-
1274 return -1;-
1275 }-
1276 }-
1277-
1278 iov[0].iov_base = (char *)in;-
1279 iov[0].iov_len = inl;-
1280 msg.msg_name = NULL;-
1281 msg.msg_namelen = 0;-
1282 msg.msg_iov = iov;-
1283 msg.msg_iovlen = 1;-
1284 msg.msg_control = (caddr_t) cmsgbuf;-
1285 msg.msg_controllen = 0;-
1286 msg.msg_flags = 0;-
1287# if defined(SCTP_SNDINFO) && defined(SCTP_PRINFO)-
1288 cmsg = (struct cmsghdr *)cmsgbuf;-
1289 cmsg->cmsg_level = IPPROTO_SCTP;-
1290 cmsg->cmsg_type = SCTP_SNDINFO;-
1291 cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndinfo));-
1292 sndinfo = (struct sctp_sndinfo *)CMSG_DATA(cmsg);-
1293 memset(sndinfo, 0, sizeof(*sndinfo));-
1294 sndinfo->snd_sid = sinfo->snd_sid;-
1295 sndinfo->snd_flags = sinfo->snd_flags;-
1296 sndinfo->snd_ppid = sinfo->snd_ppid;-
1297 sndinfo->snd_context = sinfo->snd_context;-
1298 msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndinfo));-
1299-
1300 cmsg =-
1301 (struct cmsghdr *)&cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndinfo))];-
1302 cmsg->cmsg_level = IPPROTO_SCTP;-
1303 cmsg->cmsg_type = SCTP_PRINFO;-
1304 cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_prinfo));-
1305 prinfo = (struct sctp_prinfo *)CMSG_DATA(cmsg);-
1306 memset(prinfo, 0, sizeof(*prinfo));-
1307 prinfo->pr_policy = pinfo->pr_policy;-
1308 prinfo->pr_value = pinfo->pr_value;-
1309 msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_prinfo));-
1310# else-
1311 cmsg = (struct cmsghdr *)cmsgbuf;-
1312 cmsg->cmsg_level = IPPROTO_SCTP;-
1313 cmsg->cmsg_type = SCTP_SNDRCV;-
1314 cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));-
1315 sndrcvinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);-
1316 memset(sndrcvinfo, 0, sizeof(*sndrcvinfo));-
1317 sndrcvinfo->sinfo_stream = sinfo->snd_sid;-
1318 sndrcvinfo->sinfo_flags = sinfo->snd_flags;-
1319# ifdef __FreeBSD__-
1320 sndrcvinfo->sinfo_flags |= pinfo->pr_policy;-
1321# endif-
1322 sndrcvinfo->sinfo_ppid = sinfo->snd_ppid;-
1323 sndrcvinfo->sinfo_context = sinfo->snd_context;-
1324 sndrcvinfo->sinfo_timetolive = pinfo->pr_value;-
1325 msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndrcvinfo));-
1326# endif-
1327-
1328 ret = sendmsg(b->num, &msg, 0);-
1329-
1330 BIO_clear_retry_flags(b);-
1331 if (ret <= 0) {-
1332 if (BIO_dgram_should_retry(ret)) {-
1333 BIO_set_retry_write(b);-
1334 data->_errno = get_last_socket_error();-
1335 }-
1336 }-
1337 return ret;-
1338}-
1339-
1340static long dgram_sctp_ctrl(BIO *b, int cmd, long num, void *ptr)-
1341{-
1342 long ret = 1;-
1343 bio_dgram_sctp_data *data = NULL;-
1344 socklen_t sockopt_len = 0;-
1345 struct sctp_authkeyid authkeyid;-
1346 struct sctp_authkey *authkey = NULL;-
1347-
1348 data = (bio_dgram_sctp_data *) b->ptr;-
1349-
1350 switch (cmd) {-
1351 case BIO_CTRL_DGRAM_QUERY_MTU:-
1352 /*-
1353 * Set to maximum (2^14) and ignore user input to enable transport-
1354 * protocol fragmentation. Returns always 2^14.-
1355 */-
1356 data->mtu = 16384;-
1357 ret = data->mtu;-
1358 break;-
1359 case BIO_CTRL_DGRAM_SET_MTU:-
1360 /*-
1361 * Set to maximum (2^14) and ignore input to enable transport-
1362 * protocol fragmentation. Returns always 2^14.-
1363 */-
1364 data->mtu = 16384;-
1365 ret = data->mtu;-
1366 break;-
1367 case BIO_CTRL_DGRAM_SET_CONNECTED:-
1368 case BIO_CTRL_DGRAM_CONNECT:-
1369 /* Returns always -1. */-
1370 ret = -1;-
1371 break;-
1372 case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:-
1373 /*-
1374 * SCTP doesn't need the DTLS timer Returns always 1.-
1375 */-
1376 break;-
1377 case BIO_CTRL_DGRAM_GET_MTU_OVERHEAD:-
1378 /*-
1379 * We allow transport protocol fragmentation so this is irrelevant-
1380 */-
1381 ret = 0;-
1382 break;-
1383 case BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE:-
1384 if (num > 0)-
1385 data->in_handshake = 1;-
1386 else-
1387 data->in_handshake = 0;-
1388-
1389 ret =-
1390 setsockopt(b->num, IPPROTO_SCTP, SCTP_NODELAY,-
1391 &data->in_handshake, sizeof(int));-
1392 break;-
1393 case BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY:-
1394 /*-
1395 * New shared key for SCTP AUTH. Returns 0 on success, -1 otherwise.-
1396 */-
1397-
1398 /* Get active key */-
1399 sockopt_len = sizeof(struct sctp_authkeyid);-
1400 ret =-
1401 getsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, &authkeyid,-
1402 &sockopt_len);-
1403 if (ret < 0)-
1404 break;-
1405-
1406 /* Add new key */-
1407 sockopt_len = sizeof(struct sctp_authkey) + 64 * sizeof(uint8_t);-
1408 authkey = OPENSSL_malloc(sockopt_len);-
1409 if (authkey == NULL) {-
1410 ret = -1;-
1411 break;-
1412 }-
1413 memset(authkey, 0, sockopt_len);-
1414 authkey->sca_keynumber = authkeyid.scact_keynumber + 1;-
1415# ifndef __FreeBSD__-
1416 /*-
1417 * This field is missing in FreeBSD 8.2 and earlier, and FreeBSD 8.3-
1418 * and higher work without it.-
1419 */-
1420 authkey->sca_keylength = 64;-
1421# endif-
1422 memcpy(&authkey->sca_key[0], ptr, 64 * sizeof(uint8_t));-
1423-
1424 ret =-
1425 setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_KEY, authkey,-
1426 sockopt_len);-
1427 OPENSSL_free(authkey);-
1428 authkey = NULL;-
1429 if (ret < 0)-
1430 break;-
1431-
1432 /* Reset active key */-
1433 ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY,-
1434 &authkeyid, sizeof(struct sctp_authkeyid));-
1435 if (ret < 0)-
1436 break;-
1437-
1438 break;-
1439 case BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY:-
1440 /* Returns 0 on success, -1 otherwise. */-
1441-
1442 /* Get active key */-
1443 sockopt_len = sizeof(struct sctp_authkeyid);-
1444 ret =-
1445 getsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, &authkeyid,-
1446 &sockopt_len);-
1447 if (ret < 0)-
1448 break;-
1449-
1450 /* Set active key */-
1451 authkeyid.scact_keynumber = authkeyid.scact_keynumber + 1;-
1452 ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY,-
1453 &authkeyid, sizeof(struct sctp_authkeyid));-
1454 if (ret < 0)-
1455 break;-
1456-
1457 /*-
1458 * CCS has been sent, so remember that and fall through to check if-
1459 * we need to deactivate an old key-
1460 */-
1461 data->ccs_sent = 1;-
1462 /* fall-through */-
1463-
1464 case BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD:-
1465 /* Returns 0 on success, -1 otherwise. */-
1466-
1467 /*-
1468 * Has this command really been called or is this just a-
1469 * fall-through?-
1470 */-
1471 if (cmd == BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD)-
1472 data->ccs_rcvd = 1;-
1473-
1474 /*-
1475 * CSS has been both, received and sent, so deactivate an old key-
1476 */-
1477 if (data->ccs_rcvd == 1 && data->ccs_sent == 1) {-
1478 /* Get active key */-
1479 sockopt_len = sizeof(struct sctp_authkeyid);-
1480 ret =-
1481 getsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY,-
1482 &authkeyid, &sockopt_len);-
1483 if (ret < 0)-
1484 break;-
1485-
1486 /*-
1487 * Deactivate key or delete second last key if-
1488 * SCTP_AUTHENTICATION_EVENT is not available.-
1489 */-
1490 authkeyid.scact_keynumber = authkeyid.scact_keynumber - 1;-
1491# ifdef SCTP_AUTH_DEACTIVATE_KEY-
1492 sockopt_len = sizeof(struct sctp_authkeyid);-
1493 ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_DEACTIVATE_KEY,-
1494 &authkeyid, sockopt_len);-
1495 if (ret < 0)-
1496 break;-
1497# endif-
1498# ifndef SCTP_AUTHENTICATION_EVENT-
1499 if (authkeyid.scact_keynumber > 0) {-
1500 authkeyid.scact_keynumber = authkeyid.scact_keynumber - 1;-
1501 ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_DELETE_KEY,-
1502 &authkeyid, sizeof(struct sctp_authkeyid));-
1503 if (ret < 0)-
1504 break;-
1505 }-
1506# endif-
1507-
1508 data->ccs_rcvd = 0;-
1509 data->ccs_sent = 0;-
1510 }-
1511 break;-
1512 case BIO_CTRL_DGRAM_SCTP_GET_SNDINFO:-
1513 /* Returns the size of the copied struct. */-
1514 if (num > (long)sizeof(struct bio_dgram_sctp_sndinfo))-
1515 num = sizeof(struct bio_dgram_sctp_sndinfo);-
1516-
1517 memcpy(ptr, &(data->sndinfo), num);-
1518 ret = num;-
1519 break;-
1520 case BIO_CTRL_DGRAM_SCTP_SET_SNDINFO:-
1521 /* Returns the size of the copied struct. */-
1522 if (num > (long)sizeof(struct bio_dgram_sctp_sndinfo))-
1523 num = sizeof(struct bio_dgram_sctp_sndinfo);-
1524-
1525 memcpy(&(data->sndinfo), ptr, num);-
1526 break;-
1527 case BIO_CTRL_DGRAM_SCTP_GET_RCVINFO:-
1528 /* Returns the size of the copied struct. */-
1529 if (num > (long)sizeof(struct bio_dgram_sctp_rcvinfo))-
1530 num = sizeof(struct bio_dgram_sctp_rcvinfo);-
1531-
1532 memcpy(ptr, &data->rcvinfo, num);-
1533-
1534 ret = num;-
1535 break;-
1536 case BIO_CTRL_DGRAM_SCTP_SET_RCVINFO:-
1537 /* Returns the size of the copied struct. */-
1538 if (num > (long)sizeof(struct bio_dgram_sctp_rcvinfo))-
1539 num = sizeof(struct bio_dgram_sctp_rcvinfo);-
1540-
1541 memcpy(&(data->rcvinfo), ptr, num);-
1542 break;-
1543 case BIO_CTRL_DGRAM_SCTP_GET_PRINFO:-
1544 /* Returns the size of the copied struct. */-
1545 if (num > (long)sizeof(struct bio_dgram_sctp_prinfo))-
1546 num = sizeof(struct bio_dgram_sctp_prinfo);-
1547-
1548 memcpy(ptr, &(data->prinfo), num);-
1549 ret = num;-
1550 break;-
1551 case BIO_CTRL_DGRAM_SCTP_SET_PRINFO:-
1552 /* Returns the size of the copied struct. */-
1553 if (num > (long)sizeof(struct bio_dgram_sctp_prinfo))-
1554 num = sizeof(struct bio_dgram_sctp_prinfo);-
1555-
1556 memcpy(&(data->prinfo), ptr, num);-
1557 break;-
1558 case BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN:-
1559 /* Returns always 1. */-
1560 if (num > 0)-
1561 data->save_shutdown = 1;-
1562 else-
1563 data->save_shutdown = 0;-
1564 break;-
1565-
1566 default:-
1567 /*-
1568 * Pass to default ctrl function to process SCTP unspecific commands-
1569 */-
1570 ret = dgram_ctrl(b, cmd, num, ptr);-
1571 break;-
1572 }-
1573 return ret;-
1574}-
1575-
1576int BIO_dgram_sctp_notification_cb(BIO *b,-
1577 void (*handle_notifications) (BIO *bio,-
1578 void-
1579 *context,-
1580 void *buf),-
1581 void *context)-
1582{-
1583 bio_dgram_sctp_data *data = (bio_dgram_sctp_data *) b->ptr;-
1584-
1585 if (handle_notifications != NULL) {-
1586 data->handle_notifications = handle_notifications;-
1587 data->notification_context = context;-
1588 } else-
1589 return -1;-
1590-
1591 return 0;-
1592}-
1593-
1594/*-
1595 * BIO_dgram_sctp_wait_for_dry - Wait for SCTP SENDER_DRY event-
1596 * @b: The BIO to check for the dry event-
1597 *-
1598 * Wait until the peer confirms all packets have been received, and so that-
1599 * our kernel doesn't have anything to send anymore. This is only received by-
1600 * the peer's kernel, not the application.-
1601 *-
1602 * Returns:-
1603 * -1 on error-
1604 * 0 when not dry yet-
1605 * 1 when dry-
1606 */-
1607int BIO_dgram_sctp_wait_for_dry(BIO *b)-
1608{-
1609 int is_dry = 0;-
1610 int sockflags = 0;-
1611 int n, ret;-
1612 union sctp_notification snp;-
1613 struct msghdr msg;-
1614 struct iovec iov;-
1615# ifdef SCTP_EVENT-
1616 struct sctp_event event;-
1617# else-
1618 struct sctp_event_subscribe event;-
1619 socklen_t eventsize;-
1620# endif-
1621 bio_dgram_sctp_data *data = (bio_dgram_sctp_data *) b->ptr;-
1622-
1623 /* set sender dry event */-
1624# ifdef SCTP_EVENT-
1625 memset(&event, 0, sizeof(event));-
1626 event.se_assoc_id = 0;-
1627 event.se_type = SCTP_SENDER_DRY_EVENT;-
1628 event.se_on = 1;-
1629 ret =-
1630 setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event,-
1631 sizeof(struct sctp_event));-
1632# else-
1633 eventsize = sizeof(struct sctp_event_subscribe);-
1634 ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize);-
1635 if (ret < 0)-
1636 return -1;-
1637-
1638 event.sctp_sender_dry_event = 1;-
1639-
1640 ret =-
1641 setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event,-
1642 sizeof(struct sctp_event_subscribe));-
1643# endif-
1644 if (ret < 0)-
1645 return -1;-
1646-
1647 /* peek for notification */-
1648 memset(&snp, 0, sizeof(snp));-
1649 iov.iov_base = (char *)&snp;-
1650 iov.iov_len = sizeof(union sctp_notification);-
1651 msg.msg_name = NULL;-
1652 msg.msg_namelen = 0;-
1653 msg.msg_iov = &iov;-
1654 msg.msg_iovlen = 1;-
1655 msg.msg_control = NULL;-
1656 msg.msg_controllen = 0;-
1657 msg.msg_flags = 0;-
1658-
1659 n = recvmsg(b->num, &msg, MSG_PEEK);-
1660 if (n <= 0) {-
1661 if ((n < 0) && (get_last_socket_error() != EAGAIN)-
1662 && (get_last_socket_error() != EWOULDBLOCK))-
1663 return -1;-
1664 else-
1665 return 0;-
1666 }-
1667-
1668 /* if we find a notification, process it and try again if necessary */-
1669 while (msg.msg_flags & MSG_NOTIFICATION) {-
1670 memset(&snp, 0, sizeof(snp));-
1671 iov.iov_base = (char *)&snp;-
1672 iov.iov_len = sizeof(union sctp_notification);-
1673 msg.msg_name = NULL;-
1674 msg.msg_namelen = 0;-
1675 msg.msg_iov = &iov;-
1676 msg.msg_iovlen = 1;-
1677 msg.msg_control = NULL;-
1678 msg.msg_controllen = 0;-
1679 msg.msg_flags = 0;-
1680-
1681 n = recvmsg(b->num, &msg, 0);-
1682 if (n <= 0) {-
1683 if ((n < 0) && (get_last_socket_error() != EAGAIN)-
1684 && (get_last_socket_error() != EWOULDBLOCK))-
1685 return -1;-
1686 else-
1687 return is_dry;-
1688 }-
1689-
1690 if (snp.sn_header.sn_type == SCTP_SENDER_DRY_EVENT) {-
1691 is_dry = 1;-
1692-
1693 /* disable sender dry event */-
1694# ifdef SCTP_EVENT-
1695 memset(&event, 0, sizeof(event));-
1696 event.se_assoc_id = 0;-
1697 event.se_type = SCTP_SENDER_DRY_EVENT;-
1698 event.se_on = 0;-
1699 ret =-
1700 setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event,-
1701 sizeof(struct sctp_event));-
1702# else-
1703 eventsize = (socklen_t) sizeof(struct sctp_event_subscribe);-
1704 ret =-
1705 getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event,-
1706 &eventsize);-
1707 if (ret < 0)-
1708 return -1;-
1709-
1710 event.sctp_sender_dry_event = 0;-
1711-
1712 ret =-
1713 setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event,-
1714 sizeof(struct sctp_event_subscribe));-
1715# endif-
1716 if (ret < 0)-
1717 return -1;-
1718 }-
1719# ifdef SCTP_AUTHENTICATION_EVENT-
1720 if (snp.sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)-
1721 dgram_sctp_handle_auth_free_key_event(b, &snp);-
1722# endif-
1723-
1724 if (data->handle_notifications != NULL)-
1725 data->handle_notifications(b, data->notification_context,-
1726 (void *)&snp);-
1727-
1728 /* found notification, peek again */-
1729 memset(&snp, 0, sizeof(snp));-
1730 iov.iov_base = (char *)&snp;-
1731 iov.iov_len = sizeof(union sctp_notification);-
1732 msg.msg_name = NULL;-
1733 msg.msg_namelen = 0;-
1734 msg.msg_iov = &iov;-
1735 msg.msg_iovlen = 1;-
1736 msg.msg_control = NULL;-
1737 msg.msg_controllen = 0;-
1738 msg.msg_flags = 0;-
1739-
1740 /* if we have seen the dry already, don't wait */-
1741 if (is_dry) {-
1742 sockflags = fcntl(b->num, F_GETFL, 0);-
1743 fcntl(b->num, F_SETFL, O_NONBLOCK);-
1744 }-
1745-
1746 n = recvmsg(b->num, &msg, MSG_PEEK);-
1747-
1748 if (is_dry) {-
1749 fcntl(b->num, F_SETFL, sockflags);-
1750 }-
1751-
1752 if (n <= 0) {-
1753 if ((n < 0) && (get_last_socket_error() != EAGAIN)-
1754 && (get_last_socket_error() != EWOULDBLOCK))-
1755 return -1;-
1756 else-
1757 return is_dry;-
1758 }-
1759 }-
1760-
1761 /* read anything else */-
1762 return is_dry;-
1763}-
1764-
1765int BIO_dgram_sctp_msg_waiting(BIO *b)-
1766{-
1767 int n, sockflags;-
1768 union sctp_notification snp;-
1769 struct msghdr msg;-
1770 struct iovec iov;-
1771 bio_dgram_sctp_data *data = (bio_dgram_sctp_data *) b->ptr;-
1772-
1773 /* Check if there are any messages waiting to be read */-
1774 do {-
1775 memset(&snp, 0, sizeof(snp));-
1776 iov.iov_base = (char *)&snp;-
1777 iov.iov_len = sizeof(union sctp_notification);-
1778 msg.msg_name = NULL;-
1779 msg.msg_namelen = 0;-
1780 msg.msg_iov = &iov;-
1781 msg.msg_iovlen = 1;-
1782 msg.msg_control = NULL;-
1783 msg.msg_controllen = 0;-
1784 msg.msg_flags = 0;-
1785-
1786 sockflags = fcntl(b->num, F_GETFL, 0);-
1787 fcntl(b->num, F_SETFL, O_NONBLOCK);-
1788 n = recvmsg(b->num, &msg, MSG_PEEK);-
1789 fcntl(b->num, F_SETFL, sockflags);-
1790-
1791 /* if notification, process and try again */-
1792 if (n > 0 && (msg.msg_flags & MSG_NOTIFICATION)) {-
1793# ifdef SCTP_AUTHENTICATION_EVENT-
1794 if (snp.sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)-
1795 dgram_sctp_handle_auth_free_key_event(b, &snp);-
1796# endif-
1797-
1798 memset(&snp, 0, sizeof(snp));-
1799 iov.iov_base = (char *)&snp;-
1800 iov.iov_len = sizeof(union sctp_notification);-
1801 msg.msg_name = NULL;-
1802 msg.msg_namelen = 0;-
1803 msg.msg_iov = &iov;-
1804 msg.msg_iovlen = 1;-
1805 msg.msg_control = NULL;-
1806 msg.msg_controllen = 0;-
1807 msg.msg_flags = 0;-
1808 n = recvmsg(b->num, &msg, 0);-
1809-
1810 if (data->handle_notifications != NULL)-
1811 data->handle_notifications(b, data->notification_context,-
1812 (void *)&snp);-
1813 }-
1814-
1815 } while (n > 0 && (msg.msg_flags & MSG_NOTIFICATION));-
1816-
1817 /* Return 1 if there is a message to be read, return 0 otherwise. */-
1818 if (n > 0)-
1819 return 1;-
1820 else-
1821 return 0;-
1822}-
1823-
1824static int dgram_sctp_puts(BIO *bp, const char *str)-
1825{-
1826 int n, ret;-
1827-
1828 n = strlen(str);-
1829 ret = dgram_sctp_write(bp, str, n);-
1830 return ret;-
1831}-
1832# endif-
1833-
1834static int BIO_dgram_should_retry(int i)-
1835{-
1836 int err;-
1837-
1838 if ((i == 0) || (i == -1)) {
(i == 0)Description
TRUEnever evaluated
FALSEnever evaluated
(i == -1)Description
TRUEnever evaluated
FALSEnever evaluated
0
1839 err = get_last_socket_error();-
1840-
1841# if defined(OPENSSL_SYS_WINDOWS)-
1842 /*-
1843 * If the socket return value (i) is -1 and err is unexpectedly 0 at-
1844 * this point, the error code was overwritten by another system call-
1845 * before this error handling is called.-
1846 */-
1847# endif-
1848-
1849 return BIO_dgram_non_fatal_error(err);
never executed: return BIO_dgram_non_fatal_error(err);
0
1850 }-
1851 return 0;
never executed: return 0;
0
1852}-
1853-
1854int BIO_dgram_non_fatal_error(int err)-
1855{-
1856 switch (err) {-
1857# if defined(OPENSSL_SYS_WINDOWS)-
1858# if defined(WSAEWOULDBLOCK)-
1859 case WSAEWOULDBLOCK:-
1860# endif-
1861# endif-
1862-
1863# ifdef EWOULDBLOCK-
1864# ifdef WSAEWOULDBLOCK-
1865# if WSAEWOULDBLOCK != EWOULDBLOCK-
1866 case EWOULDBLOCK:-
1867# endif-
1868# else-
1869 case EWOULDBLOCK:
never executed: case 11 :
0
1870# endif-
1871# endif-
1872-
1873# ifdef EINTR-
1874 case EINTR:
never executed: case 4 :
0
1875# endif-
1876-
1877# ifdef EAGAIN-
1878# if EWOULDBLOCK != EAGAIN-
1879 case EAGAIN:-
1880# endif-
1881# endif-
1882-
1883# ifdef EPROTO-
1884 case EPROTO:
never executed: case 71 :
0
1885# endif-
1886-
1887# ifdef EINPROGRESS-
1888 case EINPROGRESS:
never executed: case 115 :
0
1889# endif-
1890-
1891# ifdef EALREADY-
1892 case EALREADY:
never executed: case 114 :
0
1893# endif-
1894-
1895 return 1;
never executed: return 1;
0
1896 default:
never executed: default:
0
1897 break;
never executed: break;
0
1898 }-
1899 return 0;
never executed: return 0;
0
1900}-
1901-
1902static void get_current_time(struct timeval *t)-
1903{-
1904# if defined(_WIN32)-
1905 SYSTEMTIME st;-
1906 union {-
1907 unsigned __int64 ul;-
1908 FILETIME ft;-
1909 } now;-
1910-
1911 GetSystemTime(&st);-
1912 SystemTimeToFileTime(&st, &now.ft);-
1913# ifdef __MINGW32__-
1914 now.ul -= 116444736000000000ULL;-
1915# else-
1916 now.ul -= 116444736000000000UI64; /* re-bias to 1/1/1970 */-
1917# endif-
1918 t->tv_sec = (long)(now.ul / 10000000);-
1919 t->tv_usec = ((int)(now.ul % 10000000)) / 10;-
1920# else-
1921 gettimeofday(t, NULL);-
1922# endif-
1923}
never executed: end of block
0
1924-
1925#endif-
Source codeSwitch to Preprocessed file

Generated by Squish Coco 4.2.2