socket.c (27232B)
1 /* 2 * Claws Mail -- a GTK based, lightweight, and fast e-mail client 3 * Copyright (C) 1999-2022 the Claws Mail team and Hiroyuki Yamamoto 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #include <glib.h> 20 #include <glib/gi18n.h> 21 22 #include <sys/time.h> 23 #include <sys/types.h> 24 #include <sys/wait.h> 25 #include <sys/socket.h> 26 #include <sys/stat.h> 27 #include <sys/un.h> 28 #include <netinet/in.h> 29 #include <arpa/inet.h> 30 #include <netdb.h> 31 #include <unistd.h> 32 #include <stdio.h> 33 #include <string.h> 34 #include <stdarg.h> 35 #include <fcntl.h> 36 #include <errno.h> 37 #include <signal.h> 38 #include <setjmp.h> 39 #if HAVE_SYS_SELECT_H 40 # include <sys/select.h> 41 #endif 42 43 #include "socket.h" 44 #include "utils.h" 45 #include "log.h" 46 #include "ssl.h" 47 48 #if USE_GIO 49 #error USE_GIO is currently not supported 50 #endif 51 52 #define BUFFSIZE 8192 53 54 typedef gint (*SockAddrFunc) (GList *addr_list, 55 gpointer data); 56 57 typedef struct _SockConnectData SockConnectData; 58 typedef struct _SockLookupData SockLookupData; 59 typedef struct _SockAddrData SockAddrData; 60 typedef struct _SockSource SockSource; 61 62 struct _SockConnectData { 63 gint id; 64 gchar *hostname; 65 gushort port; 66 GList *addr_list; 67 GList *cur_addr; 68 SockLookupData *lookup_data; 69 GIOChannel *channel; 70 guint io_tag; 71 SockConnectFunc func; 72 gpointer data; 73 gchar *canonical_name; 74 }; 75 76 struct _SockLookupData { 77 gchar *hostname; 78 pid_t child_pid; 79 GIOChannel *channel; 80 guint io_tag; 81 SockAddrFunc func; 82 gpointer data; 83 gushort port; 84 gint pipe_fds[2]; 85 gchar *canonical_name; 86 }; 87 88 struct _SockAddrData { 89 gint family; 90 gint socktype; 91 gint protocol; 92 gint addr_len; 93 struct sockaddr *addr; 94 }; 95 96 struct _SockSource { 97 GSource parent; 98 SockInfo *sock; 99 }; 100 101 static guint io_timeout = 60; 102 103 static GList *sock_connect_data_list = NULL; 104 105 static gboolean ssl_sock_prepare (GSource *source, 106 gint *timeout); 107 static gboolean ssl_sock_check (GSource *source); 108 static gboolean ssl_sock_dispatch (GSource *source, 109 GSourceFunc callback, 110 gpointer user_data); 111 GSourceFuncs ssl_watch_funcs = { 112 ssl_sock_prepare, 113 ssl_sock_check, 114 ssl_sock_dispatch, 115 NULL, 116 NULL, 117 NULL 118 }; 119 120 static gint sock_connect_with_timeout (gint sock, 121 const struct sockaddr *serv_addr, 122 gint addrlen, 123 guint timeout_secs); 124 125 static gint sock_connect_by_getaddrinfo (const gchar *hostname, 126 gushort port); 127 128 static SockInfo *sockinfo_from_fd(const gchar *hostname, 129 gushort port, 130 gint sock); 131 static void sock_address_list_free (GList *addr_list); 132 133 static gboolean sock_connect_async_cb (GIOChannel *source, 134 GIOCondition condition, 135 gpointer data); 136 static gint sock_connect_async_get_address_info_cb 137 (GList *addr_list, 138 gpointer data); 139 140 static gint sock_connect_address_list_async (SockConnectData *conn_data); 141 142 static gboolean sock_get_address_info_async_cb (GIOChannel *source, 143 GIOCondition condition, 144 gpointer data); 145 static SockLookupData *sock_get_address_info_async 146 (const gchar *hostname, 147 gushort port, 148 SockAddrFunc func, 149 gpointer data); 150 static gint sock_get_address_info_async_cancel (SockLookupData *lookup_data); 151 152 gint sock_set_io_timeout(guint sec) 153 { 154 io_timeout = sec; 155 return 0; 156 } 157 158 #define SOCKET_IS_VALID(s) (s != -1) 159 160 gint fd_connect_unix(const gchar *path) 161 { 162 #ifdef G_OS_UNIX 163 gint sock; 164 struct sockaddr_un addr; 165 166 sock = socket(PF_UNIX, SOCK_STREAM, 0); 167 if (sock < 0) { 168 perror("sock_connect_unix(): socket"); 169 return -1; 170 } 171 172 memset(&addr, 0, sizeof(addr)); 173 addr.sun_family = AF_UNIX; 174 strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1); 175 176 if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 177 close(sock); 178 return -1; 179 } 180 181 return sock; 182 #else 183 return -1; 184 #endif 185 } 186 187 gint fd_open_unix(const gchar *path) 188 { 189 #ifdef G_OS_UNIX 190 gint sock; 191 struct sockaddr_un addr; 192 193 sock = socket(PF_UNIX, SOCK_STREAM, 0); 194 195 if (sock < 0) { 196 perror("sock_open_unix(): socket"); 197 return -1; 198 } 199 200 memset(&addr, 0, sizeof(addr)); 201 addr.sun_family = AF_UNIX; 202 strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1); 203 204 if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 205 gchar *buf = g_strdup_printf("can't bind to %s", path); 206 perror(buf); 207 g_free(buf); 208 close(sock); 209 return -1; 210 } 211 212 if (listen(sock, 1) < 0) { 213 gchar *buf = g_strdup_printf("can't listen on %s", path); 214 perror(buf); 215 g_free(buf); 216 close(sock); 217 return -1; 218 } 219 220 return sock; 221 #else 222 return -1; 223 #endif 224 } 225 226 gint fd_accept(gint sock) 227 { 228 struct sockaddr_in caddr; 229 guint caddr_len; 230 231 caddr_len = sizeof(caddr); 232 return accept(sock, (struct sockaddr *)&caddr, &caddr_len); 233 } 234 235 236 static gint set_nonblocking_mode(gint fd, gboolean nonblock) 237 { 238 #ifdef G_OS_UNIX 239 gint flags; 240 241 flags = fcntl(fd, F_GETFL, 0); 242 if (flags < 0) { 243 perror("fcntl"); 244 return -1; 245 } 246 247 if (nonblock) 248 flags |= O_NONBLOCK; 249 else 250 flags &= ~O_NONBLOCK; 251 252 return fcntl(fd, F_SETFL, flags); 253 #else 254 return -1; 255 #endif 256 } 257 258 gint sock_set_nonblocking_mode(SockInfo *sock, gboolean nonblock) 259 { 260 cm_return_val_if_fail(sock != NULL, -1); 261 262 return set_nonblocking_mode(sock->sock, nonblock); 263 } 264 265 static gboolean is_nonblocking_mode(gint fd) 266 { 267 #ifdef G_OS_UNIX 268 gint flags; 269 270 flags = fcntl(fd, F_GETFL, 0); 271 if (flags < 0) { 272 perror("fcntl"); 273 return FALSE; 274 } 275 276 return ((flags & O_NONBLOCK) != 0); 277 #else 278 return FALSE; 279 #endif 280 } 281 282 gboolean sock_is_nonblocking_mode(SockInfo *sock) 283 { 284 cm_return_val_if_fail(sock != NULL, FALSE); 285 286 return is_nonblocking_mode(sock->sock); 287 } 288 289 290 static gboolean ssl_sock_prepare(GSource *source, gint *timeout) 291 { 292 *timeout = 1; 293 return FALSE; 294 } 295 296 static gboolean ssl_sock_check(GSource *source) 297 { 298 SockInfo *sock = ((SockSource *)source)->sock; 299 struct timeval timeout = {0, 0}; 300 fd_set fds; 301 GIOCondition condition = 0; 302 303 if (!sock || !sock->sock) 304 return FALSE; 305 306 condition = sock->condition; 307 308 if ((condition & G_IO_IN) == G_IO_IN && 309 gnutls_record_check_pending(sock->ssl) != 0) 310 return TRUE; 311 312 FD_ZERO(&fds); 313 FD_SET(sock->sock, &fds); 314 315 select(sock->sock + 1, 316 (condition & G_IO_IN) ? &fds : NULL, 317 (condition & G_IO_OUT) ? &fds : NULL, 318 NULL, &timeout); 319 320 return FD_ISSET(sock->sock, &fds) != 0; 321 } 322 323 static gboolean ssl_sock_dispatch(GSource *source, GSourceFunc callback, 324 gpointer user_data) 325 { 326 SockInfo *sock = ((SockSource *)source)->sock; 327 328 if (!sock || !sock->callback || !sock->data) 329 return FALSE; 330 331 return sock->callback(sock, sock->condition, sock->data); 332 } 333 334 static gboolean sock_watch_cb(GIOChannel *source, GIOCondition condition, 335 gpointer data) 336 { 337 SockInfo *sock = (SockInfo *)data; 338 339 if ((condition & sock->condition) == 0) 340 return TRUE; 341 342 return sock->callback(sock, sock->condition, sock->data); 343 } 344 345 guint sock_add_watch(SockInfo *sock, GIOCondition condition, SockFunc func, 346 gpointer data) 347 { 348 if (!sock) 349 return FALSE; 350 351 sock->callback = func; 352 sock->condition = condition; 353 sock->data = data; 354 355 if (sock->ssl) { 356 GSource *source = g_source_new(&ssl_watch_funcs, 357 sizeof(SockSource)); 358 ((SockSource *) source)->sock = sock; 359 g_source_set_priority(source, G_PRIORITY_DEFAULT); 360 g_source_set_can_recurse(source, FALSE); 361 sock->g_source = g_source_attach(source, NULL); 362 g_source_unref (source); /* Refcount back down to 1 */ 363 return sock->g_source; 364 } 365 366 return g_io_add_watch(sock->sock_ch, condition, sock_watch_cb, sock); 367 } 368 369 static gint fd_check_io(gint fd, GIOCondition cond) 370 { 371 struct timeval timeout; 372 fd_set fds; 373 374 if (is_nonblocking_mode(fd)) 375 return 0; 376 377 timeout.tv_sec = io_timeout; 378 timeout.tv_usec = 0; 379 380 FD_ZERO(&fds); 381 FD_SET(fd, &fds); 382 383 if (cond == G_IO_IN) { 384 select(fd + 1, &fds, NULL, NULL, 385 io_timeout > 0 ? &timeout : NULL); 386 } else { 387 select(fd + 1, NULL, &fds, NULL, 388 io_timeout > 0 ? &timeout : NULL); 389 } 390 391 if (FD_ISSET(fd, &fds)) { 392 return 0; 393 } else { 394 g_warning("socket IO timeout"); 395 log_error(LOG_PROTOCOL, "Socket IO timeout.\n"); 396 return -1; 397 } 398 } 399 400 #ifdef G_OS_UNIX 401 static sigjmp_buf jmpenv; 402 403 static void timeout_handler(gint sig) 404 { 405 siglongjmp(jmpenv, 1); 406 } 407 #endif /*G_OS_UNIX*/ 408 409 static gint sock_connect_with_timeout(gint sock, 410 const struct sockaddr *serv_addr, 411 gint addrlen, 412 guint timeout_secs) 413 { 414 gint ret, saved_errno; 415 #ifdef G_OS_UNIX 416 void (*prev_handler)(gint); 417 418 alarm(0); 419 prev_handler = signal(SIGALRM, timeout_handler); 420 if (sigsetjmp(jmpenv, 1)) { 421 alarm(0); 422 signal(SIGALRM, prev_handler); 423 errno = ETIMEDOUT; 424 log_error(LOG_PROTOCOL, "Connection timed out.\n"); 425 return -1; 426 } 427 alarm(timeout_secs); 428 #endif 429 430 ret = connect(sock, serv_addr, addrlen); 431 saved_errno = errno; 432 433 if (ret == -1) { 434 debug_print("connect() failed: %d (%s)\n", 435 saved_errno, g_strerror(saved_errno)); 436 } 437 438 #ifdef G_OS_UNIX 439 alarm(0); 440 signal(SIGALRM, prev_handler); 441 #endif 442 443 return ret; 444 } 445 446 static gint sock_connect_by_getaddrinfo(const gchar *hostname, gushort port) 447 { 448 gint sock = -1, gai_error; 449 struct addrinfo hints, *res, *ai; 450 gchar port_str[6]; 451 452 memset(&hints, 0, sizeof(hints)); 453 hints.ai_flags = AI_ADDRCONFIG; 454 hints.ai_family = AF_UNSPEC; 455 hints.ai_socktype = SOCK_STREAM; 456 hints.ai_protocol = IPPROTO_TCP; 457 458 /* convert port from integer to string. */ 459 g_snprintf(port_str, sizeof(port_str), "%d", port); 460 461 if ((gai_error = getaddrinfo(hostname, port_str, &hints, &res)) != 0) { 462 g_printerr("getaddrinfo for %s:%s failed: %s\n", 463 hostname, port_str, gai_strerror(gai_error)); 464 return -1; 465 } 466 467 for (ai = res; ai != NULL; ai = ai->ai_next) { 468 sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); 469 if (sock < 0 ) 470 continue; 471 if (sock_connect_with_timeout 472 (sock, ai->ai_addr, ai->ai_addrlen, io_timeout) == 0) 473 break; 474 475 close(sock); 476 } 477 478 if (res != NULL) 479 freeaddrinfo(res); 480 481 if (ai == NULL) 482 return -1; 483 484 return sock; 485 } 486 487 SockInfo *sock_connect(const gchar *hostname, gushort port) 488 { 489 gint sock; 490 491 if ((sock = sock_connect_by_getaddrinfo(hostname, port)) < 0) { 492 return NULL; 493 } 494 495 return sockinfo_from_fd(hostname, port, sock); 496 } 497 498 499 static void sock_address_list_free(GList *addr_list) 500 { 501 GList *cur; 502 503 for (cur = addr_list; cur != NULL; cur = cur->next) { 504 SockAddrData *addr_data = (SockAddrData *)cur->data; 505 g_free(addr_data->addr); 506 g_free(addr_data); 507 } 508 509 g_list_free(addr_list); 510 } 511 512 /* asynchronous TCP connection */ 513 514 static gboolean sock_connect_async_cb(GIOChannel *source, 515 GIOCondition condition, gpointer data) 516 { 517 SockConnectData *conn_data = (SockConnectData *)data; 518 gint fd; 519 gint val; 520 socklen_t len; 521 SockInfo *sockinfo; 522 523 if (conn_data->io_tag == 0 && conn_data->channel == NULL) 524 return FALSE; 525 526 fd = g_io_channel_unix_get_fd(source); 527 528 conn_data->io_tag = 0; 529 conn_data->channel = NULL; 530 g_io_channel_unref(source); 531 532 len = sizeof(val); 533 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&val, &len) < 0) { 534 perror("getsockopt"); 535 close(fd); 536 sock_connect_address_list_async(conn_data); 537 return FALSE; 538 } 539 540 if (val != 0) { 541 close(fd); 542 log_error(LOG_PROTOCOL, "%s:%d: connection failed (%s).\n", 543 conn_data->hostname, conn_data->port, 544 g_strerror(val)); 545 sock_connect_address_list_async(conn_data); 546 return FALSE; 547 } 548 549 sockinfo = g_new0(SockInfo, 1); 550 sockinfo->sock = fd; 551 sockinfo->sock_ch = g_io_channel_unix_new(fd); 552 sockinfo->hostname = g_strdup(conn_data->hostname); 553 sockinfo->port = conn_data->port; 554 sockinfo->state = CONN_ESTABLISHED; 555 sockinfo->canonical_name = g_strdup(conn_data->canonical_name); 556 557 conn_data->func(sockinfo, conn_data->data); 558 559 sock_connect_async_cancel(conn_data->id); 560 561 return FALSE; 562 } 563 564 static gint sock_connect_async_get_address_info_cb(GList *addr_list, 565 gpointer data) 566 { 567 SockConnectData *conn_data = (SockConnectData *)data; 568 569 conn_data->addr_list = addr_list; 570 conn_data->cur_addr = addr_list; 571 if (conn_data->lookup_data) { 572 conn_data->canonical_name = conn_data->lookup_data->canonical_name; 573 conn_data->lookup_data->canonical_name = NULL; 574 conn_data->lookup_data = NULL; 575 } 576 return sock_connect_address_list_async(conn_data); 577 } 578 579 gint sock_connect_async(const gchar *hostname, gushort port, 580 SockConnectFunc func, gpointer data) 581 { 582 static gint id = 1; 583 SockConnectData *conn_data; 584 585 conn_data = g_new0(SockConnectData, 1); 586 conn_data->id = id++; 587 conn_data->hostname = g_strdup(hostname); 588 conn_data->port = port; 589 conn_data->addr_list = NULL; 590 conn_data->cur_addr = NULL; 591 conn_data->io_tag = 0; 592 conn_data->func = func; 593 conn_data->data = data; 594 595 conn_data->lookup_data = sock_get_address_info_async 596 (hostname, port, sock_connect_async_get_address_info_cb, 597 conn_data); 598 599 if (conn_data->lookup_data == NULL) { 600 g_free(conn_data->hostname); 601 g_free(conn_data); 602 return -1; 603 } 604 605 sock_connect_data_list = g_list_append(sock_connect_data_list, 606 conn_data); 607 608 return conn_data->id; 609 } 610 611 gint sock_connect_async_cancel(gint id) 612 { 613 SockConnectData *conn_data = NULL; 614 GList *cur; 615 616 for (cur = sock_connect_data_list; cur != NULL; cur = cur->next) { 617 if (((SockConnectData *)cur->data)->id == id) { 618 conn_data = (SockConnectData *)cur->data; 619 break; 620 } 621 } 622 623 if (conn_data) { 624 sock_connect_data_list = g_list_remove(sock_connect_data_list, 625 conn_data); 626 627 if (conn_data->lookup_data) 628 sock_get_address_info_async_cancel 629 (conn_data->lookup_data); 630 631 if (conn_data->io_tag > 0) 632 g_source_remove(conn_data->io_tag); 633 if (conn_data->channel) { 634 GError *err = NULL; 635 g_io_channel_shutdown(conn_data->channel, TRUE, &err); 636 if (err) 637 g_error_free(err); 638 g_io_channel_unref(conn_data->channel); 639 } 640 641 sock_address_list_free(conn_data->addr_list); 642 g_free(conn_data->canonical_name); 643 g_free(conn_data->hostname); 644 g_free(conn_data); 645 } else { 646 g_warning("sock_connect_async_cancel: id %d not found", id); 647 return -1; 648 } 649 650 return 0; 651 } 652 653 static gint sock_connect_address_list_async(SockConnectData *conn_data) 654 { 655 SockAddrData *addr_data; 656 gint sock = -1; 657 658 for (; conn_data->cur_addr != NULL; 659 conn_data->cur_addr = conn_data->cur_addr->next) { 660 addr_data = (SockAddrData *)conn_data->cur_addr->data; 661 662 if ((sock = socket(addr_data->family, addr_data->socktype, 663 addr_data->protocol)) < 0) { 664 perror("socket"); 665 666 continue; 667 } 668 669 set_nonblocking_mode(sock, TRUE); 670 671 if (connect(sock, addr_data->addr, addr_data->addr_len) < 0) { 672 if (EINPROGRESS == errno) { 673 break; 674 } else { 675 perror("connect"); 676 close(sock); 677 } 678 } else { 679 break; 680 } 681 } 682 683 if (conn_data->cur_addr == NULL) { 684 conn_data->func(NULL, conn_data->data); 685 sock_connect_async_cancel(conn_data->id); 686 return -1; 687 } 688 689 conn_data->cur_addr = conn_data->cur_addr->next; 690 conn_data->channel = g_io_channel_unix_new(sock); 691 conn_data->io_tag = g_io_add_watch(conn_data->channel, G_IO_IN|G_IO_OUT, 692 sock_connect_async_cb, conn_data); 693 694 return 0; 695 } 696 697 /* asynchronous DNS lookup */ 698 699 static gboolean sock_get_address_info_async_cb(GIOChannel *source, 700 GIOCondition condition, 701 gpointer data) 702 { 703 SockLookupData *lookup_data = (SockLookupData *)data; 704 GList *addr_list = NULL; 705 SockAddrData *addr_data; 706 gsize bytes_read; 707 gint ai_member[4]; 708 struct sockaddr *addr; 709 gchar *canonical_name = NULL; 710 gchar len = 0; 711 GError *err = NULL; 712 713 g_io_channel_set_encoding(source, NULL, &err); 714 if (err) { 715 g_warning("can't unset encoding: %s", err->message); 716 g_error_free(err); 717 return FALSE; 718 } 719 g_io_channel_set_buffered(source, FALSE); 720 if (g_io_channel_read_chars(source, &len, sizeof(len), 721 &bytes_read, &err) == G_IO_STATUS_NORMAL) { 722 if (err != NULL) { 723 g_warning("g_io_channel_read_chars: %s", err->message); 724 g_error_free(err); 725 return FALSE; 726 } 727 if (bytes_read == sizeof(len) && len > 0) { 728 gchar *cur = NULL; 729 gint todo = len; 730 canonical_name = g_malloc0(len + 1); 731 cur = canonical_name; 732 while (todo > 0) { 733 if (g_io_channel_read_chars(source, cur, todo, 734 &bytes_read, &err) != G_IO_STATUS_NORMAL) { 735 if (err) { 736 g_warning("canonical name not read %s", err->message); 737 g_free(canonical_name); 738 canonical_name = NULL; 739 g_error_free(err); 740 err = NULL; 741 break; 742 } 743 } else { 744 cur += bytes_read; 745 todo -= bytes_read; 746 } 747 if (bytes_read == 0) { 748 g_warning("canonical name not read"); 749 g_free(canonical_name); 750 canonical_name = NULL; 751 break; 752 } 753 } 754 } 755 } 756 for (;;) { 757 if (g_io_channel_read_chars(source, (gchar *)ai_member, 758 sizeof(ai_member), &bytes_read, &err) 759 != G_IO_STATUS_NORMAL) { 760 if (err != NULL) { 761 g_warning("g_io_channel_read_chars: addr len %s", err->message); 762 g_error_free(err); 763 err = NULL; 764 break; 765 } 766 } 767 768 if (bytes_read == 0 || bytes_read != sizeof(ai_member)) 769 break; 770 771 if (ai_member[0] == AF_UNSPEC) { 772 g_warning("DNS lookup failed"); 773 log_error(LOG_PROTOCOL, "%s:%d: unknown host.\n", 774 lookup_data->hostname, lookup_data->port); 775 break; 776 } 777 778 addr = g_malloc(ai_member[3]); 779 if (g_io_channel_read_chars(source, (gchar *)addr, ai_member[3], 780 &bytes_read, &err) 781 != G_IO_STATUS_NORMAL) { 782 if (err != NULL) { 783 g_warning("g_io_channel_read_chars: addr data read %s", err->message); 784 g_error_free(err); 785 err = NULL; 786 g_free(addr); 787 break; 788 } 789 } 790 791 if (bytes_read != ai_member[3]) { 792 g_warning("sock_get_address_info_async_cb: " 793 "incomplete address data"); 794 g_free(addr); 795 break; 796 } 797 798 addr_data = g_new0(SockAddrData, 1); 799 addr_data->family = ai_member[0]; 800 addr_data->socktype = ai_member[1]; 801 addr_data->protocol = ai_member[2]; 802 addr_data->addr_len = ai_member[3]; 803 addr_data->addr = addr; 804 805 addr_list = g_list_append(addr_list, addr_data); 806 } 807 808 g_io_channel_shutdown(source, TRUE, &err); 809 if (err) 810 g_error_free(err); 811 g_io_channel_unref(source); 812 813 kill(lookup_data->child_pid, SIGKILL); 814 waitpid(lookup_data->child_pid, NULL, 0); 815 816 lookup_data->canonical_name = canonical_name; 817 818 lookup_data->func(addr_list, lookup_data->data); 819 820 g_free(lookup_data->canonical_name); 821 g_free(lookup_data->hostname); 822 g_free(lookup_data); 823 824 return FALSE; 825 } 826 827 828 /* For better readability we use a separate function to implement the 829 child code of sock_get_address_info_async. Note, that under W32 830 this is actually not a child but a thread and this is the reason 831 why we pass only a void pointer. */ 832 static void address_info_async_child(void *opaque) 833 { 834 SockLookupData *parm = opaque; 835 gint gai_err; 836 struct addrinfo hints, *res, *ai; 837 gchar port_str[6]; 838 gint ai_member[4] = {AF_UNSPEC, 0, 0, 0}; 839 840 close(parm->pipe_fds[0]); 841 parm->pipe_fds[0] = -1; 842 843 memset(&hints, 0, sizeof(hints)); 844 hints.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; 845 hints.ai_family = AF_UNSPEC; 846 hints.ai_socktype = SOCK_STREAM; 847 hints.ai_protocol = IPPROTO_TCP; 848 849 g_snprintf(port_str, sizeof(port_str), "%d", parm->port); 850 851 gai_err = getaddrinfo(parm->hostname, port_str, &hints, &res); 852 if (gai_err != 0) { 853 gchar len = 0; 854 g_warning("getaddrinfo for %s:%s failed: %s", 855 parm->hostname, port_str, gai_strerror(gai_err)); 856 log_error(LOG_PROTOCOL, "%s:%s: host lookup failed (%s).\n", 857 parm->hostname, port_str, gai_strerror(gai_err)); 858 fd_write_all(parm->pipe_fds[1], &len, 859 sizeof(len)); 860 fd_write_all(parm->pipe_fds[1], (gchar *)ai_member, 861 sizeof(ai_member)); 862 close(parm->pipe_fds[1]); 863 parm->pipe_fds[1] = -1; 864 865 _exit(1); 866 } 867 868 if (res != NULL) { 869 if (res->ai_canonname && strlen(res->ai_canonname) < 255) { 870 gchar len = strlen(res->ai_canonname); 871 fd_write_all(parm->pipe_fds[1], &len, 872 sizeof(len)); 873 fd_write_all(parm->pipe_fds[1], res->ai_canonname, 874 len); 875 } else { 876 gchar len = 0; 877 fd_write_all(parm->pipe_fds[1], &len, 878 sizeof(len)); 879 } 880 } else { 881 gchar len = 0; 882 fd_write_all(parm->pipe_fds[1], &len, 883 sizeof(len)); 884 } 885 886 for (ai = res; ai != NULL; ai = ai->ai_next) { 887 ai_member[0] = ai->ai_family; 888 ai_member[1] = ai->ai_socktype; 889 ai_member[2] = ai->ai_protocol; 890 ai_member[3] = ai->ai_addrlen; 891 892 fd_write_all(parm->pipe_fds[1], (gchar *)ai_member, 893 sizeof(ai_member)); 894 fd_write_all(parm->pipe_fds[1], (gchar *)ai->ai_addr, 895 ai->ai_addrlen); 896 } 897 898 if (res != NULL) 899 freeaddrinfo(res); 900 901 close(parm->pipe_fds[1]); 902 parm->pipe_fds[1] = -1; 903 904 _exit(0); 905 } 906 907 static SockLookupData *sock_get_address_info_async(const gchar *hostname, 908 gushort port, 909 SockAddrFunc func, 910 gpointer data) 911 { 912 SockLookupData *lookup_data = NULL; 913 914 lookup_data = g_new0(SockLookupData, 1); 915 lookup_data->hostname = g_strdup(hostname); 916 lookup_data->func = func; 917 lookup_data->data = data; 918 lookup_data->port = port; 919 lookup_data->child_pid = (pid_t)(-1); 920 lookup_data->pipe_fds[0] = -1; 921 lookup_data->pipe_fds[1] = -1; 922 923 if (pipe(lookup_data->pipe_fds) < 0) { 924 perror("pipe"); 925 func(NULL, data); 926 g_free (lookup_data->hostname); 927 g_free (lookup_data); 928 return NULL; 929 } 930 931 if ((lookup_data->child_pid = fork()) < 0) { 932 perror("fork"); 933 func(NULL, data); 934 g_free (lookup_data->hostname); 935 g_free (lookup_data); 936 return NULL; 937 } 938 939 if (lookup_data->child_pid == 0) { 940 /* Child process. */ 941 address_info_async_child (lookup_data); 942 g_assert_not_reached (); 943 } 944 /* Parent process. */ 945 close(lookup_data->pipe_fds[1]); 946 lookup_data->pipe_fds[1] = -1; 947 948 lookup_data->channel = g_io_channel_unix_new(lookup_data->pipe_fds[0]); 949 lookup_data->io_tag = g_io_add_watch(lookup_data->channel, G_IO_IN, 950 sock_get_address_info_async_cb, 951 lookup_data); 952 return lookup_data; 953 } 954 955 static gint sock_get_address_info_async_cancel(SockLookupData *lookup_data) 956 { 957 if (lookup_data->io_tag > 0) 958 g_source_remove(lookup_data->io_tag); 959 if (lookup_data->channel) { 960 GError *err = NULL; 961 g_io_channel_shutdown(lookup_data->channel, TRUE, &err); 962 if (err) 963 g_error_free(err); 964 965 g_io_channel_unref(lookup_data->channel); 966 } 967 968 if (lookup_data->child_pid > 0) { 969 kill(lookup_data->child_pid, SIGKILL); 970 waitpid(lookup_data->child_pid, NULL, 0); 971 } 972 973 g_free(lookup_data->canonical_name); 974 g_free(lookup_data->hostname); 975 g_free(lookup_data); 976 977 return 0; 978 } 979 980 981 static SockInfo *sockinfo_from_fd(const gchar *hostname, 982 gushort port, 983 gint sock) 984 { 985 SockInfo *sockinfo; 986 987 sockinfo = g_new0(SockInfo, 1); 988 sockinfo->sock = sock; 989 sockinfo->sock_ch = g_io_channel_unix_new(sock); 990 sockinfo->hostname = g_strdup(hostname); 991 sockinfo->port = port; 992 sockinfo->state = CONN_ESTABLISHED; 993 994 return sockinfo; 995 } 996 997 static gint fd_read(gint fd, gchar *buf, gint len) 998 { 999 if (fd_check_io(fd, G_IO_IN) < 0) 1000 return -1; 1001 return read(fd, buf, len); 1002 } 1003 1004 static gint ssl_read(gnutls_session_t ssl, gchar *buf, gint len) 1005 { 1006 gint r; 1007 1008 if (gnutls_record_check_pending(ssl) == 0) { 1009 if (fd_check_io(GPOINTER_TO_INT(gnutls_transport_get_ptr(ssl)), G_IO_IN) < 0) 1010 return -1; 1011 } 1012 1013 while (1) { 1014 errno = 0; 1015 r = gnutls_record_recv(ssl, buf, len); 1016 if (r > 0) 1017 return r; 1018 1019 switch (r) { 1020 case 0: /* closed connection */ 1021 return -1; 1022 1023 case GNUTLS_E_REHANDSHAKE: 1024 do { 1025 r = gnutls_handshake(ssl); 1026 } while (r == GNUTLS_E_AGAIN || r == GNUTLS_E_INTERRUPTED); 1027 break; /* re-receive */ 1028 case GNUTLS_E_AGAIN: 1029 case GNUTLS_E_INTERRUPTED: 1030 errno = EAGAIN; 1031 return -1; 1032 case GNUTLS_E_PREMATURE_TERMINATION: 1033 if (errno == 0) 1034 return 0; 1035 /* fall through */ 1036 default: 1037 debug_print("Unexpected TLS read result %d\n", r); 1038 errno = EIO; 1039 return -1; 1040 } 1041 } 1042 1043 } 1044 1045 gint sock_read(SockInfo *sock, gchar *buf, gint len) 1046 { 1047 gint ret; 1048 1049 cm_return_val_if_fail(sock != NULL, -1); 1050 1051 if (sock->ssl) 1052 ret = ssl_read(sock->ssl, buf, len); 1053 else 1054 ret = fd_read(sock->sock, buf, len); 1055 1056 if (ret < 0) 1057 sock->state = CONN_DISCONNECTED; 1058 return ret; 1059 } 1060 1061 gint fd_write(gint fd, const gchar *buf, gint len) 1062 { 1063 if (fd_check_io(fd, G_IO_OUT) < 0) 1064 return -1; 1065 return write(fd, buf, len); 1066 } 1067 1068 static gint ssl_write(gnutls_session_t ssl, const gchar *buf, gint len) 1069 { 1070 gint ret; 1071 1072 if (fd_check_io(GPOINTER_TO_INT(gnutls_transport_get_ptr(ssl)), G_IO_OUT) < 0) 1073 return -1; 1074 1075 ret = gnutls_record_send(ssl, buf, len); 1076 1077 switch (ret) { 1078 case 0: 1079 return -1; 1080 case GNUTLS_E_AGAIN: 1081 case GNUTLS_E_INTERRUPTED: 1082 return 0; 1083 1084 default: 1085 return ret; 1086 } 1087 } 1088 1089 gint sock_write(SockInfo *sock, const gchar *buf, gint len) 1090 { 1091 gint ret; 1092 1093 cm_return_val_if_fail(sock != NULL, -1); 1094 1095 if (sock->ssl) 1096 ret = ssl_write(sock->ssl, buf, len); 1097 else 1098 ret = fd_write(sock->sock, buf, len); 1099 1100 if (ret < 0) 1101 sock->state = CONN_DISCONNECTED; 1102 return ret; 1103 } 1104 1105 gint fd_write_all(gint fd, const gchar *buf, gint len) 1106 { 1107 gint n, wrlen = 0; 1108 1109 while (len) { 1110 if (fd_check_io(fd, G_IO_OUT) < 0) 1111 return -1; 1112 signal(SIGPIPE, SIG_IGN); 1113 n = write(fd, buf, len); 1114 1115 if (n <= 0) { 1116 log_error(LOG_PROTOCOL, "write on fd%d: %s\n", fd, g_strerror(errno)); 1117 return -1; 1118 } 1119 len -= n; 1120 wrlen += n; 1121 buf += n; 1122 } 1123 1124 return wrlen; 1125 } 1126 1127 static gint ssl_write_all(gnutls_session_t ssl, const gchar *buf, gint len) 1128 { 1129 gint n, wrlen = 0; 1130 1131 while (len) { 1132 n = ssl_write(ssl, buf, len); 1133 if (n <= 0) 1134 return -1; 1135 len -= n; 1136 wrlen += n; 1137 buf += n; 1138 } 1139 1140 return wrlen; 1141 } 1142 1143 gint sock_write_all(SockInfo *sock, const gchar *buf, gint len) 1144 { 1145 gint ret; 1146 1147 cm_return_val_if_fail(sock != NULL, -1); 1148 1149 if (sock->ssl) 1150 ret = ssl_write_all(sock->ssl, buf, len); 1151 else 1152 ret = fd_write_all(sock->sock, buf, len); 1153 1154 if (ret < 0) 1155 sock->state = CONN_DISCONNECTED; 1156 return ret; 1157 } 1158 1159 gint fd_gets(gint fd, gchar *buf, gint len) 1160 { 1161 gchar *bp = buf; 1162 1163 if (--len < 1) 1164 return -1; 1165 *bp = '\0'; 1166 return bp - buf; 1167 } 1168 1169 gint sock_close(SockInfo *sock, gboolean close_fd) 1170 { 1171 gint ret = 0; 1172 1173 if (!sock) 1174 return 0; 1175 1176 if (sock->sock_ch) 1177 g_io_channel_unref(sock->sock_ch); 1178 1179 if (sock->ssl) 1180 ssl_done_socket(sock); 1181 if (sock->g_source != 0 && g_main_context_find_source_by_id(NULL, sock->g_source) != NULL) 1182 g_source_remove(sock->g_source); 1183 sock->g_source = 0; 1184 if (close_fd) 1185 ret = close(sock->sock); 1186 1187 g_free(sock->canonical_name); 1188 g_free(sock->hostname); 1189 g_free(sock); 1190 1191 return ret; 1192 }