1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Module for all network transactions. SLP messages can be multicast, 29 * unicast over UDP, or unicast over TCP; this module provides routines 30 * for all three. TCP transactions are handled by a single dedicated 31 * thread, while multicast and UDP unicast messages are sent by the 32 * calling thread. 33 * 34 * slp_uc_tcp_send: enqueues a message on the TCP transaction thread's 35 * queue. 36 * slp_tcp_wait: blocks until all TCP-enqueued transactions for 37 * a given SLP handle are complete 38 * slp_uc_udp_send: unicasts a message using a datagram 39 * slp_mc_send: multicasts a message 40 */ 41 42 /* 43 * todo: correct multicast interfaces; 44 */ 45 46 #include <stdio.h> 47 #include <stdlib.h> 48 #include <syslog.h> 49 #include <sys/types.h> 50 #include <sys/socket.h> 51 #include <arpa/inet.h> 52 #include <errno.h> 53 #include <unistd.h> 54 #include <time.h> 55 #include <string.h> 56 #include <slp-internal.h> 57 #include <slp_net_utils.h> 58 59 /* 60 * TCP thread particulars 61 */ 62 static SLPBoolean tcp_thr_running = SLP_FALSE; 63 static slp_queue_t *tcp_q; 64 static int tcp_sockfd; 65 static mutex_t start_lock = DEFAULTMUTEX; 66 67 /* Used to pass arguments to the TCP thread, via 'tcp_q' */ 68 struct tcp_rqst { 69 slp_handle_impl_t *hp; 70 slp_target_t *target; 71 const char *scopes; 72 SLPBoolean free_target; 73 unsigned short xid; 74 }; 75 76 /* Used to keep track of broadcast interfaces */ 77 struct bc_ifs { 78 struct sockaddr_in *sin; 79 int num_ifs; 80 }; 81 82 /* 83 * Private utility routines 84 */ 85 static SLPError start_tcp_thr(); 86 static void *tcp_thread(void *); 87 static SLPError make_header(slp_handle_impl_t *, char *, const char *); 88 static void udp_make_msghdr(struct sockaddr_in *, struct iovec *, int, 89 struct msghdr *); 90 static SLPError make_mc_target(slp_handle_impl_t *, 91 struct sockaddr_in *, char *, 92 struct pollfd **, nfds_t *, struct bc_ifs *); 93 static SLPError make_bc_target(slp_handle_impl_t *, struct in_addr *, 94 int, struct bc_ifs *); 95 static SLPError mc_sendmsg(struct pollfd *, struct msghdr *, 96 struct bc_ifs *); 97 static SLPError bc_sendmsg(struct pollfd *, struct msghdr *, struct bc_ifs *); 98 static void mc_recvmsg(struct pollfd *, nfds_t, slp_handle_impl_t *, 99 const char *, char *, void **, unsigned long long, 100 unsigned long long, unsigned long long *, 101 int *, int *, int); 102 static void free_pfds(struct pollfd *, nfds_t); 103 static void tcp_handoff(slp_handle_impl_t *, const char *, 104 struct sockaddr_in *, unsigned short); 105 static unsigned long long now_millis(); 106 static int wait_for_response(unsigned long long, int *, 107 unsigned long long, unsigned long long *, 108 struct pollfd [], nfds_t); 109 static int add2pr_list(slp_msg_t *, struct sockaddr_in *, void **); 110 static void free_pr_node(void *, VISIT, int, void *); 111 112 /* 113 * Unicasts a message using TCP. 'target' is a targets list 114 * containing DAs corresponding to 'scopes'. 'free_target' directs 115 * tcp_thread to free the target list when finished; this is useful 116 * when a target needs to be synthesised by another message thread 117 * (such as slp_mc_send for tcp_handoffs). If this message is a 118 * retransmission due to a large reply, 'xid' should be the same as for 119 * the original message. 120 * 121 * This call returns as soon as the message has been enqueued on 'tcp_q'. 122 * Callers interested in knowing when the transaction has completed 123 * should call slp_tcp_wait with the same SLP handle. 124 */ 125 void slp_uc_tcp_send(slp_handle_impl_t *hp, slp_target_t *target, 126 const char *scopes, SLPBoolean free_target, 127 unsigned short xid) { 128 struct tcp_rqst *rqst; 129 130 /* initialize TCP vars in handle, if necessary */ 131 if (!hp->tcp_lock) { 132 if (!(hp->tcp_lock = malloc(sizeof (*(hp->tcp_lock))))) { 133 slp_err(LOG_CRIT, 0, "slp_uc_tcp_send", 134 "out of memory"); 135 return; 136 } 137 (void) mutex_init(hp->tcp_lock, USYNC_THREAD, NULL); 138 } 139 if (!hp->tcp_wait) { 140 if (!(hp->tcp_wait = malloc(sizeof (*(hp->tcp_wait))))) { 141 slp_err(LOG_CRIT, 0, "slp_uc_tcp_send", 142 "out of memory"); 143 return; 144 } 145 (void) cond_init(hp->tcp_wait, USYNC_THREAD, NULL); 146 } 147 (void) mutex_lock(hp->tcp_lock); 148 (hp->tcp_ref_cnt)++; 149 (void) mutex_unlock(hp->tcp_lock); 150 151 /* start TCP thread, if not already running */ 152 if (!tcp_thr_running) 153 if (start_tcp_thr() != SLP_OK) 154 return; 155 156 /* create and enqueue the request */ 157 if (!(rqst = malloc(sizeof (*rqst)))) { 158 slp_err(LOG_CRIT, 0, "slp_uc_tcp_send", "out of memory"); 159 return; 160 } 161 rqst->hp = hp; 162 rqst->target = target; 163 rqst->scopes = scopes; 164 rqst->free_target = free_target; 165 rqst->xid = xid; 166 (void) slp_enqueue(tcp_q, rqst); 167 } 168 169 /* 170 * Wait for TCP to complete, if a transaction corresponding to this 171 * SLP handle is pending. If none are pending, returns immediately. 172 */ 173 void slp_tcp_wait(slp_handle_impl_t *hp) { 174 (void) mutex_lock(hp->tcp_lock); 175 while (hp->tcp_ref_cnt > 0) 176 (void) cond_wait(hp->tcp_wait, hp->tcp_lock); 177 (void) mutex_unlock(hp->tcp_lock); 178 } 179 180 /* 181 * Unicasts a message using datagrams. 'target' should contain a 182 * list of DAs corresponding to 'scopes'. 183 * 184 * This call does not return until the transaction has completed. It 185 * may handoff a message to the TCP thread if necessary, but will not 186 * wait for that transaction to complete. Hence callers should always 187 * invoke slp_tcp_wait before cleaning up resources. 188 */ 189 void slp_uc_udp_send(slp_handle_impl_t *hp, slp_target_t *target, 190 const char *scopes) { 191 slp_target_t *ctarg; 192 struct sockaddr_in *sin; 193 struct msghdr msg[1]; 194 char header[SLP_DEFAULT_SENDMTU]; 195 int sockfd; 196 size_t mtu; 197 SLPBoolean use_tcp; 198 struct pollfd pfd[1]; 199 unsigned long long now, sent; 200 char *reply = NULL; 201 202 use_tcp = SLP_FALSE; 203 /* build the header and iovec */ 204 if (make_header(hp, header, scopes) != SLP_OK) 205 return; 206 207 mtu = slp_get_mtu(); 208 209 /* walk targets list until we either succeed or run out of targets */ 210 for (ctarg = target; ctarg; ctarg = slp_next_failover(ctarg)) { 211 char *state; 212 const char *timeouts; 213 int timeout; 214 215 sin = (struct sockaddr_in *)slp_get_target_sin(ctarg); 216 217 /* make the socket, msghdr and reply buf */ 218 if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 219 slp_err(LOG_CRIT, 0, "slp_uc_udp_send", 220 "could not create socket: %s", 221 strerror(errno)); 222 return; 223 } 224 pfd[0].fd = sockfd; 225 pfd[0].events = POLLRDNORM; 226 227 udp_make_msghdr(sin, hp->msg.iov, hp->msg.iovlen, msg); 228 if (!reply && !(reply = malloc(mtu))) { 229 (void) close(sockfd); 230 slp_err(LOG_CRIT, 0, "slp_uc_udp_send", 231 "out of memory"); 232 return; 233 } 234 235 /* timeout loop */ 236 timeouts = SLPGetProperty(SLP_CONFIG_DATAGRAMTIMEOUTS); 237 state = (char *)timeouts; 238 for (timeout = slp_get_next_onlist(&state); 239 timeout != -1 && 240 !hp->cancel; 241 timeout = slp_get_next_onlist(&state)) { 242 int pollerr; 243 244 if (sendmsg(sockfd, msg, 0) < 0) { 245 slp_err(LOG_CRIT, 0, "slp_uc_udp_send", 246 "sendmsg failed: %s", strerror(errno)); 247 continue; /* try again */ 248 } 249 sent = now_millis(); 250 251 pollerr = wait_for_response( 252 0, &timeout, sent, &now, pfd, 1); 253 254 if (pollerr == 0) 255 /* timeout */ 256 continue; 257 if (pollerr < 0) 258 break; 259 260 /* only using one fd, so no need to scan pfd */ 261 if (recvfrom(sockfd, reply, mtu, 0, NULL, NULL) < 0) { 262 /* if reply overflows, hand off to TCP */ 263 if (errno == ENOMEM) { 264 free(reply); reply = NULL; 265 use_tcp = SLP_TRUE; 266 break; 267 } 268 slp_err(LOG_CRIT, 0, "slp_uc_udp_send", 269 "recvfrom failed: %s", 270 strerror(errno)); 271 } else { 272 /* success -- but check error code */ 273 slp_proto_err errcode = slp_get_errcode(reply); 274 switch (errcode) { 275 case SLP_MSG_PARSE_ERROR: 276 case SLP_VER_NOT_SUPPORTED: 277 case SLP_SICK_DA: 278 case SLP_DA_BUSY_NOW: 279 case SLP_OPTION_NOT_UNDERSTOOD: 280 case SLP_RQST_NOT_SUPPORTED: { 281 char addrbuf[INET6_ADDRSTRLEN], *cname; 282 283 cname = slp_ntop(addrbuf, INET6_ADDRSTRLEN, 284 (const void *) &(sin->sin_addr)); 285 cname = cname ? cname : "[invalid addr]"; 286 287 /* drop it */ 288 slp_err(LOG_INFO, 0, 289 "DA %s returned error code %d; dropping reply", 290 cname, errcode); 291 free(reply); reply = NULL; 292 } 293 } 294 } 295 break; 296 } 297 if (timeout != -1) 298 /* success or cancel */ 299 break; 300 /* else failure */ 301 slp_mark_target_failed(ctarg); 302 } 303 (void) close(sockfd); 304 if (!ctarg || hp->cancel) { 305 /* failed all attempts or canceled by consumer */ 306 if (reply) free(reply); 307 return; 308 } 309 /* success or tcp handoff */ 310 if (reply) { 311 if (slp_get_overflow(reply)) 312 use_tcp = SLP_TRUE; 313 else 314 slp_mark_target_used(ctarg); 315 (void) slp_enqueue(hp->q, reply); 316 } 317 if (use_tcp) 318 slp_uc_tcp_send( 319 hp, ctarg, scopes, SLP_FALSE, slp_get_xid(header)); 320 } 321 322 /* 323 * Multicasts (or broadcasts) a message, using multicast convergance 324 * to collect results. Large replies will cause the message to be handed 325 * off to the TCP thread. 326 * 327 * This call does not return until the transaction is complete. It does 328 * not, however, wait until pending TCP transactions are complete, so 329 * callers should always invoke slp_tcp_wait before cleaning up any 330 * resources. 331 */ 332 void slp_mc_send(slp_handle_impl_t *hp, const char *scopes) { 333 char header[SLP_DEFAULT_SENDMTU], *state; 334 const char *timeouts; 335 struct sockaddr_in sin[1]; 336 struct msghdr msg[1]; 337 int maxwait, timeout, noresults, anyresults; 338 unsigned long long final_to, now, sent; 339 struct pollfd *pfd; 340 nfds_t nfds; 341 void *collator = NULL; 342 struct bc_ifs bcifs; 343 344 /* build the header and iovec */ 345 if (make_header(hp, header, scopes) != SLP_OK) 346 return; 347 348 (void) memset(sin, 0, sizeof (sin)); 349 if (make_mc_target(hp, sin, header, &pfd, &nfds, &bcifs) != SLP_OK) 350 return; 351 udp_make_msghdr(sin, hp->msg.iov, hp->msg.iovlen, msg); 352 353 maxwait = slp_get_mcmaxwait(); 354 maxwait = maxwait ? maxwait : SLP_DEFAULT_MAXWAIT; 355 356 /* set the final timeout */ 357 now = now_millis(); 358 final_to = now + maxwait; 359 360 /* timeout prep and loop */ 361 timeouts = SLPGetProperty(SLP_CONFIG_MULTICASTTIMEOUTS); 362 state = (char *)timeouts; 363 noresults = anyresults = 0; 364 365 for (timeout = slp_get_next_onlist(&state); 366 timeout != -1 && 367 now < final_to && 368 noresults < 2 && 369 !hp->cancel; 370 timeout = slp_get_next_onlist(&state)) { 371 372 /* send msg */ 373 if (mc_sendmsg(pfd, msg, &bcifs) != SLP_OK) { 374 continue; /* try again */ 375 } 376 sent = now_millis(); 377 378 /* receive results */ 379 mc_recvmsg(pfd, nfds, hp, scopes, header, &collator, final_to, 380 sent, &now, &noresults, &anyresults, timeout); 381 382 if (!anyresults) 383 noresults++; 384 anyresults = 0; 385 } 386 /* clean up PR list collator */ 387 if (collator) 388 slp_twalk(collator, free_pr_node, 0, NULL); 389 390 /* close all fds in pfd */ 391 free_pfds(pfd, nfds); 392 393 /* free broadcast addrs, if used */ 394 if (bcifs.sin) free(bcifs.sin); 395 } 396 397 /* 398 * Private net helper routines 399 */ 400 401 /* 402 * Starts the tcp_thread and allocates any necessary resources. 403 */ 404 static SLPError 405 start_tcp_thr(void) 406 { 407 SLPError err; 408 int terr; 409 410 (void) mutex_lock(&start_lock); 411 /* make sure someone else hasn't already intialized the thread */ 412 if (tcp_thr_running) { 413 (void) mutex_unlock(&start_lock); 414 return (SLP_OK); 415 } 416 417 /* create the tcp queue */ 418 if (!(tcp_q = slp_new_queue(&err))) { 419 (void) mutex_unlock(&start_lock); 420 return (err); 421 } 422 423 /* start the tcp thread */ 424 if ((terr = thr_create(0, 0, tcp_thread, NULL, 0, NULL)) != 0) { 425 slp_err(LOG_CRIT, 0, "start_tcp_thr", 426 "could not start thread: %s", strerror(terr)); 427 (void) mutex_unlock(&start_lock); 428 return (SLP_INTERNAL_SYSTEM_ERROR); 429 } 430 431 tcp_thr_running = SLP_TRUE; 432 (void) mutex_unlock(&start_lock); 433 return (SLP_OK); 434 } 435 436 /* 437 * Called by the tcp thread to shut itself down. The queue must be 438 * empty (and should be, since the tcp thread will only shut itself 439 * down if nothing has been put in its queue for the timeout period). 440 */ 441 static void end_tcp_thr() { 442 (void) mutex_lock(&start_lock); 443 444 tcp_thr_running = SLP_FALSE; 445 slp_destroy_queue(tcp_q); 446 447 (void) mutex_unlock(&start_lock); 448 thr_exit(NULL); 449 } 450 451 /* 452 * The thread of control for the TCP thread. This sits in a loop, waiting 453 * on 'tcp_q' for new messages. If no message appear after 30 seconds, 454 * this thread cleans up resources and shuts itself down. 455 */ 456 static void * 457 tcp_thread(void *arg __unused) 458 { 459 struct tcp_rqst *rqst; 460 char *reply, header[SLP_DEFAULT_SENDMTU]; 461 timestruc_t to[1]; 462 to->tv_nsec = 0; 463 464 for (;;) { 465 slp_target_t *ctarg, *targets; 466 slp_handle_impl_t *hp; 467 const char *scopes; 468 struct sockaddr_in *sin; 469 SLPBoolean free_target, etimed; 470 unsigned short xid; 471 472 /* set idle shutdown timeout */ 473 to->tv_sec = time(NULL) + 30; 474 /* get the next request from the tcp queue */ 475 if (!(rqst = slp_dequeue_timed(tcp_q, to, &etimed))) { 476 if (!etimed) 477 continue; 478 else 479 end_tcp_thr(); 480 } 481 482 hp = rqst->hp; 483 scopes = rqst->scopes; 484 targets = rqst->target; 485 free_target = rqst->free_target; 486 xid = rqst->xid; 487 free(rqst); 488 reply = NULL; 489 490 /* Check if this handle has been cancelled */ 491 if (hp->cancel) 492 goto transaction_complete; 493 494 /* build the header and iovec */ 495 if (make_header(hp, header, scopes) != SLP_OK) { 496 if (free_target) slp_free_target(targets); 497 continue; 498 } 499 if (xid) 500 slp_set_xid(header, xid); 501 502 /* walk targets list until we either succeed or run out of targets */ 503 for (ctarg = targets; ctarg && !hp->cancel; 504 ctarg = slp_next_failover(ctarg)) { 505 506 sin = (struct sockaddr_in *)slp_get_target_sin(ctarg); 507 508 /* create the socket */ 509 if ((tcp_sockfd = socket(AF_INET, SOCK_STREAM, 0)) 510 < 0) { 511 slp_err(LOG_CRIT, 0, "tcp_thread", 512 "could not create socket: %s", 513 strerror(errno)); 514 ctarg = NULL; 515 break; 516 } 517 518 /* connect to target */ 519 if (connect(tcp_sockfd, (struct sockaddr *)sin, 520 sizeof (*sin)) < 0) { 521 slp_err(LOG_INFO, 0, "tcp_thread", 522 "could not connect, error = %s", 523 strerror(errno)); 524 goto failed; 525 } 526 527 /* send the message and read the reply */ 528 if (writev(tcp_sockfd, hp->msg.iov, hp->msg.iovlen) 529 == -1) { 530 slp_err(LOG_INFO, 0, "tcp_thread", 531 "could not send, error = %s", 532 strerror(errno)); 533 goto failed; 534 } 535 536 /* if success, break out of failover loop */ 537 if ((slp_tcp_read(tcp_sockfd, &reply)) == SLP_OK) { 538 (void) close(tcp_sockfd); 539 break; 540 } 541 542 /* else if timed out, mark target failed and try next one */ 543 failed: 544 (void) close(tcp_sockfd); 545 slp_mark_target_failed(ctarg); 546 } 547 548 if (hp->cancel) { 549 if (reply) { 550 free(reply); 551 } 552 } else if (ctarg) { 553 /* success */ 554 (void) slp_enqueue(hp->q, reply); 555 slp_mark_target_used(ctarg); 556 } 557 558 /* If all TCP transactions on this handle are complete, send notice */ 559 transaction_complete: 560 (void) mutex_lock(hp->tcp_lock); 561 if (--(hp->tcp_ref_cnt) == 0) 562 (void) cond_signal(hp->tcp_wait); 563 (void) mutex_unlock(hp->tcp_lock); 564 565 if (free_target) 566 slp_free_target(targets); 567 } 568 return (NULL); 569 } 570 571 /* 572 * Performs a full read for TCP replies, dynamically allocating a 573 * buffer large enough to hold the reply. 574 */ 575 SLPError slp_tcp_read(int sockfd, char **reply) { 576 char lenbuf[5], *p; 577 size_t nleft; 578 ssize_t nread; 579 unsigned int len; 580 581 /* find out how long the reply is */ 582 nleft = 5; 583 p = lenbuf; 584 while (nleft != 0) { 585 if ((nread = read(sockfd, p, 5)) < 0) { 586 if (errno == EINTR) 587 nread = 0; 588 else 589 return (SLP_NETWORK_ERROR); 590 } else if (nread == 0) 591 /* shouldn't hit EOF here */ 592 return (SLP_NETWORK_ERROR); 593 nleft -= nread; 594 p += nread; 595 } 596 597 len = slp_get_length(lenbuf); 598 599 /* allocate space for the reply, and copy in what we've already read */ 600 /* This buffer gets freed by a msg-specific unpacking routine later */ 601 if (!(*reply = malloc(len))) { 602 slp_err(LOG_CRIT, 0, "tcp_read", "out of memory"); 603 return (SLP_MEMORY_ALLOC_FAILED); 604 } 605 (void) memcpy(*reply, lenbuf, 5); 606 607 /* read the rest of the message */ 608 nleft = len - 5; 609 p = *reply + 5; 610 while (nleft != 0) { 611 if ((nread = read(sockfd, p, nleft)) < 0) { 612 if (errno == EINTR) 613 nread = 0; 614 else { 615 free(*reply); 616 return (SLP_NETWORK_ERROR); 617 } 618 } else if (nread == 0) 619 /* 620 * shouldn't hit EOF here, but perhaps we've 621 * gotten something useful, so return OK. 622 */ 623 return (SLP_OK); 624 625 nleft -= nread; 626 p += nread; 627 } 628 629 return (SLP_OK); 630 } 631 632 /* 633 * Lays in a SLP header for this message into the scatter / gather 634 * array 'iov'. 'header' is the buffer used to contain the header, 635 * and must contain enough space. 'scopes' should contain a string 636 * with the scopes to be used for this message. 637 */ 638 static SLPError make_header(slp_handle_impl_t *hp, char *header, 639 const char *scopes) { 640 SLPError err; 641 size_t msgLen, off; 642 int i; 643 size_t mtu; 644 unsigned short slen = (unsigned short)strlen(scopes); 645 646 mtu = slp_get_mtu(); 647 msgLen = slp_hdrlang_length(hp); 648 hp->msg.iov[0].iov_base = header; 649 hp->msg.iov[0].iov_len = msgLen; /* now the length of the hdr */ 650 651 /* use the remaining buffer in header for the prlist */ 652 hp->msg.prlist->iov_base = header + msgLen; 653 654 for (i = 1; i < hp->msg.iovlen; i++) { 655 msgLen += hp->msg.iov[i].iov_len; 656 } 657 msgLen += slen; 658 659 off = 0; 660 if ((err = slp_add_header(hp->locale, header, mtu, 661 hp->fid, msgLen, &off)) != SLP_OK) 662 return (err); 663 664 /* start out with empty prlist */ 665 hp->msg.prlist->iov_len = 0; 666 667 /* store the scope string len into the space provided by the caller */ 668 off = 0; 669 if ((err = slp_add_sht((char *)hp->msg.scopeslen.iov_base, 670 2, slen, &off)) != SLP_OK) { 671 return (err); 672 } 673 hp->msg.scopes->iov_base = (caddr_t)scopes; 674 hp->msg.scopes->iov_len = slen; 675 676 return (SLP_OK); 677 } 678 679 /* 680 * Populates a struct msghdr suitable for use with sendmsg. 681 */ 682 static void udp_make_msghdr(struct sockaddr_in *sin, struct iovec *iov, 683 int iovlen, struct msghdr *msg) { 684 msg->msg_name = (caddr_t)sin; 685 msg->msg_namelen = 16; 686 msg->msg_iov = iov; 687 msg->msg_iovlen = iovlen; 688 msg->msg_accrights = NULL; 689 msg->msg_accrightslen = 0; 690 } 691 692 /* 693 * Sets the address on 'sin', sets the flag in the message header, 694 * and creates an array of pollfds for all interfaces we need to 695 * use. If we need to use only broadcast, and net.slp.interfaces 696 * is set, fills bcifs with an array of subnet broadcast addresses 697 * to which we should send. Returns err != SLP_OK only on catastrophic 698 * error. 699 */ 700 static SLPError make_mc_target(slp_handle_impl_t *hp, 701 struct sockaddr_in *sin, char *header, 702 struct pollfd **fds, nfds_t *nfds, 703 struct bc_ifs *bcifs) { 704 705 unsigned char ttl = slp_get_multicastTTL(); 706 char *ifs_string; 707 SLPBoolean have_valid_if = SLP_FALSE; 708 SLPBoolean use_broadcast = slp_get_usebroadcast(); 709 int fd, i, num_givenifs; 710 struct in_addr *given_ifs = NULL; 711 nfds_t nfd_i; 712 713 sin->sin_port = htons(SLP_PORT); 714 sin->sin_family = AF_INET; 715 slp_set_mcast(header); 716 717 /* Get the desired multicast interfaces, if set */ 718 bcifs->sin = NULL; 719 *fds = NULL; 720 if ((ifs_string = (char *)SLPGetProperty( 721 SLP_CONFIG_INTERFACES)) != NULL && *ifs_string) { 722 723 char *p, *tstate; 724 725 /* count the number of IFs given */ 726 p = strchr(ifs_string, ','); 727 for (num_givenifs = 1; p; num_givenifs++) { 728 p = strchr(p + 1, ','); 729 } 730 731 /* copy the given IFs into an array for easier processing */ 732 if (!(given_ifs = calloc(num_givenifs, sizeof (*given_ifs)))) { 733 slp_err(LOG_CRIT, 0, "make_mc_target", 734 "out of memory"); 735 return (SLP_MEMORY_ALLOC_FAILED); 736 } 737 738 i = 0; 739 /* strtok_r will destructively modify, so make a copy first */ 740 if (!(ifs_string = strdup(ifs_string))) { 741 slp_err(LOG_CRIT, 0, "make_mc_target", 742 "out of memory"); 743 free(given_ifs); 744 return (SLP_MEMORY_ALLOC_FAILED); 745 } 746 for ( 747 p = strtok_r(ifs_string, ",", &tstate); 748 p; 749 p = strtok_r(NULL, ",", &tstate)) { 750 751 if (slp_pton(p, &(given_ifs[i])) < 1) { 752 /* skip */ 753 num_givenifs--; 754 continue; 755 } 756 i++; 757 } 758 *nfds = num_givenifs; 759 free(ifs_string); 760 761 /* allocate a pollfd array for all interfaces */ 762 if (!(*fds = calloc(num_givenifs, sizeof (**fds)))) { 763 slp_err(LOG_CRIT, 0, "make_mc_target", 764 "out of memory"); 765 free(ifs_string); 766 free(given_ifs); 767 return (SLP_MEMORY_ALLOC_FAILED); 768 } 769 770 /* lay the given interfaces into the pollfd array */ 771 for (i = 0; i < num_givenifs; i++) { 772 773 /* create a socket to bind to this interface */ 774 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 775 slp_err(LOG_CRIT, 0, "make_mc_target", 776 "could not create socket: %s", 777 strerror(errno)); 778 free_pfds(*fds, *nfds); 779 return (SLP_INTERNAL_SYSTEM_ERROR); 780 } 781 782 /* fill in the pollfd structure */ 783 (*fds)[i].fd = fd; 784 (*fds)[i].events |= POLLRDNORM; 785 786 if (use_broadcast) { 787 struct sockaddr_in bcsin[1]; 788 789 (void) memcpy( 790 &(bcsin->sin_addr), &(given_ifs[i]), 791 sizeof (bcsin->sin_addr)); 792 bcsin->sin_family = AF_INET; 793 bcsin->sin_port = 0; 794 795 /* bind fd to interface */ 796 if (bind(fd, (struct sockaddr *)bcsin, 797 sizeof (*bcsin)) == 0) { 798 continue; 799 } 800 /* else fallthru to default (multicast) */ 801 slp_err(LOG_INFO, 0, "make_mc_target", 802 "could not set broadcast interface: %s", 803 strerror(errno)); 804 } 805 /* else use multicast */ 806 if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, 807 &(given_ifs[i]), sizeof (given_ifs[i])) 808 < 0) { 809 810 slp_err(LOG_INFO, 0, "make_mc_target", 811 "could not set multicast interface: %s", 812 strerror(errno)); 813 continue; 814 } 815 816 have_valid_if = SLP_TRUE; 817 } 818 819 if (use_broadcast) { 820 SLPError err; 821 822 if ((err = make_bc_target( 823 hp, given_ifs, num_givenifs, bcifs)) 824 != SLP_OK) { 825 826 if (err == SLP_MEMORY_ALLOC_FAILED) { 827 /* the only thing which is really a showstopper */ 828 return (err); 829 } 830 831 /* else no valid interfaces */ 832 have_valid_if = SLP_FALSE; 833 } 834 } 835 free(given_ifs); 836 } 837 838 if (!have_valid_if) { 839 if (*fds && !have_valid_if) { 840 /* couldn't process net.slp.interfaces property */ 841 free(*fds); 842 } 843 844 /* bind to default interface */ 845 if (!(*fds = calloc(1, sizeof (**fds)))) { 846 slp_err(LOG_CRIT, 0, "make_mc_target", 847 "out of memory"); 848 return (SLP_MEMORY_ALLOC_FAILED); 849 } 850 851 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 852 slp_err(LOG_CRIT, 0, "make_mc_target", 853 "could not create socket: %s", 854 strerror(errno)); 855 free(*fds); 856 return (SLP_INTERNAL_SYSTEM_ERROR); 857 } 858 859 (**fds).fd = fd; 860 (**fds).events |= POLLRDNORM; 861 *nfds = 1; 862 } 863 864 /* set required options on all configured fds */ 865 for (nfd_i = 0; nfd_i < *nfds; nfd_i++) { 866 if (use_broadcast) { 867 const int on = 1; 868 if (setsockopt((*fds)[nfd_i].fd, SOL_SOCKET, 869 SO_BROADCAST, 870 (void *) &on, sizeof (on)) < 0) { 871 slp_err(LOG_CRIT, 0, "make_mc_target", 872 "could not enable broadcast: %s", 873 strerror(errno)); 874 } 875 } else { 876 if (setsockopt((*fds)[nfd_i].fd, IPPROTO_IP, 877 IP_MULTICAST_TTL, &ttl, 1) < 0) { 878 slp_err(LOG_CRIT, 0, "make_mc_target", 879 "could not set multicast TTL: %s", 880 strerror(errno)); 881 } 882 } 883 } 884 885 if (use_broadcast) { 886 sin->sin_addr.s_addr = INADDR_BROADCAST; 887 } else { 888 sin->sin_addr.s_addr = SLP_MULTICAST_ADDRESS; 889 } 890 891 return (SLP_OK); 892 } 893 894 /* 895 * Obtains the subnet broadcast address for each interface specified 896 * in net.slp.interfaces, and fill bcifs->sin with an array of these 897 * addresses. 898 */ 899 static SLPError make_bc_target(slp_handle_impl_t *hp, 900 struct in_addr *given_ifs, 901 int num_givenifs, struct bc_ifs *bcifs) { 902 SLPError err; 903 int i; 904 905 if ((err = slp_broadcast_addrs(hp, given_ifs, num_givenifs, 906 &(bcifs->sin), &(bcifs->num_ifs))) 907 != SLP_OK) { 908 return (err); 909 } 910 911 /* set SLP port on each sockaddr_in */ 912 for (i = 0; i < bcifs->num_ifs; i++) { 913 bcifs->sin[i].sin_port = htons(SLP_PORT); 914 } 915 916 return (SLP_OK); 917 } 918 919 /* 920 * Sends msg on 1st fd in fds for multicast, or on all interfaces 921 * specified in net.slp.interfaces for broadcast. Returns SLP_OK if 922 * msg was sent successfully on at least one interface; otherwise 923 * returns SLP_NETWORK_ERROR if msg was not sent on any interfaces. 924 */ 925 static SLPError mc_sendmsg(struct pollfd *fds, 926 struct msghdr *msg, struct bc_ifs *bcifs) { 927 928 if (slp_get_usebroadcast()) { 929 char *ifs = (char *)SLPGetProperty(SLP_CONFIG_INTERFACES); 930 931 /* hand off to broadcast-specific send function */ 932 if (ifs && *ifs && bc_sendmsg(fds, msg, bcifs) == SLP_OK) { 933 return (SLP_OK); 934 } 935 936 /* 937 * else no ifs given, or bc_sendmsg failed, so send on 938 * general broadcast addr (255.255.255.255). This will 939 * cause the message to be sent on all interfaces. The 940 * address will have been set in make_mc_target. 941 */ 942 } 943 944 /* 945 * Send only on one interface -- let routing take care of 946 * sending the message everywhere it needs to go. Sending 947 * on more than one interface can cause nasty routing loops. 948 * Note that this approach doesn't work with partitioned 949 * networks. 950 */ 951 if (sendmsg(fds[0].fd, msg, 0) < 0) { 952 slp_err(LOG_CRIT, 0, "mc_sendmsg", 953 "sendmsg failed: %s", strerror(errno)); 954 return (SLP_NETWORK_ERROR); 955 } 956 957 return (SLP_OK); 958 } 959 960 /* 961 * Send msg to each subnet broadcast address in bcifs->sin. Note 962 * that we can send on any fd (regardless of which interface to which 963 * it is bound), since the kernel will take care of routing for us. 964 * Returns err != SLP_OK only if no message was sent on any interface. 965 */ 966 static SLPError bc_sendmsg(struct pollfd *fds, struct msghdr *msg, 967 struct bc_ifs *bcifs) { 968 int i; 969 SLPBoolean sent_one = SLP_FALSE; 970 971 for (i = 0; i < bcifs->num_ifs; i++) { 972 msg->msg_name = (caddr_t)&(bcifs->sin[i]); 973 974 if (sendmsg(fds[0].fd, msg, 0) < 0) { 975 slp_err(LOG_CRIT, 0, "bc_sendmsg", 976 "sendmsg failed: %s", strerror(errno)); 977 continue; 978 } 979 sent_one = SLP_TRUE; 980 } 981 return (sent_one ? SLP_OK : SLP_NETWORK_ERROR); 982 } 983 984 /* 985 * This is where the bulk of the multicast convergance algorithm resides. 986 * mc_recvmsg() waits for data to be ready on any fd in pfd, iterates 987 * through pfd and reads data from ready fd's. It also checks timeouts 988 * and user-cancels. 989 * 990 * Parameters: 991 * pfd IN an array of pollfd structs containing fds to poll 992 * nfds IN number of elements in pfd 993 * hp IN SLPHandle from originating call 994 * scopes IN scopes to use for this message 995 * header IN the SLP message header for this message 996 * collator IN/OUT btree collator for PR list 997 * final_to IN final timeout 998 * sent IN time when message was sent 999 * now IN/OUT set to current time at beginning of convergance 1000 * noresults OUT set to 0 if any results are received 1001 * anyresults OUT set to true if any results are received 1002 * timeout IN time for this convergence iteration 1003 * 1004 * Returns only if an error has occured, or if either this retransmit 1005 * timeout or the final timeout has expired, or if hp->cancel becomes true. 1006 */ 1007 static void mc_recvmsg(struct pollfd *pfd, nfds_t nfds, slp_handle_impl_t *hp, 1008 const char *scopes, char *header, void **collator, 1009 unsigned long long final_to, 1010 unsigned long long sent, 1011 unsigned long long *now, 1012 int *noresults, int *anyresults, int timeout) { 1013 char *reply = NULL; 1014 nfds_t i; 1015 struct sockaddr_in responder; 1016 int pollerr; 1017 socklen_t addrlen = sizeof (responder); 1018 size_t mtu = slp_get_mtu(); 1019 1020 for (; !hp->cancel; ) { 1021 /* wait until we can read something */ 1022 pollerr = wait_for_response( 1023 final_to, &timeout, sent, now, pfd, nfds); 1024 if (pollerr == 0) 1025 /* timeout */ 1026 goto cleanup; 1027 if (pollerr < 0) 1028 /* error */ 1029 goto cleanup; 1030 1031 /* iterate through all fds to find one with data to read */ 1032 for (i = 0; !hp->cancel && i < nfds; i++) { 1033 1034 if (pfd[i].fd < 0 || 1035 !(pfd[i].revents & (POLLRDNORM | POLLERR))) { 1036 1037 /* unused fd or unwanted event */ 1038 continue; 1039 } 1040 1041 /* alloc reply buffer */ 1042 if (!reply && !(reply = malloc(mtu))) { 1043 slp_err(LOG_CRIT, 0, "mc_revcmsg", "out of memory"); 1044 return; 1045 } 1046 if (recvfrom(pfd[i].fd, reply, mtu, 0, 1047 (struct sockaddr *)&responder, 1048 (int *)&addrlen) < 0) { 1049 1050 /* if reply overflows, hand off to TCP */ 1051 if (errno == ENOMEM) { 1052 free(reply); reply = NULL; 1053 tcp_handoff(hp, scopes, 1054 &responder, slp_get_xid(header)); 1055 continue; 1056 } 1057 1058 /* else something nasty happened */ 1059 slp_err(LOG_CRIT, 0, "mc_recvmsg", 1060 "recvfrom failed: %s", 1061 strerror(errno)); 1062 continue; 1063 } else { 1064 /* success */ 1065 if (slp_get_overflow(reply)) { 1066 tcp_handoff(hp, scopes, 1067 &responder, slp_get_xid(header)); 1068 } 1069 /* 1070 * Add to the PR list. If this responder has already 1071 * answered, it doesn't count. 1072 */ 1073 if (add2pr_list(&(hp->msg), &responder, collator)) { 1074 (void) slp_enqueue(hp->q, reply); 1075 *noresults = 0; 1076 *anyresults = 1; 1077 reply = NULL; 1078 } 1079 1080 /* if we've exceeded maxwait, break out */ 1081 *now = now_millis(); 1082 if (*now > final_to) 1083 goto cleanup; 1084 1085 } /* end successful receive */ 1086 1087 } /* end fd iteration */ 1088 1089 /* reset poll's timeout */ 1090 timeout = timeout - (int)(*now - sent); 1091 if (timeout <= 0) { 1092 goto cleanup; 1093 } 1094 1095 } /* end main poll loop */ 1096 1097 cleanup: 1098 if (reply) { 1099 free(reply); 1100 } 1101 } 1102 1103 /* 1104 * Closes any open sockets and frees the pollfd array. 1105 */ 1106 static void free_pfds(struct pollfd *pfds, nfds_t nfds) { 1107 nfds_t i; 1108 1109 for (i = 0; i < nfds; i++) { 1110 if (pfds[i].fd <= 0) { 1111 continue; 1112 } 1113 1114 (void) close(pfds[i].fd); 1115 } 1116 1117 free(pfds); 1118 } 1119 1120 /* 1121 * Hands off a message to the TCP thread, fabricating a new target 1122 * from 'sin'. 'xid' will be used to create the XID for the TCP message. 1123 */ 1124 static void tcp_handoff(slp_handle_impl_t *hp, const char *scopes, 1125 struct sockaddr_in *sin, unsigned short xid) { 1126 slp_target_t *target; 1127 1128 target = slp_fabricate_target(sin); 1129 slp_uc_tcp_send(hp, target, scopes, SLP_TRUE, xid); 1130 } 1131 1132 /* 1133 * Returns the current time in milliseconds. 1134 */ 1135 static unsigned long long now_millis() { 1136 unsigned long long i; 1137 struct timeval tv[1]; 1138 1139 (void) gettimeofday(tv, NULL); 1140 i = (unsigned long long) tv->tv_sec * 1000; 1141 i += tv->tv_usec / 1000; 1142 return (i); 1143 } 1144 1145 /* 1146 * A wrapper around poll which waits until a reply comes in. This will 1147 * wait no longer than 'timeout' before returning. poll can return 1148 * even if no data is on the pipe or timeout has occured, so the 1149 * additional paramaters are used to break out of the wait loop if 1150 * we have exceeded the timeout value. 'final_to' is ignored if it is 0. 1151 * 1152 * returns: < 0 on error 1153 * 0 on timeout 1154 * > 0 on success (i.e. ready to read data). 1155 * side effect: 'now' is set to the time when poll found data on the pipe. 1156 */ 1157 static int wait_for_response( 1158 unsigned long long final_to, 1159 int *timeout, 1160 unsigned long long sent, 1161 unsigned long long *now, 1162 struct pollfd pfd[], nfds_t nfds) { 1163 1164 int when, pollerr; 1165 1166 /* wait until we can read something */ 1167 for (;;) { 1168 pollerr = poll(pfd, nfds, *timeout); 1169 *now = now_millis(); 1170 1171 /* ready to read */ 1172 if (pollerr > 0) 1173 return (pollerr); 1174 1175 /* time out */ 1176 if (pollerr == 0) 1177 /* timeout */ 1178 return (0); 1179 1180 /* error */ 1181 if (pollerr < 0) 1182 if (errno == EAGAIN || errno == EINTR) { 1183 /* poll is weird. */ 1184 when = (int)(*now - sent); 1185 if ( 1186 (final_to != 0 && *now > final_to) || 1187 when > *timeout) 1188 break; 1189 *timeout = *timeout - when; 1190 continue; 1191 } else { 1192 slp_err(LOG_INFO, 0, "wait for response", 1193 "poll error: %s", 1194 strerror(errno)); 1195 return (pollerr); 1196 } 1197 } 1198 1199 return (0); 1200 } 1201 1202 /* 1203 * Adds the cname of the host whose address is in 'sin' to this message's 1204 * previous responder list. The message is contained in 'msg'. 1205 * 'collator' contains the complete previous responder list, so that 1206 * even if the PR list in the message overflows and must be truncated, 1207 * the function can still correctly determine if we have heard from this 1208 * host before. 1209 * 1210 * returns: 1 if this is the first time we've heard from this host 1211 * 0 is this is a duplicate reply 1212 */ 1213 static int add2pr_list( 1214 slp_msg_t *msg, 1215 struct sockaddr_in *sin, 1216 void **collator) { 1217 1218 char **res, *cname, *p, *header; 1219 size_t mtu; 1220 size_t len, off, namelen; 1221 unsigned short prlen; 1222 1223 /* Attempt to resolve the responder's IP address to its host name */ 1224 if (!(cname = slp_gethostbyaddr((char *)&(sin->sin_addr), 1225 sizeof (sin->sin_addr)))) 1226 return (0); 1227 1228 res = slp_tsearch( 1229 cname, collator, 1230 (int (*)(const void *, const void *)) strcasecmp); 1231 if (*res != cname) { 1232 /* duplicate */ 1233 slp_err(LOG_INFO, 0, "add2pr_list", 1234 "drop PR ignored by host: %s", 1235 cname); 1236 free(cname); 1237 return (0); 1238 } 1239 1240 /* new responder: add to the msg PR list if there is room */ 1241 mtu = slp_get_mtu(); 1242 1243 header = msg->iov[0].iov_base; 1244 len = slp_get_length(header); 1245 1246 namelen = strlen(cname); 1247 if ((namelen + 2 + len) >= mtu) 1248 return (1); /* no room */ 1249 1250 /* else there is enough room */ 1251 prlen = (unsigned short)msg->prlist->iov_len; 1252 p = msg->prlist->iov_base + prlen; 1253 *p = 0; 1254 1255 if (prlen) { 1256 namelen++; /* add the ',' */ 1257 (void) strcat(p, ","); 1258 } 1259 (void) strcat(p, cname); 1260 1261 /* update msg and pr list length */ 1262 len += namelen; 1263 slp_set_length(header, len); 1264 prlen += (unsigned short)namelen; 1265 off = 0; 1266 (void) slp_add_sht(msg->prlistlen.iov_base, 2, prlen, &off); 1267 msg->prlist->iov_len += namelen; 1268 1269 return (1); 1270 } 1271 1272 /* 1273 * The iterator function used while traversing the previous responder 1274 * tree. Just frees resources. 1275 */ 1276 /*ARGSUSED2*/ 1277 static void free_pr_node(void *node, VISIT order, int level, void *cookie) { 1278 if (order == endorder || order == leaf) { 1279 char *pr = *(char **)node; 1280 free(pr); 1281 free(node); 1282 } 1283 } 1284