net.c revision 1.5
1/* $OpenBSD: net.c,v 1.5 2005/05/24 02:35:39 ho Exp $ */ 2 3/* 4 * Copyright (c) 2005 H�kan Olsson. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28/* 29 * This code was written under funding by Multicom Security AB. 30 */ 31 32 33#include <sys/types.h> 34#include <sys/socket.h> 35#include <sys/time.h> 36#include <netinet/in.h> 37#include <arpa/inet.h> 38#include <ifaddrs.h> 39#include <netdb.h> 40 41#include <openssl/aes.h> 42#include <openssl/sha.h> 43 44#include <errno.h> 45#include <stdio.h> 46#include <stdlib.h> 47#include <string.h> 48#include <unistd.h> 49 50#include "sasyncd.h" 51#include "net.h" 52 53struct msg { 54 u_int8_t *buf; 55 u_int32_t len; 56 int refcnt; 57}; 58 59struct qmsg { 60 SIMPLEQ_ENTRY(qmsg) next; 61 struct msg *msg; 62}; 63 64int listen_socket; 65AES_KEY aes_key[2]; 66#define AES_IV_LEN AES_BLOCK_SIZE 67 68/* We never send (or expect to receive) messages smaller/larger than this. */ 69#define MSG_MINLEN 12 70#define MSG_MAXLEN 4096 71 72/* Local prototypes. */ 73static u_int8_t *net_read(struct syncpeer *, u_int32_t *, u_int32_t *); 74static int net_set_sa(struct sockaddr *, char *, in_port_t); 75static void net_check_peers(void *); 76 77/* Pretty-print a buffer. */ 78void 79dump_buf(int lvl, u_int8_t *b, u_int32_t len, char *title) 80{ 81 u_int32_t i, off, blen; 82 u_int8_t *buf; 83 const char def[] = "Buffer:"; 84 85 if (cfgstate.verboselevel < lvl) 86 return; 87 88 blen = 2 * (len + len / 36) + 3 + (title ? strlen(title) : sizeof def); 89 if (!(buf = (u_int8_t *)calloc(1, blen))) 90 return; 91 92 snprintf(buf, blen, "%s\n ", title ? title : def); 93 off = strlen(buf); 94 for (i = 0; i < len; i++, off+=2) { 95 snprintf(buf + off, blen - off, "%02x", b[i]); 96 if ((i+1) % 36 == 0) { 97 off += 2; 98 snprintf(buf + off, blen - off, "\n "); 99 } 100 } 101 log_msg(lvl, "%s", buf); 102 free(buf); 103} 104 105int 106net_init(void) 107{ 108 struct sockaddr_storage sa_storage; 109 struct sockaddr *sa = (struct sockaddr *)&sa_storage; 110 struct syncpeer *p; 111 char host[NI_MAXHOST], port[NI_MAXSERV]; 112 int r; 113 114 /* The shared key needs to be 128, 192 or 256 bits */ 115 r = strlen(cfgstate.sharedkey) << 3; 116 if (r != 128 && r != 192 && r != 256) { 117 fprintf(stderr, "Bad shared key length (%d bits), " 118 "should be 128, 192 or 256\n", r); 119 return -1; 120 } 121 122 if (AES_set_encrypt_key(cfgstate.sharedkey, r, &aes_key[0]) || 123 AES_set_decrypt_key(cfgstate.sharedkey, r, &aes_key[1])) { 124 fprintf(stderr, "Bad AES shared key\n"); 125 return -1; 126 } 127 128 /* Setup listening socket. */ 129 memset(&sa_storage, 0, sizeof sa_storage); 130 if (net_set_sa(sa, cfgstate.listen_on, cfgstate.listen_port)) { 131 log_msg(0, "net_init: could not find listen address (%s)", 132 cfgstate.listen_on); 133 return -1; 134 } 135 136 listen_socket = socket(sa->sa_family, SOCK_STREAM, 0); 137 if (listen_socket < 0) { 138 perror("socket()"); 139 close(listen_socket); 140 return -1; 141 } 142 r = 1; 143 if (setsockopt(listen_socket, SOL_SOCKET, 144 cfgstate.listen_on ? SO_REUSEADDR : SO_REUSEPORT, (void *)&r, 145 sizeof r)) { 146 perror("setsockopt()"); 147 close(listen_socket); 148 return -1; 149 } 150 if (bind(listen_socket, sa, sizeof(struct sockaddr_in))) { 151 perror("bind()"); 152 close(listen_socket); 153 return -1; 154 } 155 if (listen(listen_socket, 10)) { 156 perror("listen()"); 157 close(listen_socket); 158 return -1; 159 } 160 161 if (getnameinfo(sa, sa->sa_len, host, sizeof host, port, sizeof port, 162 NI_NUMERICHOST | NI_NUMERICSERV)) 163 log_msg(2, "listening on port %u fd %d", cfgstate.listen_port, 164 listen_socket); 165 else 166 log_msg(2, "listening on %s port %s fd %d", host, port, 167 listen_socket); 168 169 for (p = LIST_FIRST(&cfgstate.peerlist); p; p = LIST_NEXT(p, link)) { 170 p->socket = -1; 171 SIMPLEQ_INIT(&p->msgs); 172 } 173 174 net_check_peers(0); 175 return 0; 176} 177 178static void 179net_enqueue(struct syncpeer *p, struct msg *m) 180{ 181 struct qmsg *qm; 182 183 if (p->socket < 0) 184 return; 185 186 qm = (struct qmsg *)malloc(sizeof *qm); 187 if (!qm) { 188 log_err("malloc()"); 189 return; 190 } 191 192 memset(qm, 0, sizeof *qm); 193 qm->msg = m; 194 m->refcnt++; 195 196 SIMPLEQ_INSERT_TAIL(&p->msgs, qm, next); 197 return; 198} 199 200/* 201 * Queue a message for transmission to a particular peer, 202 * or to all peers if no peer is specified. 203 */ 204int 205net_queue(struct syncpeer *p0, u_int32_t msgtype, u_int8_t *buf, u_int32_t len) 206{ 207 struct syncpeer *p = p0; 208 struct msg *m; 209 SHA_CTX ctx; 210 u_int8_t hash[SHA_DIGEST_LENGTH]; 211 u_int8_t iv[AES_IV_LEN], tmp_iv[AES_IV_LEN]; 212 u_int32_t v, padlen = 0; 213 int i, offset; 214 215 m = (struct msg *)calloc(1, sizeof *m); 216 if (!m) { 217 log_err("calloc()"); 218 free(buf); 219 return -1; 220 } 221 222 /* Generate hash */ 223 SHA1_Init(&ctx); 224 SHA1_Update(&ctx, buf, len); 225 SHA1_Final(hash, &ctx); 226 dump_buf(5, hash, sizeof hash, "net_queue: computed hash"); 227 228 /* Padding required? */ 229 i = len % AES_IV_LEN; 230 if (i) { 231 u_int8_t *pbuf; 232 i = AES_IV_LEN - i; 233 pbuf = realloc(buf, len + i); 234 if (!pbuf) { 235 log_err("net_queue: realloc()"); 236 free(buf); 237 free(m); 238 return -1; 239 } 240 padlen = i; 241 while (i > 0) 242 pbuf[len++] = (u_int8_t)i--; 243 buf = pbuf; 244 } 245 246 /* Get random IV */ 247 for (i = 0; i <= sizeof iv - sizeof v; i += sizeof v) { 248 v = arc4random(); 249 memcpy(&iv[i], &v, sizeof v); 250 } 251 dump_buf(5, iv, sizeof iv, "net_queue: IV"); 252 memcpy(tmp_iv, iv, sizeof tmp_iv); 253 254 /* Encrypt */ 255 dump_buf(5, buf, len, "net_queue: pre encrypt"); 256 AES_cbc_encrypt(buf, buf, len, &aes_key[0], tmp_iv, AES_ENCRYPT); 257 dump_buf(5, buf, len, "net_queue: post encrypt"); 258 259 /* Allocate send buffer */ 260 m->len = len + sizeof iv + sizeof hash + 3 * sizeof(u_int32_t); 261 m->buf = (u_int8_t *)malloc(m->len); 262 if (!m->buf) { 263 free(m); 264 free(buf); 265 log_err("net_queue: calloc()"); 266 return -1; 267 } 268 offset = 0; 269 270 /* Fill it (order must match parsing code in net_read()) */ 271 v = htonl(m->len - sizeof(u_int32_t)); 272 memcpy(m->buf + offset, &v, sizeof v); 273 offset += sizeof v; 274 v = htonl(msgtype); 275 memcpy(m->buf + offset, &v, sizeof v); 276 offset += sizeof v; 277 v = htonl(padlen); 278 memcpy(m->buf + offset, &v, sizeof v); 279 offset += sizeof v; 280 memcpy(m->buf + offset, hash, sizeof hash); 281 offset += sizeof hash; 282 memcpy(m->buf + offset, iv, sizeof iv); 283 offset += sizeof iv; 284 memcpy(m->buf + offset, buf, len); 285 free(buf); 286 287 if (p) 288 net_enqueue(p, m); 289 else 290 for (p = LIST_FIRST(&cfgstate.peerlist); p; 291 p = LIST_NEXT(p, link)) 292 net_enqueue(p, m); 293 294 if (!m->refcnt) { 295 free(m->buf); 296 free(m); 297 } 298 299 return 0; 300} 301 302/* Set all write pending filedescriptors. */ 303int 304net_set_pending_wfds(fd_set *fds) 305{ 306 struct syncpeer *p; 307 int max_fd = -1; 308 309 for (p = LIST_FIRST(&cfgstate.peerlist); p; p = LIST_NEXT(p, link)) 310 if (p->socket > -1 && SIMPLEQ_FIRST(&p->msgs)) { 311 FD_SET(p->socket, fds); 312 if (p->socket > max_fd) 313 max_fd = p->socket; 314 } 315 return max_fd + 1; 316} 317 318/* 319 * Set readable filedescriptors. They are basically the same as for write, 320 * plus the listening socket. 321 */ 322int 323net_set_rfds(fd_set *fds) 324{ 325 struct syncpeer *p; 326 int max_fd = -1; 327 328 for (p = LIST_FIRST(&cfgstate.peerlist); p; p = LIST_NEXT(p, link)) { 329 if (p->socket > -1) 330 FD_SET(p->socket, fds); 331 if (p->socket > max_fd) 332 max_fd = p->socket; 333 } 334 FD_SET(listen_socket, fds); 335 if (listen_socket > max_fd) 336 max_fd = listen_socket; 337 return max_fd + 1; 338} 339 340void 341net_handle_messages(fd_set *fds) 342{ 343 struct sockaddr_storage sa_storage, sa_storage2; 344 struct sockaddr *sa = (struct sockaddr *)&sa_storage; 345 struct sockaddr *sa2 = (struct sockaddr *)&sa_storage2; 346 socklen_t socklen; 347 struct syncpeer *p; 348 u_int8_t *msg; 349 u_int32_t msgtype, msglen; 350 int newsock, found; 351 352 if (FD_ISSET(listen_socket, fds)) { 353 /* Accept a new incoming connection */ 354 socklen = sizeof sa_storage; 355 newsock = accept(listen_socket, sa, &socklen); 356 if (newsock > -1) { 357 /* Setup the syncpeer structure */ 358 found = 0; 359 for (p = LIST_FIRST(&cfgstate.peerlist); p && !found; 360 p = LIST_NEXT(p, link)) { 361 struct sockaddr_in *sin, *sin2; 362 struct sockaddr_in6 *sin6, *sin62; 363 364 /* Match? */ 365 if (net_set_sa(sa2, p->name, 0)) 366 continue; 367 if (sa->sa_family != sa2->sa_family) 368 continue; 369 if (sa->sa_family == AF_INET) { 370 sin = (struct sockaddr_in *)sa; 371 sin2 = (struct sockaddr_in *)sa2; 372 if (memcmp(&sin->sin_addr, 373 &sin2->sin_addr, 374 sizeof(struct in_addr))) 375 continue; 376 } else { 377 sin6 = (struct sockaddr_in6 *)sa; 378 sin62 = (struct sockaddr_in6 *)sa2; 379 if (memcmp(&sin6->sin6_addr, 380 &sin62->sin6_addr, 381 sizeof(struct in6_addr))) 382 continue; 383 } 384 /* Match! */ 385 found++; 386 p->socket = newsock; 387 log_msg(1, "net: peer \"%s\" connected", 388 p->name); 389 if (cfgstate.runstate == MASTER) 390 timer_add("pfkey_snapshot", 2, 391 pfkey_snapshot, p); 392 } 393 if (!found) { 394 log_msg(1, "net: found no matching peer for " 395 "accepted socket, closing."); 396 close(newsock); 397 } 398 } else 399 log_err("accept()"); 400 } 401 402 for (p = LIST_FIRST(&cfgstate.peerlist); p; p = LIST_NEXT(p, link)) { 403 if (p->socket < 0 || !FD_ISSET(p->socket, fds)) 404 continue; 405 msg = net_read(p, &msgtype, &msglen); 406 if (!msg) 407 continue; 408 409 log_msg(4, "net_handle_messages: got msg type %u len %u from " 410 "peer %s", msgtype, msglen, p->name); 411 412 switch (msgtype) { 413 case MSG_SYNCCTL: 414 net_ctl_handle_msg(p, msg, msglen); 415 free(msg); 416 break; 417 418 case MSG_PFKEYDATA: 419 if (p->runstate != MASTER || 420 cfgstate.runstate == MASTER) { 421 log_msg(1, "net: got PFKEY message from " 422 "non-MASTER peer"); 423 free(msg); 424 if (cfgstate.runstate == MASTER) 425 net_ctl_send_state(p); 426 else 427 net_ctl_send_error(p, 0); 428 } else if (pfkey_queue_message(msg, msglen)) 429 free(msg); 430 break; 431 432 default: 433 log_msg(0, "net: got unknown message type %u len %u " 434 "from peer %s", msgtype, msglen, p->name); 435 free(msg); 436 net_ctl_send_error(p, 0); 437 } 438 } 439} 440 441void 442net_send_messages(fd_set *fds) 443{ 444 struct syncpeer *p; 445 struct qmsg *qm; 446 struct msg *m; 447 ssize_t r; 448 449 for (p = LIST_FIRST(&cfgstate.peerlist); p; p = LIST_NEXT(p, link)) { 450 if (p->socket < 0 || !FD_ISSET(p->socket, fds)) 451 continue; 452 qm = SIMPLEQ_FIRST(&p->msgs); 453 if (!qm) { 454 /* XXX Log */ 455 continue; 456 } 457 m = qm->msg; 458 459 log_msg(4, "net_send_messages: msg %p len %d ref %d " 460 "to peer %s", m, m->len, m->refcnt, p->name); 461 462 /* write message */ 463 r = write(p->socket, m->buf, m->len); 464 if (r == -1) { 465 net_disconnect_peer(p); 466 log_msg(0, "net_send_messages: write() failed, " 467 "peer disconnected"); 468 } else if (r < (ssize_t)m->len) { 469 /* retransmit later */ 470 continue; 471 } 472 473 /* cleanup */ 474 SIMPLEQ_REMOVE_HEAD(&p->msgs, next); 475 free(qm); 476 477 if (--m->refcnt < 1) { 478 log_msg(4, "net_send_messages: freeing msg %p", m); 479 free(m->buf); 480 free(m); 481 } 482 } 483 return; 484} 485 486void 487net_disconnect_peer(struct syncpeer *p) 488{ 489 if (p->socket > -1) { 490 log_msg(1, "net_disconnect_peer: peer \"%s\" removed", 491 p->name); 492 close(p->socket); 493 } 494 p->socket = -1; 495} 496 497void 498net_shutdown(void) 499{ 500 struct syncpeer *p; 501 struct qmsg *qm; 502 struct msg *m; 503 504 while ((p = LIST_FIRST(&cfgstate.peerlist))) { 505 while ((qm = SIMPLEQ_FIRST(&p->msgs))) { 506 SIMPLEQ_REMOVE_HEAD(&p->msgs, next); 507 m = qm->msg; 508 if (--m->refcnt < 1) { 509 free(m->buf); 510 free(m); 511 } 512 free(qm); 513 } 514 net_disconnect_peer(p); 515 if (p->name) 516 free(p->name); 517 LIST_REMOVE(p, link); 518 free(p); 519 } 520 521 if (listen_socket > -1) 522 close(listen_socket); 523} 524 525/* 526 * Helper functions (local) below here. 527 */ 528 529static u_int8_t * 530net_read(struct syncpeer *p, u_int32_t *msgtype, u_int32_t *msglen) 531{ 532 u_int8_t *msg, *blob, *rhash, *iv, hash[SHA_DIGEST_LENGTH]; 533 u_int32_t v, blob_len; 534 int padlen = 0, offset = 0, r; 535 SHA_CTX ctx; 536 537 /* Read blob length */ 538 r = read(p->socket, &v, sizeof v); 539 if (r != (ssize_t)sizeof v) { 540 if (r < 1) 541 net_disconnect_peer(p); 542 return NULL; 543 } 544 545 blob_len = ntohl(v); 546 if (blob_len < sizeof hash + AES_IV_LEN + 2 * sizeof(u_int32_t)) 547 return NULL; 548 *msglen = blob_len - sizeof hash - AES_IV_LEN - 2 * sizeof(u_int32_t); 549 if (*msglen < MSG_MINLEN || *msglen > MSG_MAXLEN) 550 return NULL; 551 552 /* Read message blob */ 553 blob = (u_int8_t *)malloc(blob_len); 554 if (!blob) { 555 log_err("net_read: malloc()"); 556 return NULL; 557 } 558 r = read(p->socket, blob, blob_len); 559 if (r < 1) { 560 net_disconnect_peer(p); 561 free(blob); 562 return NULL; 563 } else if (r < (ssize_t)blob_len) { 564 /* XXX wait and read more? */ 565 fprintf(stderr, "net_read: wanted %d, got %d\n", blob_len, r); 566 free(blob); 567 return NULL; 568 } 569 570 offset = 0; 571 memcpy(&v, blob + offset, sizeof v); 572 *msgtype = ntohl(v); 573 offset += sizeof v; 574 575 if (*msgtype > MSG_MAXTYPE) { 576 free(blob); 577 return NULL; 578 } 579 580 memcpy(&v, blob + offset, sizeof v); 581 padlen = ntohl(v); 582 offset += sizeof v; 583 584 rhash = blob + offset; 585 iv = rhash + sizeof hash; 586 msg = (u_int8_t *)malloc(*msglen); 587 if (!msg) { 588 free(blob); 589 return NULL; 590 } 591 memcpy(msg, iv + AES_IV_LEN, *msglen); 592 593 dump_buf(5, rhash, sizeof hash, "net_read: got hash"); 594 dump_buf(5, iv, AES_IV_LEN, "net_read: got IV"); 595 dump_buf(5, msg, *msglen, "net_read: pre decrypt"); 596 AES_cbc_encrypt(msg, msg, *msglen, &aes_key[1], iv, AES_DECRYPT); 597 dump_buf(5, msg, *msglen, "net_read: post decrypt"); 598 *msglen -= padlen; 599 600 SHA1_Init(&ctx); 601 SHA1_Update(&ctx, msg, *msglen); 602 SHA1_Final(hash, &ctx); 603 dump_buf(5, hash, sizeof hash, "net_read: computed hash"); 604 605 if (memcmp(hash, rhash, sizeof hash) != 0) { 606 free(blob); 607 log_msg(0, "net_read: got bad message (typo in shared key?)"); 608 return NULL; 609 } 610 free(blob); 611 return msg; 612} 613 614static int 615net_set_sa(struct sockaddr *sa, char *name, in_port_t port) 616{ 617 struct sockaddr_in *sin = (struct sockaddr_in *)sa; 618 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; 619 struct ifaddrs *ifap, *ifa; 620 621 if (!name) { 622 /* XXX Assume IPv4 */ 623 sa->sa_family = AF_INET; 624 sin->sin_port = htons(port); 625 sin->sin_len = sizeof *sin; 626 return 0; 627 } 628 629 if (inet_pton(AF_INET, name, &sin->sin_addr) == 1) { 630 sa->sa_family = AF_INET; 631 sin->sin_port = htons(port); 632 sin->sin_len = sizeof *sin; 633 return 0; 634 } 635 636 if (inet_pton(AF_INET6, name, &sin6->sin6_addr) == 1) { 637 sa->sa_family = AF_INET6; 638 sin6->sin6_port = htons(port); 639 sin6->sin6_len = sizeof *sin6; 640 return 0; 641 } 642 643 /* inet_pton failed. fail here if name is not cfgstate.listen_on */ 644 if (strcmp(cfgstate.listen_on, name) != 0) 645 return -1; 646 647 /* Is cfgstate.listen_on the name of one our interfaces? */ 648 if (getifaddrs(&ifap) != 0) { 649 perror("getifaddrs()"); 650 return -1; 651 } 652 sa->sa_family = AF_UNSPEC; 653 for (ifa = ifap; ifa && sa->sa_family == AF_UNSPEC; 654 ifa = ifa->ifa_next) { 655 if (!ifa->ifa_name || !ifa->ifa_addr) 656 continue; 657 if (strcmp(ifa->ifa_name, name) != 0) 658 continue; 659 660 switch (ifa->ifa_addr->sa_family) { 661 case AF_INET: 662 sa->sa_family = AF_INET; 663 sin->sin_port = htons(port); 664 sin->sin_len = sizeof *sin; 665 memcpy(&sin->sin_addr, 666 &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr, 667 sizeof sin->sin_addr); 668 break; 669 670 case AF_INET6: 671 sa->sa_family = AF_INET6; 672 sin6->sin6_port = htons(port); 673 sin6->sin6_len = sizeof *sin6; 674 memcpy(&sin6->sin6_addr, 675 &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr, 676 sizeof sin6->sin6_addr); 677 break; 678 } 679 } 680 freeifaddrs(ifap); 681 return sa->sa_family == AF_UNSPEC ? -1 : 0; 682} 683 684 685static void 686got_sigalrm(int s) 687{ 688 return; 689} 690 691void 692net_connect(void) 693{ 694 struct sockaddr_storage sa_storage; 695 struct itimerval iv; 696 struct sockaddr *sa = (struct sockaddr *)&sa_storage; 697 struct syncpeer *p; 698 699 signal(SIGALRM, got_sigalrm); 700 memset(&iv, 0, sizeof iv); 701 iv.it_value.tv_sec = 5; 702 iv.it_interval.tv_sec = 5; 703 setitimer(ITIMER_REAL, &iv, NULL); 704 705 for (p = LIST_FIRST(&cfgstate.peerlist); p; p = LIST_NEXT(p, link)) { 706 if (p->socket > -1) 707 continue; 708 709 memset(sa, 0, sizeof sa_storage); 710 if (net_set_sa(sa, p->name, cfgstate.listen_port)) 711 continue; 712 p->socket = socket(sa->sa_family, SOCK_STREAM, 0); 713 if (p->socket < 0) { 714 log_err("peer \"%s\": socket()", p->name); 715 continue; 716 } 717 if (connect(p->socket, sa, sa->sa_len)) { 718 log_msg(1, "net_connect: peer \"%s\" not ready yet", 719 p->name); 720 net_disconnect_peer(p); 721 continue; 722 } 723 if (net_ctl_send_state(p)) { 724 log_msg(0, "net_connect: peer \"%s\" failed", p->name); 725 net_disconnect_peer(p); 726 continue; 727 } 728 log_msg(1, "net_connect: peer \"%s\" connected, fd %d", 729 p->name, p->socket); 730 731 /* Schedule a pfkey sync to the newly connected peer. */ 732 if (cfgstate.runstate == MASTER) 733 timer_add("pfkey_snapshot", 2, pfkey_snapshot, p); 734 } 735 736 timerclear(&iv.it_value); 737 timerclear(&iv.it_interval); 738 setitimer(ITIMER_REAL, &iv, NULL); 739 signal(SIGALRM, SIG_IGN); 740 741 return; 742} 743 744static void 745net_check_peers(void *arg) 746{ 747 net_connect(); 748 749 (void)timer_add("peer recheck", 600, net_check_peers, 0); 750} 751 752