comparison libfdcore/cnxctx.c @ 1419:89cbb08d3189

Remove trailing whitespace.
author Thomas Klausner <tk@giga.or.at>
date Tue, 18 Feb 2020 11:38:37 +0100
parents b68fb21c2f72
children 407e0a889c7e
comparison
equal deleted inserted replaced
1418:a51f71694121 1419:89cbb08d3189
174 if (fd_g_config->cnf_flags.no_ip6) { 174 if (fd_g_config->cnf_flags.no_ip6) {
175 cnx->cc_family = AF_INET; 175 cnx->cc_family = AF_INET;
176 } else { 176 } else {
177 cnx->cc_family = AF_INET6; /* can create socket for both IP and IPv6 */ 177 cnx->cc_family = AF_INET6; /* can create socket for both IP and IPv6 */
178 } 178 }
179 179
180 /* Create the socket */ 180 /* Create the socket */
181 CHECK_FCT_DO( fd_sctp_create_bind_server( &cnx->cc_socket, cnx->cc_family, ep_list, port ), goto error ); 181 CHECK_FCT_DO( fd_sctp_create_bind_server( &cnx->cc_socket, cnx->cc_family, ep_list, port ), goto error );
182 182
183 /* Generate the name for the connection object */ 183 /* Generate the name for the connection object */
184 snprintf(cnx->cc_id, sizeof(cnx->cc_id), CC_ID_HDR "SCTP srv :%hu (%d)", port, cnx->cc_socket); 184 snprintf(cnx->cc_id, sizeof(cnx->cc_id), CC_ID_HDR "SCTP srv :%hu (%d)", port, cnx->cc_socket);
224 socklen_t ss_len = sizeof(ss); 224 socklen_t ss_len = sizeof(ss);
225 int cli_sock = 0; 225 int cli_sock = 0;
226 226
227 TRACE_ENTRY("%p", serv); 227 TRACE_ENTRY("%p", serv);
228 CHECK_PARAMS_DO(serv, return NULL); 228 CHECK_PARAMS_DO(serv, return NULL);
229 229
230 /* Accept the new connection -- this is blocking until new client enters or until cancellation */ 230 /* Accept the new connection -- this is blocking until new client enters or until cancellation */
231 CHECK_SYS_DO( cli_sock = accept(serv->cc_socket, (sSA *)&ss, &ss_len), return NULL ); 231 CHECK_SYS_DO( cli_sock = accept(serv->cc_socket, (sSA *)&ss, &ss_len), return NULL );
232 232
233 CHECK_MALLOC_DO( cli = fd_cnx_init(1), { shutdown(cli_sock, SHUT_RDWR); close(cli_sock); return NULL; } ); 233 CHECK_MALLOC_DO( cli = fd_cnx_init(1), { shutdown(cli_sock, SHUT_RDWR); close(cli_sock); return NULL; } );
234 cli->cc_socket = cli_sock; 234 cli->cc_socket = cli_sock;
235 cli->cc_family = serv->cc_family; 235 cli->cc_family = serv->cc_family;
236 cli->cc_proto = serv->cc_proto; 236 cli->cc_proto = serv->cc_proto;
237 237
238 /* Set the timeout */ 238 /* Set the timeout */
239 fd_cnx_s_setto(cli->cc_socket); 239 fd_cnx_s_setto(cli->cc_socket);
240 240
241 /* Generate the name for the connection object */ 241 /* Generate the name for the connection object */
242 { 242 {
243 char addrbuf[INET6_ADDRSTRLEN]; 243 char addrbuf[INET6_ADDRSTRLEN];
244 char portbuf[10]; 244 char portbuf[10];
245 int rc; 245 int rc;
246 246
247 rc = getnameinfo((sSA *)&ss, ss_len, addrbuf, sizeof(addrbuf), portbuf, sizeof(portbuf), NI_NUMERICHOST | NI_NUMERICSERV); 247 rc = getnameinfo((sSA *)&ss, ss_len, addrbuf, sizeof(addrbuf), portbuf, sizeof(portbuf), NI_NUMERICHOST | NI_NUMERICSERV);
248 if (rc) { 248 if (rc) {
249 snprintf(addrbuf, sizeof(addrbuf), "[err:%s]", gai_strerror(rc)); 249 snprintf(addrbuf, sizeof(addrbuf), "[err:%s]", gai_strerror(rc));
250 portbuf[0] = '\0'; 250 portbuf[0] = '\0';
251 } 251 }
252 252
253 /* Numeric values for debug... */ 253 /* Numeric values for debug... */
254 snprintf(cli->cc_id, sizeof(cli->cc_id), CC_ID_HDR "%s from [%s]:%s (%d<-%d)", 254 snprintf(cli->cc_id, sizeof(cli->cc_id), CC_ID_HDR "%s from [%s]:%s (%d<-%d)",
255 IPPROTO_NAME(cli->cc_proto), addrbuf, portbuf, serv->cc_socket, cli->cc_socket); 255 IPPROTO_NAME(cli->cc_proto), addrbuf, portbuf, serv->cc_socket, cli->cc_socket);
256 256
257 257
258 /* ...Name for log messages */ 258 /* ...Name for log messages */
259 rc = getnameinfo((sSA *)&ss, ss_len, cli->cc_remid, sizeof(cli->cc_remid), NULL, 0, 0); 259 rc = getnameinfo((sSA *)&ss, ss_len, cli->cc_remid, sizeof(cli->cc_remid), NULL, 0, 0);
260 if (rc) 260 if (rc)
261 snprintf(cli->cc_remid, sizeof(cli->cc_remid), "[err:%s]", gai_strerror(rc)); 261 snprintf(cli->cc_remid, sizeof(cli->cc_remid), "[err:%s]", gai_strerror(rc));
262 } 262 }
263 263
264 LOG_D("Incoming connection: '%s' <- '%s' {%s}", fd_cnx_getid(serv), cli->cc_remid, cli->cc_id); 264 LOG_D("Incoming connection: '%s' <- '%s' {%s}", fd_cnx_getid(serv), cli->cc_remid, cli->cc_id);
265 265
266 #ifndef DISABLE_SCTP 266 #ifndef DISABLE_SCTP
267 /* SCTP-specific handlings */ 267 /* SCTP-specific handlings */
268 if (cli->cc_proto == IPPROTO_SCTP) { 268 if (cli->cc_proto == IPPROTO_SCTP) {
270 CHECK_FCT_DO( fd_sctp_get_str_info( cli->cc_socket, &cli->cc_sctp_para.str_in, &cli->cc_sctp_para.str_out, NULL ), {fd_cnx_destroy(cli); return NULL;} ); 270 CHECK_FCT_DO( fd_sctp_get_str_info( cli->cc_socket, &cli->cc_sctp_para.str_in, &cli->cc_sctp_para.str_out, NULL ), {fd_cnx_destroy(cli); return NULL;} );
271 if (cli->cc_sctp_para.str_out < cli->cc_sctp_para.str_in) 271 if (cli->cc_sctp_para.str_out < cli->cc_sctp_para.str_in)
272 cli->cc_sctp_para.pairs = cli->cc_sctp_para.str_out; 272 cli->cc_sctp_para.pairs = cli->cc_sctp_para.str_out;
273 else 273 else
274 cli->cc_sctp_para.pairs = cli->cc_sctp_para.str_in; 274 cli->cc_sctp_para.pairs = cli->cc_sctp_para.str_in;
275 275
276 LOG_A( "%s : client '%s' (SCTP:%d, %d/%d streams)", fd_cnx_getid(serv), fd_cnx_getid(cli), cli->cc_socket, cli->cc_sctp_para.str_in, cli->cc_sctp_para.str_out); 276 LOG_A( "%s : client '%s' (SCTP:%d, %d/%d streams)", fd_cnx_getid(serv), fd_cnx_getid(cli), cli->cc_socket, cli->cc_sctp_para.str_in, cli->cc_sctp_para.str_out);
277 } 277 }
278 #endif /* DISABLE_SCTP */ 278 #endif /* DISABLE_SCTP */
279 279
280 return cli; 280 return cli;
284 struct cnxctx * fd_cnx_cli_connect_tcp(sSA * sa /* contains the port already */, socklen_t addrlen) 284 struct cnxctx * fd_cnx_cli_connect_tcp(sSA * sa /* contains the port already */, socklen_t addrlen)
285 { 285 {
286 int sock = 0; 286 int sock = 0;
287 struct cnxctx * cnx = NULL; 287 struct cnxctx * cnx = NULL;
288 char sa_buf[sSA_DUMP_STRLEN]; 288 char sa_buf[sSA_DUMP_STRLEN];
289 289
290 TRACE_ENTRY("%p %d", sa, addrlen); 290 TRACE_ENTRY("%p %d", sa, addrlen);
291 CHECK_PARAMS_DO( sa && addrlen, return NULL ); 291 CHECK_PARAMS_DO( sa && addrlen, return NULL );
292 292
293 fd_sa_sdump_numeric(sa_buf, sa); 293 fd_sa_sdump_numeric(sa_buf, sa);
294 294
295 LOG_D("Connecting to TCP %s...", sa_buf); 295 LOG_D("Connecting to TCP %s...", sa_buf);
296 296
297 /* Create the socket and connect, which can take some time and/or fail */ 297 /* Create the socket and connect, which can take some time and/or fail */
298 { 298 {
299 int ret = fd_tcp_client( &sock, sa, addrlen ); 299 int ret = fd_tcp_client( &sock, sa, addrlen );
300 if (ret != 0) { 300 if (ret != 0) {
301 LOG_D("TCP connection to %s failed: %s", sa_buf, strerror(ret)); 301 LOG_D("TCP connection to %s failed: %s", sa_buf, strerror(ret));
302 return NULL; 302 return NULL;
303 } 303 }
304 } 304 }
305 305
306 /* Once the socket is created successfuly, prepare the remaining of the cnx */ 306 /* Once the socket is created successfuly, prepare the remaining of the cnx */
307 CHECK_MALLOC_DO( cnx = fd_cnx_init(1), { shutdown(sock, SHUT_RDWR); close(sock); return NULL; } ); 307 CHECK_MALLOC_DO( cnx = fd_cnx_init(1), { shutdown(sock, SHUT_RDWR); close(sock); return NULL; } );
308 308
309 cnx->cc_socket = sock; 309 cnx->cc_socket = sock;
310 cnx->cc_family = sa->sa_family; 310 cnx->cc_family = sa->sa_family;
311 cnx->cc_proto = IPPROTO_TCP; 311 cnx->cc_proto = IPPROTO_TCP;
312 312
313 /* Set the timeout */ 313 /* Set the timeout */
314 fd_cnx_s_setto(cnx->cc_socket); 314 fd_cnx_s_setto(cnx->cc_socket);
315 315
316 /* Generate the names for the object */ 316 /* Generate the names for the object */
317 { 317 {
318 int rc; 318 int rc;
319 319
320 snprintf(cnx->cc_id, sizeof(cnx->cc_id), CC_ID_HDR "TCP,#%d->%s", cnx->cc_socket, sa_buf); 320 snprintf(cnx->cc_id, sizeof(cnx->cc_id), CC_ID_HDR "TCP,#%d->%s", cnx->cc_socket, sa_buf);
321 321
322 /* ...Name for log messages */ 322 /* ...Name for log messages */
323 rc = getnameinfo(sa, addrlen, cnx->cc_remid, sizeof(cnx->cc_remid), NULL, 0, 0); 323 rc = getnameinfo(sa, addrlen, cnx->cc_remid, sizeof(cnx->cc_remid), NULL, 0, 0);
324 if (rc) 324 if (rc)
325 snprintf(cnx->cc_remid, sizeof(cnx->cc_remid), "[err:%s]", gai_strerror(rc)); 325 snprintf(cnx->cc_remid, sizeof(cnx->cc_remid), "[err:%s]", gai_strerror(rc));
326 } 326 }
327 327
328 LOG_A("TCP connection to %s succeed (socket:%d).", sa_buf, sock); 328 LOG_A("TCP connection to %s succeed (socket:%d).", sa_buf, sock);
329 329
330 return cnx; 330 return cnx;
331 } 331 }
332 332
333 /* Same for SCTP, accepts a list of remote addresses to connect to (see sctp_connectx for how they are used) */ 333 /* Same for SCTP, accepts a list of remote addresses to connect to (see sctp_connectx for how they are used) */
334 struct cnxctx * fd_cnx_cli_connect_sctp(int no_ip6, uint16_t port, struct fd_list * list) 334 struct cnxctx * fd_cnx_cli_connect_sctp(int no_ip6, uint16_t port, struct fd_list * list)
341 #else /* DISABLE_SCTP */ 341 #else /* DISABLE_SCTP */
342 int sock = 0; 342 int sock = 0;
343 struct cnxctx * cnx = NULL; 343 struct cnxctx * cnx = NULL;
344 char sa_buf[sSA_DUMP_STRLEN]; 344 char sa_buf[sSA_DUMP_STRLEN];
345 sSS primary; 345 sSS primary;
346 346
347 TRACE_ENTRY("%p", list); 347 TRACE_ENTRY("%p", list);
348 CHECK_PARAMS_DO( list && !FD_IS_LIST_EMPTY(list), return NULL ); 348 CHECK_PARAMS_DO( list && !FD_IS_LIST_EMPTY(list), return NULL );
349 349
350 fd_sa_sdump_numeric(sa_buf, &((struct fd_endpoint *)(list->next))->sa); 350 fd_sa_sdump_numeric(sa_buf, &((struct fd_endpoint *)(list->next))->sa);
351 351
352 LOG_D("Connecting to SCTP %s:%hu...", sa_buf, port); 352 LOG_D("Connecting to SCTP %s:%hu...", sa_buf, port);
353 353
354 { 354 {
355 int ret = fd_sctp_client( &sock, no_ip6, port, list ); 355 int ret = fd_sctp_client( &sock, no_ip6, port, list );
356 if (ret != 0) { 356 if (ret != 0) {
357 LOG_D("SCTP connection to [%s,...] failed: %s", sa_buf, strerror(ret)); 357 LOG_D("SCTP connection to [%s,...] failed: %s", sa_buf, strerror(ret));
358 return NULL; 358 return NULL;
359 } 359 }
360 } 360 }
361 361
362 /* Once the socket is created successfuly, prepare the remaining of the cnx */ 362 /* Once the socket is created successfuly, prepare the remaining of the cnx */
363 CHECK_MALLOC_DO( cnx = fd_cnx_init(1), { shutdown(sock, SHUT_RDWR); close(sock); return NULL; } ); 363 CHECK_MALLOC_DO( cnx = fd_cnx_init(1), { shutdown(sock, SHUT_RDWR); close(sock); return NULL; } );
364 364
365 cnx->cc_socket = sock; 365 cnx->cc_socket = sock;
366 cnx->cc_family = no_ip6 ? AF_INET : AF_INET6; 366 cnx->cc_family = no_ip6 ? AF_INET : AF_INET6;
367 cnx->cc_proto = IPPROTO_SCTP; 367 cnx->cc_proto = IPPROTO_SCTP;
368 368
369 /* Set the timeout */ 369 /* Set the timeout */
370 fd_cnx_s_setto(cnx->cc_socket); 370 fd_cnx_s_setto(cnx->cc_socket);
371 371
372 /* Retrieve the number of streams and primary address */ 372 /* Retrieve the number of streams and primary address */
373 CHECK_FCT_DO( fd_sctp_get_str_info( sock, &cnx->cc_sctp_para.str_in, &cnx->cc_sctp_para.str_out, &primary ), goto error ); 373 CHECK_FCT_DO( fd_sctp_get_str_info( sock, &cnx->cc_sctp_para.str_in, &cnx->cc_sctp_para.str_out, &primary ), goto error );
374 if (cnx->cc_sctp_para.str_out < cnx->cc_sctp_para.str_in) 374 if (cnx->cc_sctp_para.str_out < cnx->cc_sctp_para.str_in)
375 cnx->cc_sctp_para.pairs = cnx->cc_sctp_para.str_out; 375 cnx->cc_sctp_para.pairs = cnx->cc_sctp_para.str_out;
376 else 376 else
377 cnx->cc_sctp_para.pairs = cnx->cc_sctp_para.str_in; 377 cnx->cc_sctp_para.pairs = cnx->cc_sctp_para.str_in;
378 378
379 fd_sa_sdump_numeric(sa_buf, (sSA *)&primary); 379 fd_sa_sdump_numeric(sa_buf, (sSA *)&primary);
380 380
381 /* Generate the names for the object */ 381 /* Generate the names for the object */
382 { 382 {
383 int rc; 383 int rc;
384 384
385 snprintf(cnx->cc_id, sizeof(cnx->cc_id), CC_ID_HDR "SCTP,#%d->%s", cnx->cc_socket, sa_buf); 385 snprintf(cnx->cc_id, sizeof(cnx->cc_id), CC_ID_HDR "SCTP,#%d->%s", cnx->cc_socket, sa_buf);
386 386
387 /* ...Name for log messages */ 387 /* ...Name for log messages */
388 rc = getnameinfo((sSA *)&primary, sSAlen(&primary), cnx->cc_remid, sizeof(cnx->cc_remid), NULL, 0, 0); 388 rc = getnameinfo((sSA *)&primary, sSAlen(&primary), cnx->cc_remid, sizeof(cnx->cc_remid), NULL, 0, 0);
389 if (rc) 389 if (rc)
390 snprintf(cnx->cc_remid, sizeof(cnx->cc_remid), "[err:%s]", gai_strerror(rc)); 390 snprintf(cnx->cc_remid, sizeof(cnx->cc_remid), "[err:%s]", gai_strerror(rc));
391 } 391 }
392 392
393 LOG_A("SCTP connection to %s succeed (socket:%d, %d/%d streams).", sa_buf, sock, cnx->cc_sctp_para.str_in, cnx->cc_sctp_para.str_out); 393 LOG_A("SCTP connection to %s succeed (socket:%d, %d/%d streams).", sa_buf, sock, cnx->cc_sctp_para.str_in, cnx->cc_sctp_para.str_out);
394 394
395 return cnx; 395 return cnx;
396 396
397 error: 397 error:
398 fd_cnx_destroy(cnx); 398 fd_cnx_destroy(cnx);
399 return NULL; 399 return NULL;
442 void fd_cnx_update_id(struct cnxctx * conn) { 442 void fd_cnx_update_id(struct cnxctx * conn) {
443 if (conn->cc_state & CC_STATUS_CLOSING) 443 if (conn->cc_state & CC_STATUS_CLOSING)
444 conn->cc_id[1] = 'C'; 444 conn->cc_id[1] = 'C';
445 else 445 else
446 conn->cc_id[1] = '-'; 446 conn->cc_id[1] = '-';
447 447
448 if (conn->cc_state & CC_STATUS_ERROR) 448 if (conn->cc_state & CC_STATUS_ERROR)
449 conn->cc_id[2] = 'E'; 449 conn->cc_id[2] = 'E';
450 else 450 else
451 conn->cc_id[2] = '-'; 451 conn->cc_id[2] = '-';
452 452
453 if (conn->cc_state & CC_STATUS_SIGNALED) 453 if (conn->cc_state & CC_STATUS_SIGNALED)
454 conn->cc_id[3] = 'S'; 454 conn->cc_id[3] = 'S';
455 else 455 else
456 conn->cc_id[3] = '-'; 456 conn->cc_id[3] = '-';
457 457
458 if (conn->cc_state & CC_STATUS_TLS) 458 if (conn->cc_state & CC_STATUS_TLS)
459 conn->cc_id[4] = 'T'; 459 conn->cc_id[4] = 'T';
460 else 460 else
461 conn->cc_id[4] = '-'; 461 conn->cc_id[4] = '-';
462 } 462 }
506 /* Get the list of endpoints (IP addresses) of the local and remote peers on this connection */ 506 /* Get the list of endpoints (IP addresses) of the local and remote peers on this connection */
507 int fd_cnx_getremoteeps(struct cnxctx * conn, struct fd_list * eps) 507 int fd_cnx_getremoteeps(struct cnxctx * conn, struct fd_list * eps)
508 { 508 {
509 TRACE_ENTRY("%p %p", conn, eps); 509 TRACE_ENTRY("%p %p", conn, eps);
510 CHECK_PARAMS(conn && eps); 510 CHECK_PARAMS(conn && eps);
511 511
512 /* Check we have a full connection object, not a listening socket (with no remote) */ 512 /* Check we have a full connection object, not a listening socket (with no remote) */
513 CHECK_PARAMS( conn->cc_incoming ); 513 CHECK_PARAMS( conn->cc_incoming );
514 514
515 /* Retrieve the peer endpoint(s) of the connection */ 515 /* Retrieve the peer endpoint(s) of the connection */
516 switch (conn->cc_proto) { 516 switch (conn->cc_proto) {
544 } 544 }
545 545
546 static int fd_cnx_may_dtls(struct cnxctx * conn); 546 static int fd_cnx_may_dtls(struct cnxctx * conn);
547 547
548 /* Get a short string representing the connection */ 548 /* Get a short string representing the connection */
549 int fd_cnx_proto_info(struct cnxctx * conn, char * buf, size_t len) 549 int fd_cnx_proto_info(struct cnxctx * conn, char * buf, size_t len)
550 { 550 {
551 CHECK_PARAMS( conn ); 551 CHECK_PARAMS( conn );
552 552
553 if (fd_cnx_teststate(conn, CC_STATUS_TLS)) { 553 if (fd_cnx_teststate(conn, CC_STATUS_TLS)) {
554 snprintf(buf, len, "%s,%s,soc#%d", IPPROTO_NAME(conn->cc_proto), fd_cnx_may_dtls(conn) ? "DTLS" : "TLS", conn->cc_socket); 554 snprintf(buf, len, "%s,%s,soc#%d", IPPROTO_NAME(conn->cc_proto), fd_cnx_may_dtls(conn) ? "DTLS" : "TLS", conn->cc_socket);
555 } else { 555 } else {
556 snprintf(buf, len, "%s,soc#%d", IPPROTO_NAME(conn->cc_proto), conn->cc_socket); 556 snprintf(buf, len, "%s,soc#%d", IPPROTO_NAME(conn->cc_proto), conn->cc_socket);
557 } 557 }
558 558
559 return 0; 559 return 0;
560 } 560 }
561 561
562 /* Retrieve a list of all IP addresses of the local system from the kernel, using getifaddrs */ 562 /* Retrieve a list of all IP addresses of the local system from the kernel, using getifaddrs */
563 int fd_cnx_get_local_eps(struct fd_list * list) 563 int fd_cnx_get_local_eps(struct fd_list * list)
564 { 564 {
565 struct ifaddrs *iflist, *cur; 565 struct ifaddrs *iflist, *cur;
566 566
567 CHECK_SYS(getifaddrs(&iflist)); 567 CHECK_SYS(getifaddrs(&iflist));
568 568
569 for (cur = iflist; cur != NULL; cur = cur->ifa_next) { 569 for (cur = iflist; cur != NULL; cur = cur->ifa_next) {
570 if (cur->ifa_flags & IFF_LOOPBACK) 570 if (cur->ifa_flags & IFF_LOOPBACK)
571 continue; 571 continue;
572 572
573 if (cur->ifa_addr == NULL) /* may happen with ppp interfaces */ 573 if (cur->ifa_addr == NULL) /* may happen with ppp interfaces */
574 continue; 574 continue;
575 575
576 if (fd_g_config->cnf_flags.no_ip4 && (cur->ifa_addr->sa_family == AF_INET)) 576 if (fd_g_config->cnf_flags.no_ip4 && (cur->ifa_addr->sa_family == AF_INET))
577 continue; 577 continue;
578 578
579 if (fd_g_config->cnf_flags.no_ip6 && (cur->ifa_addr->sa_family == AF_INET6)) 579 if (fd_g_config->cnf_flags.no_ip6 && (cur->ifa_addr->sa_family == AF_INET6))
580 continue; 580 continue;
581 581
582 CHECK_FCT(fd_ep_add_merge( list, cur->ifa_addr, sSAlen(cur->ifa_addr), EP_FL_LL )); 582 CHECK_FCT(fd_ep_add_merge( list, cur->ifa_addr, sSAlen(cur->ifa_addr), EP_FL_LL ));
583 } 583 }
584 584
585 freeifaddrs(iflist); 585 freeifaddrs(iflist);
586 586
587 return 0; 587 return 0;
588 } 588 }
589 589
590 590
591 /**************************************/ 591 /**************************************/
595 /* An error occurred on the socket */ 595 /* An error occurred on the socket */
596 void fd_cnx_markerror(struct cnxctx * conn) 596 void fd_cnx_markerror(struct cnxctx * conn)
597 { 597 {
598 TRACE_ENTRY("%p", conn); 598 TRACE_ENTRY("%p", conn);
599 CHECK_PARAMS_DO( conn, goto fatal ); 599 CHECK_PARAMS_DO( conn, goto fatal );
600 600
601 TRACE_DEBUG(FULL, "Error flag set for socket %d (%s, %s)", conn->cc_socket, conn->cc_id, conn->cc_remid); 601 TRACE_DEBUG(FULL, "Error flag set for socket %d (%s, %s)", conn->cc_socket, conn->cc_id, conn->cc_remid);
602 602
603 /* Mark the error */ 603 /* Mark the error */
604 fd_cnx_addstate(conn, CC_STATUS_ERROR); 604 fd_cnx_addstate(conn, CC_STATUS_ERROR);
605 605
606 /* Report the error if not reported yet, and not closing */ 606 /* Report the error if not reported yet, and not closing */
607 if (!fd_cnx_teststate(conn, CC_STATUS_CLOSING | CC_STATUS_SIGNALED )) { 607 if (!fd_cnx_teststate(conn, CC_STATUS_CLOSING | CC_STATUS_SIGNALED )) {
608 TRACE_DEBUG(FULL, "Sending FDEVP_CNX_ERROR event"); 608 TRACE_DEBUG(FULL, "Sending FDEVP_CNX_ERROR event");
609 CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_ERROR, 0, NULL), goto fatal); 609 CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_ERROR, 0, NULL), goto fatal);
610 fd_cnx_addstate(conn, CC_STATUS_SIGNALED); 610 fd_cnx_addstate(conn, CC_STATUS_SIGNALED);
611 } 611 }
612 612
613 return; 613 return;
614 fatal: 614 fatal:
615 /* An unrecoverable error occurred, stop the daemon */ 615 /* An unrecoverable error occurred, stop the daemon */
616 ASSERT(0); 616 ASSERT(0);
617 CHECK_FCT_DO(fd_core_shutdown(), ); 617 CHECK_FCT_DO(fd_core_shutdown(), );
618 } 618 }
619 619
620 /* Set the timeout option on the socket */ 620 /* Set the timeout option on the socket */
621 void fd_cnx_s_setto(int sock) 621 void fd_cnx_s_setto(int sock)
622 { 622 {
623 struct timeval tv; 623 struct timeval tv;
624 624
625 /* Set a timeout on the socket so that in any case we are not stuck waiting for something */ 625 /* Set a timeout on the socket so that in any case we are not stuck waiting for something */
626 memset(&tv, 0, sizeof(tv)); 626 memset(&tv, 0, sizeof(tv));
627 tv.tv_usec = 100000L; /* 100ms, to react quickly to head-of-the-line blocking. */ 627 tv.tv_usec = 100000L; /* 100ms, to react quickly to head-of-the-line blocking. */
628 CHECK_SYS_DO( setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)), ); 628 CHECK_SYS_DO( setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)), );
629 CHECK_SYS_DO( setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)), ); 629 CHECK_SYS_DO( setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)), );
634 /* The pull_timeout function for gnutls */ 634 /* The pull_timeout function for gnutls */
635 static int fd_cnx_s_select (struct cnxctx * conn, unsigned int ms) 635 static int fd_cnx_s_select (struct cnxctx * conn, unsigned int ms)
636 { 636 {
637 fd_set rfds; 637 fd_set rfds;
638 struct timeval tv; 638 struct timeval tv;
639 639
640 FD_ZERO (&rfds); 640 FD_ZERO (&rfds);
641 FD_SET (conn->cc_socket, &rfds); 641 FD_SET (conn->cc_socket, &rfds);
642 642
643 tv.tv_sec = ms / 1000; 643 tv.tv_sec = ms / 1000;
644 tv.tv_usec = (ms * 1000) % 1000000; 644 tv.tv_usec = (ms * 1000) % 1000000;
645 645
646 return select (conn->cc_socket + 1, &rfds, NULL, NULL, &tv); 646 return select (conn->cc_socket + 1, &rfds, NULL, NULL, &tv);
647 } 647 }
648 #endif /* GNUTLS_VERSION_300 */ 648 #endif /* GNUTLS_VERSION_300 */
649 649
650 /* A recv-like function, taking a cnxctx object instead of socket as entry. We use it to quickly react to timeouts without traversing GNUTLS wrapper each time */ 650 /* A recv-like function, taking a cnxctx object instead of socket as entry. We use it to quickly react to timeouts without traversing GNUTLS wrapper each time */
651 ssize_t fd_cnx_s_recv(struct cnxctx * conn, void *buffer, size_t length) 651 ssize_t fd_cnx_s_recv(struct cnxctx * conn, void *buffer, size_t length)
652 { 652 {
662 if (!timedout) { 662 if (!timedout) {
663 timedout ++; /* allow for one timeout while closing */ 663 timedout ++; /* allow for one timeout while closing */
664 goto again; 664 goto again;
665 } 665 }
666 } 666 }
667 667
668 /* Mark the error */ 668 /* Mark the error */
669 if (ret <= 0) { 669 if (ret <= 0) {
670 CHECK_SYS_DO(ret, /* continue, this is only used to log the error here */); 670 CHECK_SYS_DO(ret, /* continue, this is only used to log the error here */);
671 fd_cnx_markerror(conn); 671 fd_cnx_markerror(conn);
672 } 672 }
673 673
674 return ret; 674 return ret;
675 } 675 }
676 676
677 /* Send */ 677 /* Send */
678 static ssize_t fd_cnx_s_sendv(struct cnxctx * conn, const struct iovec * iov, int iovcnt) 678 static ssize_t fd_cnx_s_sendv(struct cnxctx * conn, const struct iovec * iov, int iovcnt)
684 ret = writev(conn->cc_socket, iov, iovcnt); 684 ret = writev(conn->cc_socket, iov, iovcnt);
685 /* Handle special case of timeout */ 685 /* Handle special case of timeout */
686 if ((ret < 0) && ((errno == EAGAIN) || (errno == EINTR))) { 686 if ((ret < 0) && ((errno == EAGAIN) || (errno == EINTR))) {
687 ret = -errno; 687 ret = -errno;
688 pthread_testcancel(); 688 pthread_testcancel();
689 689
690 /* Check how much time we were blocked for this sending. */ 690 /* Check how much time we were blocked for this sending. */
691 CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &now), return -1 ); 691 CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &now), return -1 );
692 if ( ((now.tv_sec - ts.tv_sec) * 1000 + ((now.tv_nsec - ts.tv_nsec) / 1000000L)) > MAX_HOTL_BLOCKING_TIME) { 692 if ( ((now.tv_sec - ts.tv_sec) * 1000 + ((now.tv_nsec - ts.tv_nsec) / 1000000L)) > MAX_HOTL_BLOCKING_TIME) {
693 LOG_D("Unable to send any data for %dms, closing the connection", MAX_HOTL_BLOCKING_TIME); 693 LOG_D("Unable to send any data for %dms, closing the connection", MAX_HOTL_BLOCKING_TIME);
694 } else if (! fd_cnx_teststate(conn, CC_STATUS_CLOSING )) { 694 } else if (! fd_cnx_teststate(conn, CC_STATUS_CLOSING )) {
695 goto again; /* don't care, just ignore */ 695 goto again; /* don't care, just ignore */
696 } 696 }
697 697
698 /* propagate the error */ 698 /* propagate the error */
699 errno = -ret; 699 errno = -ret;
700 ret = -1; 700 ret = -1;
701 CHECK_SYS_DO(ret, /* continue */); 701 CHECK_SYS_DO(ret, /* continue */);
702 } 702 }
703 703
704 /* Mark the error */ 704 /* Mark the error */
705 if (ret <= 0) 705 if (ret <= 0)
706 fd_cnx_markerror(conn); 706 fd_cnx_markerror(conn);
707 707
708 return ret; 708 return ret;
709 } 709 }
710 710
711 /* Send, for older GNUTLS */ 711 /* Send, for older GNUTLS */
712 #ifndef GNUTLS_VERSION_212 712 #ifndef GNUTLS_VERSION_212
728 } 728 }
729 729
730 struct fd_msg_pmdl * fd_msg_pmdl_get_inbuf(uint8_t * buf, size_t datalen) 730 struct fd_msg_pmdl * fd_msg_pmdl_get_inbuf(uint8_t * buf, size_t datalen)
731 { 731 {
732 return (struct fd_msg_pmdl *)(buf + PMDL_PADDED(datalen)); 732 return (struct fd_msg_pmdl *)(buf + PMDL_PADDED(datalen));
733 } 733 }
734 734
735 static int fd_cnx_init_msg_buffer(uint8_t * buffer, size_t expected_len, struct fd_msg_pmdl ** pmdl) 735 static int fd_cnx_init_msg_buffer(uint8_t * buffer, size_t expected_len, struct fd_msg_pmdl ** pmdl)
736 { 736 {
737 *pmdl = fd_msg_pmdl_get_inbuf(buffer, expected_len); 737 *pmdl = fd_msg_pmdl_get_inbuf(buffer, expected_len);
738 fd_list_init(&(*pmdl)->sentinel, NULL); 738 fd_list_init(&(*pmdl)->sentinel, NULL);
741 } 741 }
742 742
743 static uint8_t * fd_cnx_alloc_msg_buffer(size_t expected_len, struct fd_msg_pmdl ** pmdl) 743 static uint8_t * fd_cnx_alloc_msg_buffer(size_t expected_len, struct fd_msg_pmdl ** pmdl)
744 { 744 {
745 uint8_t * ret = NULL; 745 uint8_t * ret = NULL;
746 746
747 CHECK_MALLOC_DO( ret = malloc( fd_msg_pmdl_sizewithoverhead(expected_len) ), return NULL ); 747 CHECK_MALLOC_DO( ret = malloc( fd_msg_pmdl_sizewithoverhead(expected_len) ), return NULL );
748 CHECK_FCT_DO( fd_cnx_init_msg_buffer(ret, expected_len, pmdl), {free(ret); return NULL;} ); 748 CHECK_FCT_DO( fd_cnx_init_msg_buffer(ret, expected_len, pmdl), {free(ret); return NULL;} );
749 return ret; 749 return ret;
750 } 750 }
751 751
752 #ifndef DISABLE_SCTP /* WE use this function only in SCTP code */ 752 #ifndef DISABLE_SCTP /* WE use this function only in SCTP code */
753 static uint8_t * fd_cnx_realloc_msg_buffer(uint8_t * buffer, size_t expected_len, struct fd_msg_pmdl ** pmdl) 753 static uint8_t * fd_cnx_realloc_msg_buffer(uint8_t * buffer, size_t expected_len, struct fd_msg_pmdl ** pmdl)
754 { 754 {
755 uint8_t * ret = NULL; 755 uint8_t * ret = NULL;
756 756
757 CHECK_MALLOC_DO( ret = realloc( buffer, fd_msg_pmdl_sizewithoverhead(expected_len) ), return NULL ); 757 CHECK_MALLOC_DO( ret = realloc( buffer, fd_msg_pmdl_sizewithoverhead(expected_len) ), return NULL );
758 CHECK_FCT_DO( fd_cnx_init_msg_buffer(ret, expected_len, pmdl), {free(ret); return NULL;} ); 758 CHECK_FCT_DO( fd_cnx_init_msg_buffer(ret, expected_len, pmdl), {free(ret); return NULL;} );
759 return ret; 759 return ret;
760 } 760 }
761 #endif /* DISABLE_SCTP */ 761 #endif /* DISABLE_SCTP */
762 762
763 static void free_rcvdata(void * arg) 763 static void free_rcvdata(void * arg)
764 { 764 {
765 struct fd_cnx_rcvdata * data = arg; 765 struct fd_cnx_rcvdata * data = arg;
766 struct fd_msg_pmdl * pmdl = fd_msg_pmdl_get_inbuf(data->buffer, data->length); 766 struct fd_msg_pmdl * pmdl = fd_msg_pmdl_get_inbuf(data->buffer, data->length);
767 (void) pthread_mutex_destroy(&pmdl->lock); 767 (void) pthread_mutex_destroy(&pmdl->lock);
768 free(data->buffer); 768 free(data->buffer);
770 770
771 /* Receiver thread (TCP & noTLS) : incoming message is directly saved into the target queue */ 771 /* Receiver thread (TCP & noTLS) : incoming message is directly saved into the target queue */
772 static void * rcvthr_notls_tcp(void * arg) 772 static void * rcvthr_notls_tcp(void * arg)
773 { 773 {
774 struct cnxctx * conn = arg; 774 struct cnxctx * conn = arg;
775 775
776 TRACE_ENTRY("%p", arg); 776 TRACE_ENTRY("%p", arg);
777 CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), goto out); 777 CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), goto out);
778 778
779 /* Set the thread name */ 779 /* Set the thread name */
780 { 780 {
781 char buf[48]; 781 char buf[48];
782 snprintf(buf, sizeof(buf), "Receiver (%d) TCP/noTLS)", conn->cc_socket); 782 snprintf(buf, sizeof(buf), "Receiver (%d) TCP/noTLS)", conn->cc_socket);
783 fd_log_threadname ( buf ); 783 fd_log_threadname ( buf );
784 } 784 }
785 785
786 ASSERT( conn->cc_proto == IPPROTO_TCP ); 786 ASSERT( conn->cc_proto == IPPROTO_TCP );
787 ASSERT( ! fd_cnx_teststate(conn, CC_STATUS_TLS ) ); 787 ASSERT( ! fd_cnx_teststate(conn, CC_STATUS_TLS ) );
788 ASSERT( fd_cnx_target_queue(conn) ); 788 ASSERT( fd_cnx_target_queue(conn) );
789 789
790 /* Receive from a TCP connection: we have to rebuild the message boundaries */ 790 /* Receive from a TCP connection: we have to rebuild the message boundaries */
791 do { 791 do {
792 uint8_t header[4]; 792 uint8_t header[4];
793 struct fd_cnx_rcvdata rcv_data; 793 struct fd_cnx_rcvdata rcv_data;
794 struct fd_msg_pmdl *pmdl=NULL; 794 struct fd_msg_pmdl *pmdl=NULL;
800 if (ret <= 0) { 800 if (ret <= 0) {
801 goto out; /* Stop the thread, the event was already sent */ 801 goto out; /* Stop the thread, the event was already sent */
802 } 802 }
803 803
804 received += ret; 804 received += ret;
805 805
806 if (header[0] != DIAMETER_VERSION) 806 if (header[0] != DIAMETER_VERSION)
807 break; /* No need to wait for 4 bytes in this case */ 807 break; /* No need to wait for 4 bytes in this case */
808 } while (received < sizeof(header)); 808 } while (received < sizeof(header));
809 809
810 rcv_data.length = ((size_t)header[1] << 16) + ((size_t)header[2] << 8) + (size_t)header[3]; 810 rcv_data.length = ((size_t)header[1] << 16) + ((size_t)header[2] << 8) + (size_t)header[3];
831 free_rcvdata(&rcv_data); 831 free_rcvdata(&rcv_data);
832 goto out; 832 goto out;
833 } 833 }
834 received += ret; 834 received += ret;
835 } 835 }
836 836
837 fd_hook_call(HOOK_DATA_RECEIVED, NULL, NULL, &rcv_data, pmdl); 837 fd_hook_call(HOOK_DATA_RECEIVED, NULL, NULL, &rcv_data, pmdl);
838 838
839 /* We have received a complete message, pass it to the daemon */ 839 /* We have received a complete message, pass it to the daemon */
840 CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_MSG_RECV, rcv_data.length, rcv_data.buffer), 840 CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_MSG_RECV, rcv_data.length, rcv_data.buffer),
841 { 841 {
842 free_rcvdata(&rcv_data); 842 free_rcvdata(&rcv_data);
843 goto fatal; 843 goto fatal;
844 } ); 844 } );
845 845
846 } while (conn->cc_loop); 846 } while (conn->cc_loop);
847 847
848 out: 848 out:
849 TRACE_DEBUG(FULL, "Thread terminated"); 849 TRACE_DEBUG(FULL, "Thread terminated");
850 return NULL; 850 return NULL;
851 851
852 fatal: 852 fatal:
853 /* An unrecoverable error occurred, stop the daemon */ 853 /* An unrecoverable error occurred, stop the daemon */
854 CHECK_FCT_DO(fd_core_shutdown(), ); 854 CHECK_FCT_DO(fd_core_shutdown(), );
855 goto out; 855 goto out;
856 } 856 }
860 static void * rcvthr_notls_sctp(void * arg) 860 static void * rcvthr_notls_sctp(void * arg)
861 { 861 {
862 struct cnxctx * conn = arg; 862 struct cnxctx * conn = arg;
863 struct fd_cnx_rcvdata rcv_data; 863 struct fd_cnx_rcvdata rcv_data;
864 int event; 864 int event;
865 865
866 TRACE_ENTRY("%p", arg); 866 TRACE_ENTRY("%p", arg);
867 CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), goto fatal); 867 CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), goto fatal);
868 868
869 /* Set the thread name */ 869 /* Set the thread name */
870 { 870 {
871 char buf[48]; 871 char buf[48];
872 snprintf(buf, sizeof(buf), "Receiver (%d) SCTP/noTLS)", conn->cc_socket); 872 snprintf(buf, sizeof(buf), "Receiver (%d) SCTP/noTLS)", conn->cc_socket);
873 fd_log_threadname ( buf ); 873 fd_log_threadname ( buf );
874 } 874 }
875 875
876 ASSERT( conn->cc_proto == IPPROTO_SCTP ); 876 ASSERT( conn->cc_proto == IPPROTO_SCTP );
877 ASSERT( ! fd_cnx_teststate(conn, CC_STATUS_TLS ) ); 877 ASSERT( ! fd_cnx_teststate(conn, CC_STATUS_TLS ) );
878 ASSERT( fd_cnx_target_queue(conn) ); 878 ASSERT( fd_cnx_target_queue(conn) );
879 879
880 do { 880 do {
881 struct fd_msg_pmdl *pmdl=NULL; 881 struct fd_msg_pmdl *pmdl=NULL;
882 CHECK_FCT_DO( fd_sctp_recvmeta(conn, NULL, &rcv_data.buffer, &rcv_data.length, &event), goto fatal ); 882 CHECK_FCT_DO( fd_sctp_recvmeta(conn, NULL, &rcv_data.buffer, &rcv_data.length, &event), goto fatal );
883 if (event == FDEVP_CNX_ERROR) { 883 if (event == FDEVP_CNX_ERROR) {
884 fd_cnx_markerror(conn); 884 fd_cnx_markerror(conn);
885 goto out; 885 goto out;
886 } 886 }
887 887
888 if (event == FDEVP_CNX_SHUTDOWN) { 888 if (event == FDEVP_CNX_SHUTDOWN) {
889 /* Just ignore the notification for now, we will get another error later anyway */ 889 /* Just ignore the notification for now, we will get another error later anyway */
890 continue; 890 continue;
891 } 891 }
892 892
893 if (event == FDEVP_CNX_MSG_RECV) { 893 if (event == FDEVP_CNX_MSG_RECV) {
894 CHECK_MALLOC_DO( rcv_data.buffer = fd_cnx_realloc_msg_buffer(rcv_data.buffer, rcv_data.length, &pmdl), goto fatal ); 894 CHECK_MALLOC_DO( rcv_data.buffer = fd_cnx_realloc_msg_buffer(rcv_data.buffer, rcv_data.length, &pmdl), goto fatal );
895 fd_hook_call(HOOK_DATA_RECEIVED, NULL, NULL, &rcv_data, pmdl); 895 fd_hook_call(HOOK_DATA_RECEIVED, NULL, NULL, &rcv_data, pmdl);
896 } 896 }
897 CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), event, rcv_data.length, rcv_data.buffer), goto fatal ); 897 CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), event, rcv_data.length, rcv_data.buffer), goto fatal );
898 898
899 } while (conn->cc_loop || (event != FDEVP_CNX_MSG_RECV)); 899 } while (conn->cc_loop || (event != FDEVP_CNX_MSG_RECV));
900 900
901 out: 901 out:
902 TRACE_DEBUG(FULL, "Thread terminated"); 902 TRACE_DEBUG(FULL, "Thread terminated");
903 return NULL; 903 return NULL;
904 904
905 fatal: 905 fatal:
906 /* An unrecoverable error occurred, stop the daemon */ 906 /* An unrecoverable error occurred, stop the daemon */
907 CHECK_FCT_DO(fd_core_shutdown(), ); 907 CHECK_FCT_DO(fd_core_shutdown(), );
911 911
912 /* Start receving messages in clear (no TLS) on the connection */ 912 /* Start receving messages in clear (no TLS) on the connection */
913 int fd_cnx_start_clear(struct cnxctx * conn, int loop) 913 int fd_cnx_start_clear(struct cnxctx * conn, int loop)
914 { 914 {
915 TRACE_ENTRY("%p %i", conn, loop); 915 TRACE_ENTRY("%p %i", conn, loop);
916 916
917 CHECK_PARAMS( conn && fd_cnx_target_queue(conn) && (!fd_cnx_teststate(conn, CC_STATUS_TLS)) && (!conn->cc_loop)); 917 CHECK_PARAMS( conn && fd_cnx_target_queue(conn) && (!fd_cnx_teststate(conn, CC_STATUS_TLS)) && (!conn->cc_loop));
918 918
919 /* Release resources in case of a previous call was already made */ 919 /* Release resources in case of a previous call was already made */
920 CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */); 920 CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */);
921 921
922 /* Save the loop request */ 922 /* Save the loop request */
923 conn->cc_loop = loop; 923 conn->cc_loop = loop;
924 924
925 switch (conn->cc_proto) { 925 switch (conn->cc_proto) {
926 case IPPROTO_TCP: 926 case IPPROTO_TCP:
927 /* Start the tcp_notls thread */ 927 /* Start the tcp_notls thread */
928 CHECK_POSIX( pthread_create( &conn->cc_rcvthr, NULL, rcvthr_notls_tcp, conn ) ); 928 CHECK_POSIX( pthread_create( &conn->cc_rcvthr, NULL, rcvthr_notls_tcp, conn ) );
929 break; 929 break;
936 default: 936 default:
937 TRACE_DEBUG(INFO, "Unknown protocol: %d", conn->cc_proto); 937 TRACE_DEBUG(INFO, "Unknown protocol: %d", conn->cc_proto);
938 ASSERT(0); 938 ASSERT(0);
939 return ENOTSUP; 939 return ENOTSUP;
940 } 940 }
941 941
942 return 0; 942 return 0;
943 } 943 }
944 944
945 945
946 946
947 947
948 /* Returns 0 on error, received data size otherwise (always >= 0). This is not used for DTLS-protected associations. */ 948 /* Returns 0 on error, received data size otherwise (always >= 0). This is not used for DTLS-protected associations. */
949 static ssize_t fd_tls_recv_handle_error(struct cnxctx * conn, gnutls_session_t session, void * data, size_t sz) 949 static ssize_t fd_tls_recv_handle_error(struct cnxctx * conn, gnutls_session_t session, void * data, size_t sz)
950 { 950 {
951 ssize_t ret; 951 ssize_t ret;
952 again: 952 again:
953 CHECK_GNUTLS_DO( ret = gnutls_record_recv(session, data, sz), 953 CHECK_GNUTLS_DO( ret = gnutls_record_recv(session, data, sz),
954 { 954 {
955 switch (ret) { 955 switch (ret) {
956 case GNUTLS_E_REHANDSHAKE: 956 case GNUTLS_E_REHANDSHAKE:
957 if (!fd_cnx_teststate(conn, CC_STATUS_CLOSING)) { 957 if (!fd_cnx_teststate(conn, CC_STATUS_CLOSING)) {
958 CHECK_GNUTLS_DO( ret = gnutls_handshake(session), 958 CHECK_GNUTLS_DO( ret = gnutls_handshake(session),
959 { 959 {
960 if (TRACE_BOOL(INFO)) { 960 if (TRACE_BOOL(INFO)) {
961 fd_log_debug("TLS re-handshake failed on socket %d (%s) : %s", conn->cc_socket, conn->cc_id, gnutls_strerror(ret)); 961 fd_log_debug("TLS re-handshake failed on socket %d (%s) : %s", conn->cc_socket, conn->cc_id, gnutls_strerror(ret));
973 973
974 case GNUTLS_E_UNEXPECTED_PACKET_LENGTH: 974 case GNUTLS_E_UNEXPECTED_PACKET_LENGTH:
975 /* The connection is closed */ 975 /* The connection is closed */
976 TRACE_DEBUG(FULL, "Got 0 size while reading the socket, probably connection closed..."); 976 TRACE_DEBUG(FULL, "Got 0 size while reading the socket, probably connection closed...");
977 break; 977 break;
978 978
979 default: 979 default:
980 if (gnutls_error_is_fatal (ret) == 0) { 980 if (gnutls_error_is_fatal (ret) == 0) {
981 LOG_N("Ignoring non-fatal GNU TLS error: %s", gnutls_strerror (ret)); 981 LOG_N("Ignoring non-fatal GNU TLS error: %s", gnutls_strerror (ret));
982 goto again; 982 goto again;
983 } 983 }
984 LOG_E("Fatal GNUTLS error: %s", gnutls_strerror (ret)); 984 LOG_E("Fatal GNUTLS error: %s", gnutls_strerror (ret));
985 } 985 }
986 } ); 986 } );
987 987
988 if (ret == 0) 988 if (ret == 0)
989 CHECK_GNUTLS_DO( gnutls_bye(session, GNUTLS_SHUT_RDWR), ); 989 CHECK_GNUTLS_DO( gnutls_bye(session, GNUTLS_SHUT_RDWR), );
990 990
991 end: 991 end:
992 if (ret <= 0) 992 if (ret <= 0)
993 fd_cnx_markerror(conn); 993 fd_cnx_markerror(conn);
994 return ret; 994 return ret;
995 } 995 }
996 996
998 static ssize_t fd_tls_send_handle_error(struct cnxctx * conn, gnutls_session_t session, void * data, size_t sz) 998 static ssize_t fd_tls_send_handle_error(struct cnxctx * conn, gnutls_session_t session, void * data, size_t sz)
999 { 999 {
1000 ssize_t ret; 1000 ssize_t ret;
1001 struct timespec ts, now; 1001 struct timespec ts, now;
1002 CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &ts), return -1 ); 1002 CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &ts), return -1 );
1003 again: 1003 again:
1004 CHECK_GNUTLS_DO( ret = gnutls_record_send(session, data, sz), 1004 CHECK_GNUTLS_DO( ret = gnutls_record_send(session, data, sz),
1005 { 1005 {
1006 pthread_testcancel(); 1006 pthread_testcancel();
1007 switch (ret) { 1007 switch (ret) {
1008 case GNUTLS_E_REHANDSHAKE: 1008 case GNUTLS_E_REHANDSHAKE:
1009 if (!fd_cnx_teststate(conn, CC_STATUS_CLOSING)) { 1009 if (!fd_cnx_teststate(conn, CC_STATUS_CLOSING)) {
1010 CHECK_GNUTLS_DO( ret = gnutls_handshake(session), 1010 CHECK_GNUTLS_DO( ret = gnutls_handshake(session),
1011 { 1011 {
1012 if (TRACE_BOOL(INFO)) { 1012 if (TRACE_BOOL(INFO)) {
1013 fd_log_debug("TLS re-handshake failed on socket %d (%s) : %s", conn->cc_socket, conn->cc_id, gnutls_strerror(ret)); 1013 fd_log_debug("TLS re-handshake failed on socket %d (%s) : %s", conn->cc_socket, conn->cc_id, gnutls_strerror(ret));
1032 goto again; 1032 goto again;
1033 } 1033 }
1034 LOG_E("Fatal GNUTLS error: %s", gnutls_strerror (ret)); 1034 LOG_E("Fatal GNUTLS error: %s", gnutls_strerror (ret));
1035 } 1035 }
1036 } ); 1036 } );
1037 end: 1037 end:
1038 if (ret <= 0) 1038 if (ret <= 0)
1039 fd_cnx_markerror(conn); 1039 fd_cnx_markerror(conn);
1040 1040
1041 return ret; 1041 return ret;
1042 } 1042 }
1043 1043
1044 1044
1045 /* The function that receives TLS data and re-builds a Diameter message -- it exits only on error or cancelation */ 1045 /* The function that receives TLS data and re-builds a Diameter message -- it exits only on error or cancelation */
1046 /* For the case of DTLS, since we are not using SCTP_UNORDERED, the messages over a single stream are ordered. 1046 /* For the case of DTLS, since we are not using SCTP_UNORDERED, the messages over a single stream are ordered.
1047 Furthermore, as long as messages are shorter than the MTU [2^14 = 16384 bytes], they are delivered in a single 1047 Furthermore, as long as messages are shorter than the MTU [2^14 = 16384 bytes], they are delivered in a single
1048 record, as far as I understand. 1048 record, as far as I understand.
1049 For larger messages, however, it is possible that pieces of messages coming from different streams can get interleaved. 1049 For larger messages, however, it is possible that pieces of messages coming from different streams can get interleaved.
1050 As a result, we do not use the following function for DTLS reception, because we use the sequence number to rebuild the 1050 As a result, we do not use the following function for DTLS reception, because we use the sequence number to rebuild the
1051 messages. */ 1051 messages. */
1052 int fd_tls_rcvthr_core(struct cnxctx * conn, gnutls_session_t session) 1052 int fd_tls_rcvthr_core(struct cnxctx * conn, gnutls_session_t session)
1053 { 1053 {
1054 ssize_t ret = 0; 1054 ssize_t ret = 0;
1093 free_rcvdata(&rcv_data); 1093 free_rcvdata(&rcv_data);
1094 goto out; 1094 goto out;
1095 } 1095 }
1096 received += ret; 1096 received += ret;
1097 } 1097 }
1098 1098
1099 fd_hook_call(HOOK_DATA_RECEIVED, NULL, NULL, &rcv_data, pmdl); 1099 fd_hook_call(HOOK_DATA_RECEIVED, NULL, NULL, &rcv_data, pmdl);
1100 1100
1101 /* We have received a complete message, pass it to the daemon */ 1101 /* We have received a complete message, pass it to the daemon */
1102 CHECK_FCT_DO( ret = fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_MSG_RECV, rcv_data.length, rcv_data.buffer), 1102 CHECK_FCT_DO( ret = fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_MSG_RECV, rcv_data.length, rcv_data.buffer),
1103 { 1103 {
1104 free_rcvdata(&rcv_data); 1104 free_rcvdata(&rcv_data);
1105 CHECK_FCT_DO(fd_core_shutdown(), ); 1105 CHECK_FCT_DO(fd_core_shutdown(), );
1106 return ret; 1106 return ret;
1107 } ); 1107 } );
1108 1108
1109 } while (1); 1109 } while (1);
1110 1110
1111 out: 1111 out:
1112 return (ret == 0) ? 0 : ENOTCONN; 1112 return (ret == 0) ? 0 : ENOTCONN;
1113 } 1113 }
1114 1114
1115 /* Receiver thread (TLS & 1 stream SCTP or TCP) */ 1115 /* Receiver thread (TLS & 1 stream SCTP or TCP) */
1116 static void * rcvthr_tls_single(void * arg) 1116 static void * rcvthr_tls_single(void * arg)
1117 { 1117 {
1118 struct cnxctx * conn = arg; 1118 struct cnxctx * conn = arg;
1119 1119
1120 TRACE_ENTRY("%p", arg); 1120 TRACE_ENTRY("%p", arg);
1121 CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), return NULL ); 1121 CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), return NULL );
1122 1122
1123 /* Set the thread name */ 1123 /* Set the thread name */
1124 { 1124 {
1125 char buf[48]; 1125 char buf[48];
1126 snprintf(buf, sizeof(buf), "Receiver (%d) TLS/single stream", conn->cc_socket); 1126 snprintf(buf, sizeof(buf), "Receiver (%d) TLS/single stream", conn->cc_socket);
1127 fd_log_threadname ( buf ); 1127 fd_log_threadname ( buf );
1128 } 1128 }
1129 1129
1130 ASSERT( fd_cnx_teststate(conn, CC_STATUS_TLS) ); 1130 ASSERT( fd_cnx_teststate(conn, CC_STATUS_TLS) );
1131 ASSERT( fd_cnx_target_queue(conn) ); 1131 ASSERT( fd_cnx_target_queue(conn) );
1132 1132
1133 /* The next function only returns when there is an error on the socket */ 1133 /* The next function only returns when there is an error on the socket */
1134 CHECK_FCT_DO(fd_tls_rcvthr_core(conn, conn->cc_tls_para.session), /* continue */); 1134 CHECK_FCT_DO(fd_tls_rcvthr_core(conn, conn->cc_tls_para.session), /* continue */);
1135 1135
1136 TRACE_DEBUG(FULL, "Thread terminated"); 1136 TRACE_DEBUG(FULL, "Thread terminated");
1137 return NULL; 1137 return NULL;
1138 } 1138 }
1139 1139
1140 /* Prepare a gnutls session object for handshake */ 1140 /* Prepare a gnutls session object for handshake */
1141 int fd_tls_prepare(gnutls_session_t * session, int mode, int dtls, char * priority, void * alt_creds) 1141 int fd_tls_prepare(gnutls_session_t * session, int mode, int dtls, char * priority, void * alt_creds)
1149 CHECK_GNUTLS_DO( gnutls_init (session, mode), return ENOMEM ); 1149 CHECK_GNUTLS_DO( gnutls_init (session, mode), return ENOMEM );
1150 1150
1151 /* Set the algorithm suite */ 1151 /* Set the algorithm suite */
1152 if (priority) { 1152 if (priority) {
1153 const char * errorpos; 1153 const char * errorpos;
1154 CHECK_GNUTLS_DO( gnutls_priority_set_direct( *session, priority, &errorpos ), 1154 CHECK_GNUTLS_DO( gnutls_priority_set_direct( *session, priority, &errorpos ),
1155 { TRACE_DEBUG(INFO, "Error in priority string '%s' at position: '%s'", priority, errorpos); return EINVAL; } ); 1155 { TRACE_DEBUG(INFO, "Error in priority string '%s' at position: '%s'", priority, errorpos); return EINVAL; } );
1156 } else { 1156 } else {
1157 CHECK_GNUTLS_DO( gnutls_priority_set( *session, fd_g_config->cnf_sec_data.prio_cache ), return EINVAL ); 1157 CHECK_GNUTLS_DO( gnutls_priority_set( *session, fd_g_config->cnf_sec_data.prio_cache ), return EINVAL );
1158 } 1158 }
1159 1159
1162 1162
1163 /* Request the remote credentials as well */ 1163 /* Request the remote credentials as well */
1164 if (mode == GNUTLS_SERVER) { 1164 if (mode == GNUTLS_SERVER) {
1165 gnutls_certificate_server_set_request (*session, GNUTLS_CERT_REQUIRE); 1165 gnutls_certificate_server_set_request (*session, GNUTLS_CERT_REQUIRE);
1166 } 1166 }
1167 1167
1168 return 0; 1168 return 0;
1169 } 1169 }
1170 1170
1171 #ifndef GNUTLS_VERSION_300 1171 #ifndef GNUTLS_VERSION_300
1172 1172
1177 unsigned int gtret; 1177 unsigned int gtret;
1178 const gnutls_datum_t *cert_list; 1178 const gnutls_datum_t *cert_list;
1179 unsigned int cert_list_size; 1179 unsigned int cert_list_size;
1180 gnutls_x509_crt_t cert; 1180 gnutls_x509_crt_t cert;
1181 time_t now; 1181 time_t now;
1182 1182
1183 TRACE_ENTRY("%p %d", conn, verbose); 1183 TRACE_ENTRY("%p %d", conn, verbose);
1184 CHECK_PARAMS(conn); 1184 CHECK_PARAMS(conn);
1185 1185
1186 /* Trace the session information -- http://www.gnu.org/software/gnutls/manual/gnutls.html#Obtaining-session-information */ 1186 /* Trace the session information -- http://www.gnu.org/software/gnutls/manual/gnutls.html#Obtaining-session-information */
1187 #ifdef DEBUG 1187 #ifdef DEBUG
1188 if (verbose) { 1188 if (verbose) {
1189 const char *tmp; 1189 const char *tmp;
1190 gnutls_kx_algorithm_t kx; 1190 gnutls_kx_algorithm_t kx;
1191 gnutls_credentials_type_t cred; 1191 gnutls_credentials_type_t cred;
1192 1192
1193 LOG_D("TLS Session information for connection '%s':", conn->cc_id); 1193 LOG_D("TLS Session information for connection '%s':", conn->cc_id);
1194 1194
1195 /* print the key exchange's algorithm name */ 1195 /* print the key exchange's algorithm name */
1196 GNUTLS_TRACE( kx = gnutls_kx_get (session) ); 1196 GNUTLS_TRACE( kx = gnutls_kx_get (session) );
1197 GNUTLS_TRACE( tmp = gnutls_kx_get_name (kx) ); 1197 GNUTLS_TRACE( tmp = gnutls_kx_get_name (kx) );
1227 if (kx == GNUTLS_KX_DHE_RSA || kx == GNUTLS_KX_DHE_DSS) { 1227 if (kx == GNUTLS_KX_DHE_RSA || kx == GNUTLS_KX_DHE_DSS) {
1228 LOG_D("\t - Ephemeral DH using prime of %d bits", 1228 LOG_D("\t - Ephemeral DH using prime of %d bits",
1229 gnutls_dh_get_prime_bits (session)); 1229 gnutls_dh_get_prime_bits (session));
1230 } 1230 }
1231 break; 1231 break;
1232 #ifdef ENABLE_SRP 1232 #ifdef ENABLE_SRP
1233 case GNUTLS_CRD_SRP: 1233 case GNUTLS_CRD_SRP:
1234 LOG_D("\t - SRP session with username %s", 1234 LOG_D("\t - SRP session with username %s",
1235 gnutls_srp_server_get_username (session)); 1235 gnutls_srp_server_get_username (session));
1236 break; 1236 break;
1237 #endif /* ENABLE_SRP */ 1237 #endif /* ENABLE_SRP */
1261 /* Print the MAC algorithms name. ie SHA1 */ 1261 /* Print the MAC algorithms name. ie SHA1 */
1262 tmp = gnutls_mac_get_name (gnutls_mac_get (session)); 1262 tmp = gnutls_mac_get_name (gnutls_mac_get (session));
1263 LOG_D("\t - MAC: %s", tmp); 1263 LOG_D("\t - MAC: %s", tmp);
1264 } 1264 }
1265 #endif /* DEBUG */ 1265 #endif /* DEBUG */
1266 1266
1267 /* First, use built-in verification */ 1267 /* First, use built-in verification */
1268 CHECK_GNUTLS_DO( gnutls_certificate_verify_peers2 (session, &gtret), return EINVAL ); 1268 CHECK_GNUTLS_DO( gnutls_certificate_verify_peers2 (session, &gtret), return EINVAL );
1269 if (gtret) { 1269 if (gtret) {
1270 LOG_E("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id); 1270 LOG_E("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id);
1271 if (gtret & GNUTLS_CERT_INVALID) 1271 if (gtret & GNUTLS_CERT_INVALID)
1278 LOG_E(" - The certificate signer is not a CA, or uses version 1, or 3 without basic constraints."); 1278 LOG_E(" - The certificate signer is not a CA, or uses version 1, or 3 without basic constraints.");
1279 if (gtret & GNUTLS_CERT_INSECURE_ALGORITHM) 1279 if (gtret & GNUTLS_CERT_INSECURE_ALGORITHM)
1280 LOG_E(" - The certificate signature uses a weak algorithm."); 1280 LOG_E(" - The certificate signature uses a weak algorithm.");
1281 return EINVAL; 1281 return EINVAL;
1282 } 1282 }
1283 1283
1284 /* Code from http://www.gnu.org/software/gnutls/manual/gnutls.html#Verifying-peer_0027s-certificate */ 1284 /* Code from http://www.gnu.org/software/gnutls/manual/gnutls.html#Verifying-peer_0027s-certificate */
1285 if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509) { 1285 if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509) {
1286 LOG_E("TLS: Remote peer did not present a certificate, other mechanisms are not supported yet. socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id); 1286 LOG_E("TLS: Remote peer did not present a certificate, other mechanisms are not supported yet. socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id);
1287 return EINVAL; 1287 return EINVAL;
1288 } 1288 }
1289 1289
1290 GNUTLS_TRACE( cert_list = gnutls_certificate_get_peers (session, &cert_list_size) ); 1290 GNUTLS_TRACE( cert_list = gnutls_certificate_get_peers (session, &cert_list_size) );
1291 if (cert_list == NULL) 1291 if (cert_list == NULL)
1292 return EINVAL; 1292 return EINVAL;
1293 1293
1294 now = time(NULL); 1294 now = time(NULL);
1295 1295
1296 #ifdef DEBUG 1296 #ifdef DEBUG
1297 char serial[40]; 1297 char serial[40];
1298 char dn[128]; 1298 char dn[128];
1299 size_t size; 1299 size_t size;
1300 unsigned int algo, bits; 1300 unsigned int algo, bits;
1301 time_t expiration_time, activation_time; 1301 time_t expiration_time, activation_time;
1302 1302
1303 LOG_D("TLS Certificate information for connection '%s' (%d certs provided):", conn->cc_id, cert_list_size); 1303 LOG_D("TLS Certificate information for connection '%s' (%d certs provided):", conn->cc_id, cert_list_size);
1304 for (i = 0; i < cert_list_size; i++) 1304 for (i = 0; i < cert_list_size; i++)
1305 { 1305 {
1306 1306
1307 CHECK_GNUTLS_DO( gnutls_x509_crt_init (&cert), return EINVAL); 1307 CHECK_GNUTLS_DO( gnutls_x509_crt_init (&cert), return EINVAL);
1308 CHECK_GNUTLS_DO( gnutls_x509_crt_import (cert, &cert_list[i], GNUTLS_X509_FMT_DER), return EINVAL); 1308 CHECK_GNUTLS_DO( gnutls_x509_crt_import (cert, &cert_list[i], GNUTLS_X509_FMT_DER), return EINVAL);
1309 1309
1310 LOG_A(" Certificate %d info:", i); 1310 LOG_A(" Certificate %d info:", i);
1311 1311
1312 GNUTLS_TRACE( expiration_time = gnutls_x509_crt_get_expiration_time (cert) ); 1312 GNUTLS_TRACE( expiration_time = gnutls_x509_crt_get_expiration_time (cert) );
1313 GNUTLS_TRACE( activation_time = gnutls_x509_crt_get_activation_time (cert) ); 1313 GNUTLS_TRACE( activation_time = gnutls_x509_crt_get_activation_time (cert) );
1314 1314
1316 LOG( i ? FD_LOG_ANNOYING : FD_LOG_DEBUG, "\t - Certificate expires: %.24s", ctime (&expiration_time)); 1316 LOG( i ? FD_LOG_ANNOYING : FD_LOG_DEBUG, "\t - Certificate expires: %.24s", ctime (&expiration_time));
1317 1317
1318 /* Print the serial number of the certificate. */ 1318 /* Print the serial number of the certificate. */
1319 size = sizeof (serial); 1319 size = sizeof (serial);
1320 gnutls_x509_crt_get_serial (cert, serial, &size); 1320 gnutls_x509_crt_get_serial (cert, serial, &size);
1321 1321
1322 { 1322 {
1323 int j; 1323 int j;
1324 char buf[1024]; 1324 char buf[1024];
1325 snprintf(buf, sizeof(buf), "\t - Certificate serial number: "); 1325 snprintf(buf, sizeof(buf), "\t - Certificate serial number: ");
1326 for (j = 0; j < size; j++) { 1326 for (j = 0; j < size; j++) {
1352 1352
1353 /* Check validity of all the certificates */ 1353 /* Check validity of all the certificates */
1354 for (i = 0; i < cert_list_size; i++) 1354 for (i = 0; i < cert_list_size; i++)
1355 { 1355 {
1356 time_t deadline; 1356 time_t deadline;
1357 1357
1358 CHECK_GNUTLS_DO( gnutls_x509_crt_init (&cert), return EINVAL); 1358 CHECK_GNUTLS_DO( gnutls_x509_crt_init (&cert), return EINVAL);
1359 CHECK_GNUTLS_DO( gnutls_x509_crt_import (cert, &cert_list[i], GNUTLS_X509_FMT_DER), return EINVAL); 1359 CHECK_GNUTLS_DO( gnutls_x509_crt_import (cert, &cert_list[i], GNUTLS_X509_FMT_DER), return EINVAL);
1360 1360
1361 GNUTLS_TRACE( deadline = gnutls_x509_crt_get_expiration_time(cert) ); 1361 GNUTLS_TRACE( deadline = gnutls_x509_crt_get_expiration_time(cert) );
1362 if ((deadline != (time_t)-1) && (deadline < now)) { 1362 if ((deadline != (time_t)-1) && (deadline < now)) {
1363 LOG_E("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id); 1363 LOG_E("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id);
1364 LOG_E(" - The certificate %d in the chain is expired", i); 1364 LOG_E(" - The certificate %d in the chain is expired", i);
1365 ret = EINVAL; 1365 ret = EINVAL;
1366 } 1366 }
1367 1367
1368 GNUTLS_TRACE( deadline = gnutls_x509_crt_get_activation_time(cert) ); 1368 GNUTLS_TRACE( deadline = gnutls_x509_crt_get_activation_time(cert) );
1369 if ((deadline != (time_t)-1) && (deadline > now)) { 1369 if ((deadline != (time_t)-1) && (deadline > now)) {
1370 LOG_E("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id); 1370 LOG_E("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id);
1371 LOG_E(" - The certificate %d in the chain is not yet activated", i); 1371 LOG_E(" - The certificate %d in the chain is not yet activated", i);
1372 ret = EINVAL; 1372 ret = EINVAL;
1373 } 1373 }
1374 1374
1375 if ((i == 0) && (conn->cc_tls_para.cn)) { 1375 if ((i == 0) && (conn->cc_tls_para.cn)) {
1376 if (!gnutls_x509_crt_check_hostname (cert, conn->cc_tls_para.cn)) { 1376 if (!gnutls_x509_crt_check_hostname (cert, conn->cc_tls_para.cn)) {
1377 LOG_E("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id); 1377 LOG_E("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id);
1378 LOG_E(" - The certificate hostname does not match '%s'", conn->cc_tls_para.cn); 1378 LOG_E(" - The certificate hostname does not match '%s'", conn->cc_tls_para.cn);
1379 ret = EINVAL; 1379 ret = EINVAL;
1380 } 1380 }
1381 } 1381 }
1382 1382
1383 GNUTLS_TRACE( gnutls_x509_crt_deinit (cert) ); 1383 GNUTLS_TRACE( gnutls_x509_crt_deinit (cert) );
1384 } 1384 }
1385 1385
1386 return ret; 1386 return ret;
1387 } 1387 }
1398 gnutls_x509_crt_t cert; 1398 gnutls_x509_crt_t cert;
1399 struct cnxctx * conn; 1399 struct cnxctx * conn;
1400 int hostname_verified = 0; 1400 int hostname_verified = 0;
1401 1401
1402 TRACE_ENTRY("%p", session); 1402 TRACE_ENTRY("%p", session);
1403 1403
1404 /* get the associated connection */ 1404 /* get the associated connection */
1405 conn = gnutls_session_get_ptr (session); 1405 conn = gnutls_session_get_ptr (session);
1406 1406
1407 /* Trace the session information -- http://www.gnu.org/software/gnutls/manual/gnutls.html#Obtaining-session-information */ 1407 /* Trace the session information -- http://www.gnu.org/software/gnutls/manual/gnutls.html#Obtaining-session-information */
1408 #ifdef DEBUG 1408 #ifdef DEBUG
1409 const char *tmp; 1409 const char *tmp;
1410 gnutls_credentials_type_t cred; 1410 gnutls_credentials_type_t cred;
1411 gnutls_kx_algorithm_t kx; 1411 gnutls_kx_algorithm_t kx;
1412 int dhe, ecdh; 1412 int dhe, ecdh;
1413 1413
1414 dhe = ecdh = 0; 1414 dhe = ecdh = 0;
1415 1415
1416 LOG_A("TLS Session information for connection '%s':", conn->cc_id); 1416 LOG_A("TLS Session information for connection '%s':", conn->cc_id);
1417 1417
1418 /* print the key exchange's algorithm name 1418 /* print the key exchange's algorithm name
1419 */ 1419 */
1420 GNUTLS_TRACE( kx = gnutls_kx_get (session) ); 1420 GNUTLS_TRACE( kx = gnutls_kx_get (session) );
1421 GNUTLS_TRACE( tmp = gnutls_kx_get_name (kx) ); 1421 GNUTLS_TRACE( tmp = gnutls_kx_get_name (kx) );
1422 LOG_D("\t- Key Exchange: %s", tmp); 1422 LOG_D("\t- Key Exchange: %s", tmp);
1472 */ 1472 */
1473 if (kx == GNUTLS_KX_DHE_RSA || kx == GNUTLS_KX_DHE_DSS) 1473 if (kx == GNUTLS_KX_DHE_RSA || kx == GNUTLS_KX_DHE_DSS)
1474 dhe = 1; 1474 dhe = 1;
1475 else if (kx == GNUTLS_KX_ECDHE_RSA || kx == GNUTLS_KX_ECDHE_ECDSA) 1475 else if (kx == GNUTLS_KX_ECDHE_RSA || kx == GNUTLS_KX_ECDHE_ECDSA)
1476 ecdh = 1; 1476 ecdh = 1;
1477 1477
1478 /* Now print some info on the remote certificate */ 1478 /* Now print some info on the remote certificate */
1479 if (gnutls_certificate_type_get (session) == GNUTLS_CRT_X509) { 1479 if (gnutls_certificate_type_get (session) == GNUTLS_CRT_X509) {
1480 gnutls_datum_t cinfo; 1480 gnutls_datum_t cinfo;
1481 1481
1482 cert_list = gnutls_certificate_get_peers (session, &cert_list_size); 1482 cert_list = gnutls_certificate_get_peers (session, &cert_list_size);
1502 if (ret == 0) 1502 if (ret == 0)
1503 { 1503 {
1504 LOG_D("\t\t%s", cinfo.data); 1504 LOG_D("\t\t%s", cinfo.data);
1505 gnutls_free (cinfo.data); 1505 gnutls_free (cinfo.data);
1506 } 1506 }
1507 1507
1508 if (conn->cc_tls_para.cn) { 1508 if (conn->cc_tls_para.cn) {
1509 if (!gnutls_x509_crt_check_hostname (cert, conn->cc_tls_para.cn)) { 1509 if (!gnutls_x509_crt_check_hostname (cert, conn->cc_tls_para.cn)) {
1510 LOG_E("\tTLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id); 1510 LOG_E("\tTLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id);
1511 LOG_E("\t - The certificate hostname does not match '%s'", conn->cc_tls_para.cn); 1511 LOG_E("\t - The certificate hostname does not match '%s'", conn->cc_tls_para.cn);
1512 gnutls_x509_crt_deinit (cert); 1512 gnutls_x509_crt_deinit (cert);
1513 return GNUTLS_E_CERTIFICATE_ERROR; 1513 return GNUTLS_E_CERTIFICATE_ERROR;
1514 } 1514 }
1515 1515
1516 } 1516 }
1517 1517
1518 hostname_verified = 1; 1518 hostname_verified = 1;
1519 1519
1520 gnutls_x509_crt_deinit (cert); 1520 gnutls_x509_crt_deinit (cert);
1533 gnutls_ecc_curve_get_name (gnutls_ecc_curve_get (session))); 1533 gnutls_ecc_curve_get_name (gnutls_ecc_curve_get (session)));
1534 else if (dhe != 0) 1534 else if (dhe != 0)
1535 LOG_D("\t - Ephemeral DH using prime of %d bits", 1535 LOG_D("\t - Ephemeral DH using prime of %d bits",
1536 gnutls_dh_get_prime_bits (session)); 1536 gnutls_dh_get_prime_bits (session));
1537 1537
1538 /* print the protocol's name (ie TLS 1.0) 1538 /* print the protocol's name (ie TLS 1.0)
1539 */ 1539 */
1540 tmp = gnutls_protocol_get_name (gnutls_protocol_get_version (session)); 1540 tmp = gnutls_protocol_get_name (gnutls_protocol_get_version (session));
1541 LOG_D("\t - Protocol: %s", tmp); 1541 LOG_D("\t - Protocol: %s", tmp);
1542 1542
1543 /* print the certificate type of the peer. 1543 /* print the certificate type of the peer.
1555 /* Print the MAC algorithms name. 1555 /* Print the MAC algorithms name.
1556 * ie SHA1 1556 * ie SHA1
1557 */ 1557 */
1558 tmp = gnutls_mac_get_name (gnutls_mac_get (session)); 1558 tmp = gnutls_mac_get_name (gnutls_mac_get (session));
1559 LOG_D("\t - MAC: %s", tmp); 1559 LOG_D("\t - MAC: %s", tmp);
1560 1560
1561 #endif /* DEBUG */ 1561 #endif /* DEBUG */
1562 1562
1563 /* This verification function uses the trusted CAs in the credentials 1563 /* This verification function uses the trusted CAs in the credentials
1564 * structure. So you must have installed one or more CA certificates. 1564 * structure. So you must have installed one or more CA certificates.
1565 */ 1565 */
1566 CHECK_GNUTLS_DO( gnutls_certificate_verify_peers2 (session, &status), return GNUTLS_E_CERTIFICATE_ERROR ); 1566 CHECK_GNUTLS_DO( gnutls_certificate_verify_peers2 (session, &status), return GNUTLS_E_CERTIFICATE_ERROR );
1575 if (status & GNUTLS_CERT_EXPIRED) 1575 if (status & GNUTLS_CERT_EXPIRED)
1576 LOG_E(" - The certificate has expired."); 1576 LOG_E(" - The certificate has expired.");
1577 1577
1578 if (status & GNUTLS_CERT_NOT_ACTIVATED) 1578 if (status & GNUTLS_CERT_NOT_ACTIVATED)
1579 LOG_E(" - The certificate is not yet activated."); 1579 LOG_E(" - The certificate is not yet activated.");
1580 } 1580 }
1581 if (status & GNUTLS_CERT_INVALID) 1581 if (status & GNUTLS_CERT_INVALID)
1582 { 1582 {
1583 return GNUTLS_E_CERTIFICATE_ERROR; 1583 return GNUTLS_E_CERTIFICATE_ERROR;
1584 } 1584 }
1585 1585
1586 /* Up to here the process is the same for X.509 certificates and 1586 /* Up to here the process is the same for X.509 certificates and
1587 * OpenPGP keys. From now on X.509 certificates are assumed. This can 1587 * OpenPGP keys. From now on X.509 certificates are assumed. This can
1588 * be easily extended to work with openpgp keys as well. 1588 * be easily extended to work with openpgp keys as well.
1589 */ 1589 */
1590 if ((!hostname_verified) && (conn->cc_tls_para.cn)) { 1590 if ((!hostname_verified) && (conn->cc_tls_para.cn)) {
1632 1632
1633 /* TLS handshake a connection; no need to have called start_clear before. Reception is active if handhsake is successful */ 1633 /* TLS handshake a connection; no need to have called start_clear before. Reception is active if handhsake is successful */
1634 int fd_cnx_handshake(struct cnxctx * conn, int mode, int algo, char * priority, void * alt_creds) 1634 int fd_cnx_handshake(struct cnxctx * conn, int mode, int algo, char * priority, void * alt_creds)
1635 { 1635 {
1636 int dtls = 0; 1636 int dtls = 0;
1637 1637
1638 TRACE_ENTRY( "%p %d %d %p %p", conn, mode, algo, priority, alt_creds); 1638 TRACE_ENTRY( "%p %d %d %p %p", conn, mode, algo, priority, alt_creds);
1639 CHECK_PARAMS( conn && (!fd_cnx_teststate(conn, CC_STATUS_TLS)) && ( (mode == GNUTLS_CLIENT) || (mode == GNUTLS_SERVER) ) && (!conn->cc_loop) ); 1639 CHECK_PARAMS( conn && (!fd_cnx_teststate(conn, CC_STATUS_TLS)) && ( (mode == GNUTLS_CLIENT) || (mode == GNUTLS_SERVER) ) && (!conn->cc_loop) );
1640 1640
1641 /* Save the mode */ 1641 /* Save the mode */
1642 conn->cc_tls_para.mode = mode; 1642 conn->cc_tls_para.mode = mode;
1643 conn->cc_tls_para.algo = algo; 1643 conn->cc_tls_para.algo = algo;
1644 1644
1645 /* Cancel receiving thread if any -- it should already be terminated anyway, we just release the resources */ 1645 /* Cancel receiving thread if any -- it should already be terminated anyway, we just release the resources */
1646 CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */); 1646 CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */);
1647 1647
1648 /* Once TLS handshake is done, we don't stop after the first message */ 1648 /* Once TLS handshake is done, we don't stop after the first message */
1649 conn->cc_loop = 1; 1649 conn->cc_loop = 1;
1650 1650
1651 dtls = fd_cnx_may_dtls(conn); 1651 dtls = fd_cnx_may_dtls(conn);
1652 1652
1653 /* Prepare the master session credentials and priority */ 1653 /* Prepare the master session credentials and priority */
1654 CHECK_FCT( fd_tls_prepare(&conn->cc_tls_para.session, mode, dtls, priority, alt_creds) ); 1654 CHECK_FCT( fd_tls_prepare(&conn->cc_tls_para.session, mode, dtls, priority, alt_creds) );
1655 1655
1656 /* Special case: multi-stream TLS is not natively managed in GNU TLS, we use a wrapper library */ 1656 /* Special case: multi-stream TLS is not natively managed in GNU TLS, we use a wrapper library */
1657 if ((!dtls) && (conn->cc_sctp_para.pairs > 1)) { 1657 if ((!dtls) && (conn->cc_sctp_para.pairs > 1)) {
1680 } else { 1680 } else {
1681 TODO("DTLS push/pull functions"); 1681 TODO("DTLS push/pull functions");
1682 return ENOTSUP; 1682 return ENOTSUP;
1683 } 1683 }
1684 } 1684 }
1685 1685
1686 /* additional initialization for gnutls 3.x */ 1686 /* additional initialization for gnutls 3.x */
1687 #ifdef GNUTLS_VERSION_300 1687 #ifdef GNUTLS_VERSION_300
1688 /* the verify function has already been set in the global initialization in config.c */ 1688 /* the verify function has already been set in the global initialization in config.c */
1689 1689
1690 /* fd_tls_verify_credentials_2 uses the connection */ 1690 /* fd_tls_verify_credentials_2 uses the connection */
1691 gnutls_session_set_ptr (conn->cc_tls_para.session, (void *) conn); 1691 gnutls_session_set_ptr (conn->cc_tls_para.session, (void *) conn);
1692 1692
1693 if ((conn->cc_tls_para.cn != NULL) && (mode == GNUTLS_CLIENT)) { 1693 if ((conn->cc_tls_para.cn != NULL) && (mode == GNUTLS_CLIENT)) {
1694 /* this might allow virtual hosting on the remote peer */ 1694 /* this might allow virtual hosting on the remote peer */
1695 CHECK_GNUTLS_DO( gnutls_server_name_set (conn->cc_tls_para.session, GNUTLS_NAME_DNS, conn->cc_tls_para.cn, strlen(conn->cc_tls_para.cn)), /* ignore failure */); 1695 CHECK_GNUTLS_DO( gnutls_server_name_set (conn->cc_tls_para.session, GNUTLS_NAME_DNS, conn->cc_tls_para.cn, strlen(conn->cc_tls_para.cn)), /* ignore failure */);
1696 } 1696 }
1697 1697
1698 #endif /* GNUTLS_VERSION_300 */ 1698 #endif /* GNUTLS_VERSION_300 */
1699 1699
1700 #ifdef GNUTLS_VERSION_310 1700 #ifdef GNUTLS_VERSION_310
1701 GNUTLS_TRACE( gnutls_handshake_set_timeout( conn->cc_tls_para.session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT)); 1701 GNUTLS_TRACE( gnutls_handshake_set_timeout( conn->cc_tls_para.session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT));
1702 #endif /* GNUTLS_VERSION_310 */ 1702 #endif /* GNUTLS_VERSION_310 */
1703 1703
1704 /* Mark the connection as protected from here, so that the gnutls credentials will be freed */ 1704 /* Mark the connection as protected from here, so that the gnutls credentials will be freed */
1705 fd_cnx_addstate(conn, CC_STATUS_TLS); 1705 fd_cnx_addstate(conn, CC_STATUS_TLS);
1706 1706
1707 /* Handshake master session */ 1707 /* Handshake master session */
1708 { 1708 {
1709 int ret; 1709 int ret;
1710 1710
1711 CHECK_GNUTLS_DO( ret = gnutls_handshake(conn->cc_tls_para.session), 1711 CHECK_GNUTLS_DO( ret = gnutls_handshake(conn->cc_tls_para.session),
1712 { 1712 {
1713 if (TRACE_BOOL(INFO)) { 1713 if (TRACE_BOOL(INFO)) {
1714 fd_log_debug("TLS Handshake failed on socket %d (%s) : %s", conn->cc_socket, conn->cc_id, gnutls_strerror(ret)); 1714 fd_log_debug("TLS Handshake failed on socket %d (%s) : %s", conn->cc_socket, conn->cc_id, gnutls_strerror(ret));
1715 } 1715 }
1717 return EINVAL; 1717 return EINVAL;
1718 } ); 1718 } );
1719 1719
1720 #ifndef GNUTLS_VERSION_300 1720 #ifndef GNUTLS_VERSION_300
1721 /* Now verify the remote credentials are valid -- only simple tests here */ 1721 /* Now verify the remote credentials are valid -- only simple tests here */
1722 CHECK_FCT_DO( fd_tls_verify_credentials(conn->cc_tls_para.session, conn, 1), 1722 CHECK_FCT_DO( fd_tls_verify_credentials(conn->cc_tls_para.session, conn, 1),
1723 { 1723 {
1724 CHECK_GNUTLS_DO( gnutls_bye(conn->cc_tls_para.session, GNUTLS_SHUT_RDWR), ); 1724 CHECK_GNUTLS_DO( gnutls_bye(conn->cc_tls_para.session, GNUTLS_SHUT_RDWR), );
1725 fd_cnx_markerror(conn); 1725 fd_cnx_markerror(conn);
1726 return EINVAL; 1726 return EINVAL;
1727 }); 1727 });
1728 #endif /* GNUTLS_VERSION_300 */ 1728 #endif /* GNUTLS_VERSION_300 */
1729 } 1729 }
1730 1730
1731 /* Multi-stream TLS: handshake other streams as well */ 1731 /* Multi-stream TLS: handshake other streams as well */
1732 if ((!dtls) && (conn->cc_sctp_para.pairs > 1)) { 1732 if ((!dtls) && (conn->cc_sctp_para.pairs > 1)) {
1733 #ifndef DISABLE_SCTP 1733 #ifndef DISABLE_SCTP
1734 /* Start reading the messages from the master session. That way, if the remote peer closed, we are not stuck inside handshake */ 1734 /* Start reading the messages from the master session. That way, if the remote peer closed, we are not stuck inside handshake */
1735 CHECK_FCT(fd_sctp3436_startthreads(conn, 0)); 1735 CHECK_FCT(fd_sctp3436_startthreads(conn, 0));
1748 TODO("Signal the dtls_push function that multiple streams can be used from this point."); 1748 TODO("Signal the dtls_push function that multiple streams can be used from this point.");
1749 TODO("Create DTLS rcvthr (must reassembly based on seq numbers & stream id ?)"); 1749 TODO("Create DTLS rcvthr (must reassembly based on seq numbers & stream id ?)");
1750 return ENOTSUP; 1750 return ENOTSUP;
1751 } 1751 }
1752 } 1752 }
1753 1753
1754 return 0; 1754 return 0;
1755 } 1755 }
1756 1756
1757 /* Retrieve TLS credentials of the remote peer, after handshake */ 1757 /* Retrieve TLS credentials of the remote peer, after handshake */
1758 int fd_cnx_getcred(struct cnxctx * conn, const gnutls_datum_t **cert_list, unsigned int *cert_list_size) 1758 int fd_cnx_getcred(struct cnxctx * conn, const gnutls_datum_t **cert_list, unsigned int *cert_list_size)
1759 { 1759 {
1760 TRACE_ENTRY("%p %p %p", conn, cert_list, cert_list_size); 1760 TRACE_ENTRY("%p %p %p", conn, cert_list, cert_list_size);
1761 CHECK_PARAMS( conn && fd_cnx_teststate(conn, CC_STATUS_TLS) && cert_list && cert_list_size ); 1761 CHECK_PARAMS( conn && fd_cnx_teststate(conn, CC_STATUS_TLS) && cert_list && cert_list_size );
1762 1762
1763 /* This function only works for X.509 certificates. */ 1763 /* This function only works for X.509 certificates. */
1764 CHECK_PARAMS( gnutls_certificate_type_get (conn->cc_tls_para.session) == GNUTLS_CRT_X509 ); 1764 CHECK_PARAMS( gnutls_certificate_type_get (conn->cc_tls_para.session) == GNUTLS_CRT_X509 );
1765 1765
1766 GNUTLS_TRACE( *cert_list = gnutls_certificate_get_peers (conn->cc_tls_para.session, cert_list_size) ); 1766 GNUTLS_TRACE( *cert_list = gnutls_certificate_get_peers (conn->cc_tls_para.session, cert_list_size) );
1767 if (*cert_list == NULL) { 1767 if (*cert_list == NULL) {
1768 TRACE_DEBUG(INFO, "No certificate was provided by remote peer / an error occurred."); 1768 TRACE_DEBUG(INFO, "No certificate was provided by remote peer / an error occurred.");
1769 return EINVAL; 1769 return EINVAL;
1770 } 1770 }
1771 1771
1772 TRACE_DEBUG( FULL, "Saved certificate chain (%d certificates) in peer structure.", *cert_list_size); 1772 TRACE_DEBUG( FULL, "Saved certificate chain (%d certificates) in peer structure.", *cert_list_size);
1773 1773
1774 return 0; 1774 return 0;
1775 } 1775 }
1776 1776
1777 /* Receive next message. if timeout is not NULL, wait only until timeout. This function only pulls from a queue, mgr thread is filling that queue aynchrounously. */ 1777 /* Receive next message. if timeout is not NULL, wait only until timeout. This function only pulls from a queue, mgr thread is filling that queue aynchrounously. */
1778 /* if the altfifo has been set on this conn object, this function must not be called */ 1778 /* if the altfifo has been set on this conn object, this function must not be called */
1779 int fd_cnx_receive(struct cnxctx * conn, struct timespec * timeout, unsigned char **buf, size_t * len) 1779 int fd_cnx_receive(struct cnxctx * conn, struct timespec * timeout, unsigned char **buf, size_t * len)
1780 { 1780 {
1781 int ev; 1781 int ev;
1782 size_t ev_sz; 1782 size_t ev_sz;
1783 void * ev_data; 1783 void * ev_data;
1784 1784
1785 TRACE_ENTRY("%p %p %p %p", conn, timeout, buf, len); 1785 TRACE_ENTRY("%p %p %p %p", conn, timeout, buf, len);
1786 CHECK_PARAMS(conn && (conn->cc_socket > 0) && buf && len); 1786 CHECK_PARAMS(conn && (conn->cc_socket > 0) && buf && len);
1787 CHECK_PARAMS(conn->cc_rcvthr != (pthread_t)NULL); 1787 CHECK_PARAMS(conn->cc_rcvthr != (pthread_t)NULL);
1788 CHECK_PARAMS(conn->cc_alt == NULL); 1788 CHECK_PARAMS(conn->cc_alt == NULL);
1789 1789
1792 if (timeout) { 1792 if (timeout) {
1793 CHECK_FCT( fd_event_timedget(conn->cc_incoming, timeout, FDEVP_PSM_TIMEOUT, &ev, &ev_sz, &ev_data) ); 1793 CHECK_FCT( fd_event_timedget(conn->cc_incoming, timeout, FDEVP_PSM_TIMEOUT, &ev, &ev_sz, &ev_data) );
1794 } else { 1794 } else {
1795 CHECK_FCT( fd_event_get(conn->cc_incoming, &ev, &ev_sz, &ev_data) ); 1795 CHECK_FCT( fd_event_get(conn->cc_incoming, &ev, &ev_sz, &ev_data) );
1796 } 1796 }
1797 1797
1798 switch (ev) { 1798 switch (ev) {
1799 case FDEVP_CNX_MSG_RECV: 1799 case FDEVP_CNX_MSG_RECV:
1800 /* We got one */ 1800 /* We got one */
1801 *len = ev_sz; 1801 *len = ev_sz;
1802 *buf = ev_data; 1802 *buf = ev_data;
1803 return 0; 1803 return 0;
1804 1804
1805 case FDEVP_PSM_TIMEOUT: 1805 case FDEVP_PSM_TIMEOUT:
1806 TRACE_DEBUG(FULL, "Timeout event received"); 1806 TRACE_DEBUG(FULL, "Timeout event received");
1807 return ETIMEDOUT; 1807 return ETIMEDOUT;
1808 1808
1809 case FDEVP_CNX_EP_CHANGE: 1809 case FDEVP_CNX_EP_CHANGE:
1810 /* We ignore this event */ 1810 /* We ignore this event */
1811 goto get_next; 1811 goto get_next;
1812 1812
1813 case FDEVP_CNX_ERROR: 1813 case FDEVP_CNX_ERROR:
1814 TRACE_DEBUG(FULL, "Received ERROR event on the connection"); 1814 TRACE_DEBUG(FULL, "Received ERROR event on the connection");
1815 return ENOTCONN; 1815 return ENOTCONN;
1816 } 1816 }
1817 1817
1818 TRACE_DEBUG(INFO, "Received unexpected event %d (%s)", ev, fd_pev_str(ev)); 1818 TRACE_DEBUG(INFO, "Received unexpected event %d (%s)", ev, fd_pev_str(ev));
1819 return EINVAL; 1819 return EINVAL;
1820 } 1820 }
1821 1821
1822 /* Where the events are sent */ 1822 /* Where the events are sent */
1833 int fd_cnx_recv_setaltfifo(struct cnxctx * conn, struct fifo * alt_fifo) 1833 int fd_cnx_recv_setaltfifo(struct cnxctx * conn, struct fifo * alt_fifo)
1834 { 1834 {
1835 int ret; 1835 int ret;
1836 TRACE_ENTRY( "%p %p", conn, alt_fifo ); 1836 TRACE_ENTRY( "%p %p", conn, alt_fifo );
1837 CHECK_PARAMS( conn && alt_fifo && conn->cc_incoming ); 1837 CHECK_PARAMS( conn && alt_fifo && conn->cc_incoming );
1838 1838
1839 /* The magic function does it all */ 1839 /* The magic function does it all */
1840 CHECK_POSIX_DO( pthread_mutex_lock(&state_lock), { ASSERT(0); } ); 1840 CHECK_POSIX_DO( pthread_mutex_lock(&state_lock), { ASSERT(0); } );
1841 CHECK_FCT_DO( ret = fd_fifo_move( conn->cc_incoming, alt_fifo, &conn->cc_alt ), ); 1841 CHECK_FCT_DO( ret = fd_fifo_move( conn->cc_incoming, alt_fifo, &conn->cc_alt ), );
1842 CHECK_POSIX_DO( pthread_mutex_unlock(&state_lock), { ASSERT(0); } ); 1842 CHECK_POSIX_DO( pthread_mutex_unlock(&state_lock), { ASSERT(0); } );
1843 1843
1844 return ret; 1844 return ret;
1845 } 1845 }
1846 1846
1847 /* Send function when no multi-stream is involved, or sending on stream #0 (send() always use stream 0)*/ 1847 /* Send function when no multi-stream is involved, or sending on stream #0 (send() always use stream 0)*/
1848 static int send_simple(struct cnxctx * conn, unsigned char * buf, size_t len) 1848 static int send_simple(struct cnxctx * conn, unsigned char * buf, size_t len)
1859 iov.iov_len = len - sent; 1859 iov.iov_len = len - sent;
1860 CHECK_SYS_DO( ret = fd_cnx_s_sendv(conn, &iov, 1), ); 1860 CHECK_SYS_DO( ret = fd_cnx_s_sendv(conn, &iov, 1), );
1861 } 1861 }
1862 if (ret <= 0) 1862 if (ret <= 0)
1863 return ENOTCONN; 1863 return ENOTCONN;
1864 1864
1865 sent += ret; 1865 sent += ret;
1866 } while ( sent < len ); 1866 } while ( sent < len );
1867 return 0; 1867 return 0;
1868 } 1868 }
1869 1869
1870 /* Send a message -- this is synchronous -- and we assume it's never called by several threads at the same time (on the same conn), so we don't protect. */ 1870 /* Send a message -- this is synchronous -- and we assume it's never called by several threads at the same time (on the same conn), so we don't protect. */
1871 int fd_cnx_send(struct cnxctx * conn, unsigned char * buf, size_t len) 1871 int fd_cnx_send(struct cnxctx * conn, unsigned char * buf, size_t len)
1872 { 1872 {
1873 TRACE_ENTRY("%p %p %zd", conn, buf, len); 1873 TRACE_ENTRY("%p %p %zd", conn, buf, len);
1874 1874
1875 CHECK_PARAMS(conn && (conn->cc_socket > 0) && (! fd_cnx_teststate(conn, CC_STATUS_ERROR)) && buf && len); 1875 CHECK_PARAMS(conn && (conn->cc_socket > 0) && (! fd_cnx_teststate(conn, CC_STATUS_ERROR)) && buf && len);
1876 1876
1877 TRACE_DEBUG(FULL, "Sending %zdb %sdata on connection %s", len, fd_cnx_teststate(conn, CC_STATUS_TLS) ? "TLS-protected ":"", conn->cc_id); 1877 TRACE_DEBUG(FULL, "Sending %zdb %sdata on connection %s", len, fd_cnx_teststate(conn, CC_STATUS_TLS) ? "TLS-protected ":"", conn->cc_id);
1878 1878
1879 switch (conn->cc_proto) { 1879 switch (conn->cc_proto) {
1880 case IPPROTO_TCP: 1880 case IPPROTO_TCP:
1881 CHECK_FCT( send_simple(conn, buf, len) ); 1881 CHECK_FCT( send_simple(conn, buf, len) );
1882 break; 1882 break;
1883 1883
1884 #ifndef DISABLE_SCTP 1884 #ifndef DISABLE_SCTP
1885 case IPPROTO_SCTP: { 1885 case IPPROTO_SCTP: {
1886 int dtls = fd_cnx_uses_dtls(conn); 1886 int dtls = fd_cnx_uses_dtls(conn);
1887 if (!dtls) { 1887 if (!dtls) {
1888 int stream = 0; 1888 int stream = 0;
1890 int limit; 1890 int limit;
1891 if (fd_cnx_teststate(conn, CC_STATUS_TLS)) 1891 if (fd_cnx_teststate(conn, CC_STATUS_TLS))
1892 limit = conn->cc_sctp_para.pairs; 1892 limit = conn->cc_sctp_para.pairs;
1893 else 1893 else
1894 limit = conn->cc_sctp_para.str_out; 1894 limit = conn->cc_sctp_para.str_out;
1895 1895
1896 if (limit > 1) { 1896 if (limit > 1) {
1897 conn->cc_sctp_para.next += 1; 1897 conn->cc_sctp_para.next += 1;
1898 conn->cc_sctp_para.next %= limit; 1898 conn->cc_sctp_para.next %= limit;
1899 stream = conn->cc_sctp_para.next; 1899 stream = conn->cc_sctp_para.next;
1900 } 1900 }
1901 } 1901 }
1902 1902
1903 if (stream == 0) { 1903 if (stream == 0) {
1904 /* We can use default function, it sends over stream #0 */ 1904 /* We can use default function, it sends over stream #0 */
1905 CHECK_FCT( send_simple(conn, buf, len) ); 1905 CHECK_FCT( send_simple(conn, buf, len) );
1906 } else { 1906 } else {
1907 if (!fd_cnx_teststate(conn, CC_STATUS_TLS)) { 1907 if (!fd_cnx_teststate(conn, CC_STATUS_TLS)) {
1908 struct iovec iov; 1908 struct iovec iov;
1909 iov.iov_base = buf; 1909 iov.iov_base = buf;
1910 iov.iov_len = len; 1910 iov.iov_len = len;
1911 1911
1912 CHECK_SYS_DO( fd_sctp_sendstrv(conn, stream, &iov, 1), { fd_cnx_markerror(conn); return ENOTCONN; } ); 1912 CHECK_SYS_DO( fd_sctp_sendstrv(conn, stream, &iov, 1), { fd_cnx_markerror(conn); return ENOTCONN; } );
1913 } else { 1913 } else {
1914 /* push the data to the appropriate session */ 1914 /* push the data to the appropriate session */
1915 ssize_t ret; 1915 ssize_t ret;
1916 size_t sent = 0; 1916 size_t sent = 0;
1930 CHECK_FCT( send_simple(conn, buf, len) ); 1930 CHECK_FCT( send_simple(conn, buf, len) );
1931 } 1931 }
1932 } 1932 }
1933 break; 1933 break;
1934 #endif /* DISABLE_SCTP */ 1934 #endif /* DISABLE_SCTP */
1935 1935
1936 default: 1936 default:
1937 TRACE_DEBUG(INFO, "Unknown protocol: %d", conn->cc_proto); 1937 TRACE_DEBUG(INFO, "Unknown protocol: %d", conn->cc_proto);
1938 ASSERT(0); 1938 ASSERT(0);
1939 return ENOTSUP; /* or EINVAL... */ 1939 return ENOTSUP; /* or EINVAL... */
1940 } 1940 }
1941 1941
1942 return 0; 1942 return 0;
1943 } 1943 }
1944 1944
1945 1945
1946 /**************************************/ 1946 /**************************************/
1949 1949
1950 /* Destroy a conn structure, and shutdown the socket */ 1950 /* Destroy a conn structure, and shutdown the socket */
1951 void fd_cnx_destroy(struct cnxctx * conn) 1951 void fd_cnx_destroy(struct cnxctx * conn)
1952 { 1952 {
1953 TRACE_ENTRY("%p", conn); 1953 TRACE_ENTRY("%p", conn);
1954 1954
1955 CHECK_PARAMS_DO(conn, return); 1955 CHECK_PARAMS_DO(conn, return);
1956 1956
1957 fd_cnx_addstate(conn, CC_STATUS_CLOSING); 1957 fd_cnx_addstate(conn, CC_STATUS_CLOSING);
1958 1958
1959 /* Initiate shutdown of the TLS session(s): call gnutls_bye(WR), then read until error */ 1959 /* Initiate shutdown of the TLS session(s): call gnutls_bye(WR), then read until error */
1960 if (fd_cnx_teststate(conn, CC_STATUS_TLS)) { 1960 if (fd_cnx_teststate(conn, CC_STATUS_TLS)) {
1961 #ifndef DISABLE_SCTP 1961 #ifndef DISABLE_SCTP
1962 int dtls = fd_cnx_uses_dtls(conn); 1962 int dtls = fd_cnx_uses_dtls(conn);
1963 if ((!dtls) && (conn->cc_sctp_para.pairs > 1)) { 1963 if ((!dtls) && (conn->cc_sctp_para.pairs > 1)) {
1983 fd_sctp3436_gnutls_deinit_others(conn); 1983 fd_sctp3436_gnutls_deinit_others(conn);
1984 if (conn->cc_tls_para.session) { 1984 if (conn->cc_tls_para.session) {
1985 GNUTLS_TRACE( gnutls_deinit(conn->cc_tls_para.session) ); 1985 GNUTLS_TRACE( gnutls_deinit(conn->cc_tls_para.session) );
1986 conn->cc_tls_para.session = NULL; 1986 conn->cc_tls_para.session = NULL;
1987 } 1987 }
1988 1988
1989 /* Destroy the wrapper (also stops the demux thread) */ 1989 /* Destroy the wrapper (also stops the demux thread) */
1990 fd_sctp3436_destroy(conn); 1990 fd_sctp3436_destroy(conn);
1991 1991
1992 } else { 1992 } else {
1993 #endif /* DISABLE_SCTP */ 1993 #endif /* DISABLE_SCTP */
2005 } 2005 }
2006 } else { 2006 } else {
2007 /* Cancel the receiver thread in case it did not already terminate */ 2007 /* Cancel the receiver thread in case it did not already terminate */
2008 CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */ ); 2008 CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */ );
2009 } 2009 }
2010 2010
2011 /* Free the resources of the TLS session */ 2011 /* Free the resources of the TLS session */
2012 if (conn->cc_tls_para.session) { 2012 if (conn->cc_tls_para.session) {
2013 GNUTLS_TRACE( gnutls_deinit(conn->cc_tls_para.session) ); 2013 GNUTLS_TRACE( gnutls_deinit(conn->cc_tls_para.session) );
2014 conn->cc_tls_para.session = NULL; 2014 conn->cc_tls_para.session = NULL;
2015 } 2015 }
2016 #ifndef DISABLE_SCTP 2016 #ifndef DISABLE_SCTP
2017 } 2017 }
2018 #endif /* DISABLE_SCTP */ 2018 #endif /* DISABLE_SCTP */
2019 } 2019 }
2020 2020
2021 /* Terminate the thread in case it is not done yet -- is there any such case left ?*/ 2021 /* Terminate the thread in case it is not done yet -- is there any such case left ?*/
2022 CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */ ); 2022 CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */ );
2023 2023
2024 /* Shut the connection down */ 2024 /* Shut the connection down */
2025 if (conn->cc_socket > 0) { 2025 if (conn->cc_socket > 0) {
2026 shutdown(conn->cc_socket, SHUT_RDWR); 2026 shutdown(conn->cc_socket, SHUT_RDWR);
2027 close(conn->cc_socket); 2027 close(conn->cc_socket);
2028 conn->cc_socket = -1; 2028 conn->cc_socket = -1;
2029 } 2029 }
2030 2030
2031 /* Empty and destroy FIFO list */ 2031 /* Empty and destroy FIFO list */
2032 if (conn->cc_incoming) { 2032 if (conn->cc_incoming) {
2033 fd_event_destroy( &conn->cc_incoming, free ); 2033 fd_event_destroy( &conn->cc_incoming, free );
2034 } 2034 }
2035 2035
2036 /* Free the object */ 2036 /* Free the object */
2037 free(conn); 2037 free(conn);
2038 2038
2039 /* Done! */ 2039 /* Done! */
2040 return; 2040 return;
2041 } 2041 }
"Welcome to our mercurial repository"