1/* 2 * Copyright (c) 2010 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 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 * 3. Neither the name of Apple Inc. ("Apple") nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * Portions of this software have been released under the following terms: 31 * 32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC. 33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY 34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION 35 * 36 * To anyone who acknowledges that this file is provided "AS IS" 37 * without any express or implied warranty: 38 * permission to use, copy, modify, and distribute this file for any 39 * purpose is hereby granted without fee, provided that the above 40 * copyright notices and this notice appears in all source code copies, 41 * and that none of the names of Open Software Foundation, Inc., Hewlett- 42 * Packard Company or Digital Equipment Corporation be used 43 * in advertising or publicity pertaining to distribution of the software 44 * without specific, written prior permission. Neither Open Software 45 * Foundation, Inc., Hewlett-Packard Company nor Digital 46 * Equipment Corporation makes any representations about the suitability 47 * of this software for any purpose. 48 * 49 * Copyright (c) 2007, Novell, Inc. All rights reserved. 50 * Redistribution and use in source and binary forms, with or without 51 * modification, are permitted provided that the following conditions 52 * are met: 53 * 54 * 1. Redistributions of source code must retain the above copyright 55 * notice, this list of conditions and the following disclaimer. 56 * 2. Redistributions in binary form must reproduce the above copyright 57 * notice, this list of conditions and the following disclaimer in the 58 * documentation and/or other materials provided with the distribution. 59 * 3. Neither the name of Novell Inc. nor the names of its contributors 60 * may be used to endorse or promote products derived from this 61 * this software without specific prior written permission. 62 * 63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY 67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 73 * 74 * @APPLE_LICENSE_HEADER_END@ 75 */ 76 77/* 78** 79** NAME: 80** 81** comsoc.c 82** 83** FACILITY: 84** 85** Remote Procedure Call (RPC) 86** 87** ABSTRACT: 88** 89** Veneer over the BSD socket abstraction not provided by the old sock_ 90** or new rpc_{tower,addr}_ components. 91** 92** 93*/ 94 95#include <config.h> 96#include <dce/lrpc.h> 97#include <commonp.h> 98#include <com.h> 99#include <comprot.h> 100#include <comnaf.h> 101#include <comp.h> 102#include <comsoc_bsd.h> 103#include <fcntl.h> 104#include <sys/un.h> 105#include <sys/types.h> 106#include <sys/stat.h> 107#include <sys/param.h> 108#include <sys/socket.h> 109#include <cnp.h> 110 111#if HAVE_LW_BASE_H 112#include <lw/base.h> 113#endif 114 115#if HAVE_LWMAPSECURITY_LWMAPSECURITY_H 116#include <lwmapsecurity/lwmapsecurity.h> 117#endif 118 119/* Bizarre hack for HP-UX ia64 where a system header 120 * makes reference to a kernel-only data structure 121 */ 122#if defined(__hpux) && defined(__ia64) 123union mpinfou {}; 124#endif 125#include <net/if.h> 126#include <sys/ioctl.h> 127/* Hack to ensure we actually get a definition of ioctl on AIX */ 128#if defined(_AIX) && defined(_BSD) 129int ioctl(int d, int request, ...); 130#endif 131#include <unistd.h> 132#ifdef HAVE_SYS_SOCKIO_H 133#include <sys/sockio.h> /* Not just Linux */ 134#endif 135 136/*#include <dce/cma_ux_wrappers.h>*/ 137 138/* ======================================================================== */ 139 140/* 141 * What we think a socket's buffering is in case rpc__socket_set_bufs() 142 * fails miserably. The #ifndef is here so that these values can be 143 * overridden in a per-system file. 144 */ 145 146#ifndef RPC_C_SOCKET_GUESSED_RCVBUF 147# define RPC_C_SOCKET_GUESSED_RCVBUF (4 * 1024) 148#endif 149 150#ifndef RPC_C_SOCKET_GUESSED_SNDBUF 151# define RPC_C_SOCKET_GUESSED_SNDBUF (4 * 1024) 152#endif 153 154/* 155 * Maximum send and receive buffer sizes. The #ifndef is here so that 156 * these values can be overridden in a per-system file. 157 */ 158 159#ifndef RPC_C_SOCKET_MAX_RCVBUF 160# define RPC_C_SOCKET_MAX_RCVBUF (64 * 1024) 161#endif 162 163#ifndef RPC_C_SOCKET_MAX_SNDBUF 164# define RPC_C_SOCKET_MAX_SNDBUF (64 * 1024) 165#endif 166 167/* 168 * The RPC_SOCKET_DISABLE_CANCEL/RPC_SOCKET_RESTORE_CANCEL macros 169 * are used to disable cancellation before entering library calls 170 * which were non-cancelable under CMA threads but are generally 171 * cancelable on modern POSIX systems. 172 */ 173#define RPC_SOCKET_DISABLE_CANCEL { int __cs = dcethread_enableinterrupt_throw(0); 174#define RPC_SOCKET_RESTORE_CANCEL dcethread_enableinterrupt_throw(__cs); } 175 176/* 177 * Macros to paper over the difference between the 4.4bsd and 4.3bsd 178 * socket API. 179 * 180 * The layout of a 4.4 struct sockaddr includes a 1 byte "length" field 181 * which used to be one of the bytes of the "family" field. (The "family" 182 * field is now 1 byte instead of 2 bytes.) 4.4 provides binary 183 * compatibility with applications compiled with a 4.3 sockaddr definition 184 * by inferring a default length when the supplied length is zero. Source 185 * compatibility is blown however (if _SOCKADDR_LEN is #define'd) -- 186 * applications that assign only to the "family" field will leave the 187 * "length" field possibly non-zero. 188 * 189 * Note that RPC's "sockaddr_t" is always defined to contains only a 190 * family. (We defined "rpc_addr_t" to be a struct that contains a length 191 * and a sockaddr rather than mucking with the sockaddr itself.) We 192 * assumed that "sockaddr_t" and "struct sockaddr" are the same. At 193 * 4.4, this assumption caused problems. We use RPC_SOCKET_FIX_ADDRLEN 194 * at various opportunities to make sure sockaddrs' length is zero and 195 * that makes the problems go away. 196 * 197 * ADDENDUM: 198 * This only makes the problem go away on little-endian systems 199 * where the length field on the 4.4 struct occupies the same position 200 * as the high byte of the family field on the 4.3 struct. This is 201 * no good for i386 FreeBSD, so we have actually adapted sockaddr_t 202 * to match the system struct sockaddr. 203 * -- Brian Koropoff, Likewise 204 * 205 * RPC_SOCKET_FIX_ADDRLEN takes an "rpc_addr_p_t" (or "rpc_ip_addr_p_t") 206 * as input. The complicated casting (as opposed to simply setting 207 * ".sa_len" to zero) is to ensure that the right thing happens regardless 208 * of the integer endian-ness of the system). 209 * 210 * RPC_SOCKET_INIT_MGRHDR deals with the differences in the field names of 211 * the "struct msghdr" data type between 4.3 and 4.4. 212 */ 213 214#ifdef BSD_4_4_SOCKET 215#define RPC_SOCKET_INIT_MSGHDR(msgp) ( \ 216 (msgp)->msg_control = NULL, \ 217 (msgp)->msg_controllen = 0, \ 218 (msgp)->msg_flags = 0 \ 219) 220#else 221#define RPC_SOCKET_INIT_MSGHDR(msgp) ( \ 222 (msgp)->msg_accrights = NULL, \ 223 (msgp)->msg_accrightslen = 0 \ 224) 225#endif /* BSD_4_4_SOCKET */ 226 227/*#if defined(_SOCKADDR_LEN) 228#define RPC_SOCKET_FIX_ADDRLEN(addrp) ( \ 229 ((struct osockaddr *) &(addrp)->sa)->sa_family = \ 230 ((struct sockaddr *) &(addrp)->sa)->sa_family \ 231 ) 232 #else*/ 233#define RPC_SOCKET_FIX_ADDRLEN(addrp) do { } while (0) 234/*#endif*/ 235 236#ifndef CMSG_ALIGN 237#if defined(_CMSG_DATA_ALIGN) 238#define CMSG_ALIGN _CMSG_DATA_ALIGN 239 240#elif defined(_CMSG_ALIGN) 241#define CMSG_ALIGN _CMSG_ALIGN 242 243#elif defined(__DARWIN_ALIGN32) 244#define CMSG_ALIGN __DARWIN_ALIGN32 245 246#elif defined(ALIGN) 247#define CMSG_ALIGN ALIGN 248#endif 249#endif /* CMSG_ALIGN */ 250 251#ifndef CMSG_SPACE 252#define CMSG_SPACE(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + CMSG_ALIGN(len)) 253#endif 254 255#ifndef CMSG_LEN 256#define CMSG_LEN(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + (len)) 257#endif 258 259/* 260 * BSD socket transport layer info structures 261 */ 262typedef struct rpc_bsd_transport_info_s 263{ 264 uid_t peer_uid; 265 gid_t peer_gid; 266} rpc_bsd_transport_info_t, *rpc_bsd_transport_info_p_t; 267 268typedef struct rpc_bsd_socket_s 269{ 270 int fd; 271 rpc_bsd_transport_info_t info; 272} rpc_bsd_socket_t, *rpc_bsd_socket_p_t; 273 274INTERNAL rpc_socket_error_t 275rpc__bsd_socket_set_default_options ( 276 rpc_socket_basic_t sockfd) 277{ 278#ifdef SO_NOSIGPIPE 279 int on = 1; 280 281 /* Set SO_NOSIGPIPE on the socket */ 282 if (setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof (on)) == -1) { 283 return errno; 284 } 285#endif 286 return RPC_C_SOCKET_OK; 287} 288 289INTERNAL rpc_socket_error_t rpc__bsd_socket_destruct 290( 291 rpc_socket_t sock 292); 293 294INTERNAL rpc_socket_error_t rpc__bsd_socket_construct( 295 rpc_socket_t sock, 296 rpc_protseq_id_t pseq_id, 297 rpc_transport_info_handle_t info 298); 299 300/* ======================================================================== */ 301/* 302 * R P C _ _ S O C K E T _ D U P L I C A T E 303 * 304 * Wrap the native socket representation in a rpc_socket_t. We duplicate the 305 * socket file descriptor because we will eventually end up close(2)ing it. 306 */ 307 308INTERNAL rpc_socket_error_t 309rpc__bsd_socket_duplicate( 310 rpc_socket_t sock, 311 rpc_protseq_id_t pseq_id ATTRIBUTE_UNUSED, 312 const void * sockrep /* pointer to native representation */ 313 ) 314{ 315 rpc_socket_error_t serr; 316 rpc_bsd_socket_p_t lrpc; 317 const int * sockfd = (const int *)sockrep; 318 319 if (sockfd == NULL || *sockfd == -1) { 320 return RPC_C_SOCKET_ENOTSOCK; 321 } 322 323 if (sock->pseq_id != pseq_id) { 324 return RPC_C_SOCKET_EINVAL; 325 } 326 327 serr = rpc__bsd_socket_destruct(sock); 328 if (serr != RPC_C_SOCKET_OK) { 329 return serr; 330 } 331 332 serr = rpc__bsd_socket_construct(sock, pseq_id, NULL); 333 if (serr != RPC_C_SOCKET_OK) { 334 return serr; 335 } 336 337 lrpc = (rpc_bsd_socket_p_t) sock->data.pointer; 338 339 RPC_SOCKET_DISABLE_CANCEL; 340 341 if (lrpc->fd != -1) { 342 close(lrpc->fd); 343 } 344 345 lrpc->fd = dup(*sockfd); 346 347 serr = ((lrpc->fd == -1) ? errno : RPC_C_SOCKET_OK); 348 if (serr != RPC_C_SOCKET_OK) { 349 goto error; 350 } 351 352 serr = rpc__bsd_socket_set_default_options(lrpc->fd); 353 if (serr != RPC_C_SOCKET_OK) { 354 goto error; 355 } 356 357 RPC_SOCKET_RESTORE_CANCEL; 358 359 return RPC_C_SOCKET_OK; 360 361error: 362 rpc__bsd_socket_destruct(sock); 363 return serr; 364} 365 366/* 367 * R P C _ _ S O C K E T _ C O N S T R U C T 368 * 369 * Create a new socket for the specified Protocol Sequence. 370 * The new socket has blocking IO semantics. 371 * 372 * (see BSD UNIX socket(2)). 373 */ 374 375INTERNAL rpc_socket_error_t 376rpc__bsd_socket_construct( 377 rpc_socket_t sock, 378 rpc_protseq_id_t pseq_id, 379 rpc_transport_info_handle_t info ATTRIBUTE_UNUSED 380 ) 381{ 382 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 383 rpc_bsd_socket_p_t lrpc = NULL; 384 385 /* set data.point to be 0 in case we get an error 386 and have to call rpc__bsd_socket_destruct */ 387 sock->data.pointer = NULL; 388 389 lrpc = calloc(1, sizeof(*lrpc)); 390 391 if (!lrpc) 392 { 393 serr = ENOMEM; 394 goto error; 395 } 396 397 sock->data.pointer = (void*) lrpc; 398 399 lrpc->fd = -1; 400 lrpc->info.peer_uid = -1; 401 lrpc->info.peer_gid = -1; 402 403 RPC_SOCKET_DISABLE_CANCEL; 404 lrpc->fd = socket( 405 (int) RPC_PROTSEQ_INQ_NAF_ID(pseq_id), 406 (int) RPC_PROTSEQ_INQ_NET_IF_ID(pseq_id), 407 0 /*(int) RPC_PROTSEQ_INQ_NET_PROT_ID(pseq_id)*/); 408 serr = ((lrpc->fd == -1) ? errno : RPC_C_SOCKET_OK); 409 410 if (serr == RPC_C_SOCKET_OK) { 411 serr = rpc__bsd_socket_set_default_options(lrpc->fd); 412 if (serr != RPC_C_SOCKET_OK) 413 close (lrpc->fd); 414 } 415 RPC_SOCKET_RESTORE_CANCEL; 416 417 if (serr) 418 { 419 goto error; 420 } 421 422done: 423 return serr; 424 425error: 426 if (lrpc) 427 { 428 rpc__bsd_socket_destruct(sock); 429 } 430 431 goto done; 432} 433 434/* 435 * R P C _ _ S O C K E T _ O P E N _ B A S I C 436 * 437 * A special version of socket_open that is used *only* by 438 * the low level initialization code when it is trying to 439 * determine what network services are supported by the host OS. 440 */ 441 442PRIVATE rpc_socket_error_t 443rpc__bsd_socket_open_basic( 444 rpc_naf_id_t naf, 445 rpc_network_if_id_t net_if, 446 rpc_network_protocol_id_t net_prot ATTRIBUTE_UNUSED, 447 rpc_socket_basic_t *sock 448 ) 449{ 450 rpc_socket_error_t serr; 451 452 /* 453 * Always pass zero as socket protocol to compensate for 454 * overloading the protocol field for named pipes 455 */ 456 RPC_SOCKET_DISABLE_CANCEL; 457 *sock = socket((int) naf, (int) net_if, 0); 458 serr = ((*sock == -1) ? errno : RPC_C_SOCKET_OK); 459 460 if (serr == RPC_C_SOCKET_OK) { 461 serr = rpc__bsd_socket_set_default_options(*sock); 462 if (serr != RPC_C_SOCKET_OK) 463 close (*sock); 464 } 465 RPC_SOCKET_RESTORE_CANCEL; 466 467 return serr; 468} 469 470PRIVATE rpc_socket_error_t 471rpc__bsd_socket_close_basic( 472 rpc_socket_basic_t sock 473 ) 474{ 475 rpc_socket_error_t serr; 476 477 RPC_LOG_SOCKET_CLOSE_NTR; 478 RPC_SOCKET_DISABLE_CANCEL; 479 serr = (close(sock) == -1) ? errno : RPC_C_SOCKET_OK; 480 RPC_SOCKET_RESTORE_CANCEL; 481 RPC_LOG_SOCKET_CLOSE_XIT; 482 483 return (serr); 484} 485 486 487/* 488 * R P C _ _ S O C K E T _ C L O S E 489 * 490 * Close (destroy) a socket. 491 * 492 * (see BSD UNIX close(2)). 493 */ 494 495INTERNAL rpc_socket_error_t rpc__bsd_socket_destruct 496( 497 rpc_socket_t sock 498) 499{ 500 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 501 rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer; 502 503 if (lrpc && lrpc->fd > 0) 504 { 505 506 RPC_LOG_SOCKET_CLOSE_NTR; 507 RPC_SOCKET_DISABLE_CANCEL; 508 serr = (close(lrpc->fd) == -1) ? errno : RPC_C_SOCKET_OK; 509 RPC_SOCKET_RESTORE_CANCEL; 510 RPC_LOG_SOCKET_CLOSE_XIT; 511 } 512 513 if (lrpc) 514 { 515 free(lrpc); 516 sock->data.pointer = NULL; 517 } 518 519 return serr; 520} 521 522/* 523 * R P C _ _ S O C K E T _ B I N D 524 * 525 * Bind a socket to a specified local address. 526 * 527 * (see BSD UNIX bind(2)). 528 */ 529 530INTERNAL rpc_socket_error_t rpc__bsd_socket_bind 531( 532 rpc_socket_t sock, 533 rpc_addr_p_t addr 534) 535{ 536 rpc_socket_error_t serr = EINVAL; 537 unsigned32 status; 538 rpc_addr_p_t temp_addr = NULL; 539 boolean has_endpoint = false; 540 int setsock_val = 1; 541 int ncalrpc; 542 rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer; 543 544 RPC_LOG_SOCKET_BIND_NTR; 545 546 ncalrpc = addr->rpc_protseq_id == rpc_c_protseq_id_ncalrpc; 547 548 /* 549 * Check if the address has a well-known endpoint. 550 */ 551 if (addr->rpc_protseq_id == rpc_c_protseq_id_ncacn_ip_tcp || ncalrpc) 552 { 553 unsigned_char_t *endpoint; 554 555 rpc__naf_addr_inq_endpoint (addr, &endpoint, &status); 556 557 if (status == rpc_s_ok && endpoint != NULL) 558 { 559 if (endpoint[0] != '\0') /* test for null string */ 560 has_endpoint = true; 561 562 rpc_string_free (&endpoint, &status); 563 } 564 status = rpc_s_ok; 565 } 566 567 /* 568 * If there is no port restriction in this address family, then do a 569 * simple bind. 570 */ 571 572 if (! RPC_PROTSEQ_TEST_PORT_RESTRICTION (addr -> rpc_protseq_id)) 573 { 574 if (!has_endpoint && ncalrpc) 575 { 576 serr = 0; 577 } 578 else 579 { 580#if defined(SOL_SOCKET) && defined(SO_REUSEADDR) 581 setsockopt(lrpc->fd, SOL_SOCKET, SO_REUSEADDR, 582 &setsock_val, sizeof(setsock_val)); 583#endif 584 if (addr->sa.family == AF_UNIX && addr->sa.data[0] != '\0') 585 { 586 // This function is going to bind a named socket. First, try 587 // to delete the path incase a previous instance of a program 588 // left it behind. 589 // 590 // Ignore any errors from this function. 591 unlink((const char*)addr->sa.data); 592 } 593 serr = 594 (bind(lrpc->fd, (struct sockaddr *)&addr->sa, addr->len) == -1) ? 595 errno : RPC_C_SOCKET_OK; 596 } 597 } /* no port restriction */ 598 599 else 600 { 601 /* 602 * Port restriction is in place. If the address has a well-known 603 * endpoint, then do a simple bind. 604 */ 605 606 if (has_endpoint) 607 { 608#if defined(SOL_SOCKET) && defined(SO_REUSEADDR) 609 setsockopt(lrpc->fd, SOL_SOCKET, SO_REUSEADDR, 610 &setsock_val, sizeof(setsock_val)); 611#endif 612 serr = (bind(lrpc->fd, (struct sockaddr *)&addr->sa, addr->len) == -1)? 613 errno : RPC_C_SOCKET_OK; 614 } /* well-known endpoint */ 615 else 616 { 617 618 unsigned_char_t *endpoint; 619 unsigned char c; 620 621 rpc__naf_addr_inq_endpoint (addr, &endpoint, &status); 622 623 c = endpoint[0]; /* grab first char */ 624 rpc_string_free (&endpoint, &status); 625 626 if (c != '\0') /* test for null string */ 627 { 628 serr = (bind(lrpc->fd, (struct sockaddr *)&addr->sa, addr->len) == -1)? 629 errno : RPC_C_SOCKET_OK; 630 } /* well-known endpoint */ 631 632 else 633 { 634 /* 635 * Port restriction is in place and the address doesn't have a 636 * well-known endpoint. Try to bind until we hit a good port, 637 * or exhaust the retry count. 638 * 639 * Make a copy of the address to work in; if we hardwire an 640 * endpoint into our caller's address, later logic could infer 641 * that it is a well-known endpoint. 642 */ 643 644 unsigned32 i; 645 boolean found; 646 647 for (i = 0, found = false; 648 (i < RPC_PORT_RESTRICTION_INQ_N_TRIES (addr->rpc_protseq_id)) 649 && !found; 650 i++) 651 { 652 unsigned_char_p_t port_name; 653 654 rpc__naf_addr_overcopy (addr, &temp_addr, &status); 655 656 if (status != rpc_s_ok) 657 { 658 serr = RPC_C_SOCKET_EIO; 659 break; 660 } 661 662 rpc__naf_get_next_restricted_port (temp_addr -> rpc_protseq_id, 663 &port_name, &status); 664 665 if (status != rpc_s_ok) 666 { 667 serr = RPC_C_SOCKET_EIO; 668 break; 669 } 670 671 rpc__naf_addr_set_endpoint (port_name, &temp_addr, &status); 672 673 if (status != rpc_s_ok) 674 { 675 serr = RPC_C_SOCKET_EIO; 676 rpc_string_free (&port_name, &status); 677 break; 678 } 679 680 if (bind(lrpc->fd, (struct sockaddr *)&temp_addr->sa, temp_addr->len) == 0) 681 { 682 found = true; 683 serr = RPC_C_SOCKET_OK; 684 } 685 else 686 serr = RPC_C_SOCKET_EIO; 687 688 rpc_string_free (&port_name, &status); 689 } /* for i */ 690 691 if (!found) 692 { 693 serr = RPC_C_SOCKET_EADDRINUSE; 694 } 695 } /* no well-known endpoint */ 696 } /* has endpoint */ 697 } /* port restriction is in place */ 698 699 if (serr == RPC_C_SOCKET_OK && ncalrpc && has_endpoint) 700 { 701 struct sockaddr_un *skun = (struct sockaddr_un *)&addr->sa; 702 703 serr = chmod(skun->sun_path, 704 S_IRUSR | S_IWUSR | S_IXUSR | 705 S_IRGRP | S_IWGRP | S_IXGRP | 706 S_IROTH | S_IWOTH | S_IXOTH) == -1 ? errno : RPC_C_SOCKET_OK; 707 } 708 709 if (temp_addr != NULL) 710 rpc__naf_addr_free (&temp_addr, &status); 711 712 RPC_LOG_SOCKET_BIND_XIT; 713 return (serr); 714} 715 716INTERNAL rpc_socket_error_t rpc__bsd_socket_getpeereid 717( 718 rpc_socket_t sock, 719 uid_t *euid, 720 gid_t *egid 721); 722 723#if !defined(SO_PEERCRED) && !defined(HAVE_GETPEEREID) 724 725INTERNAL rpc_socket_error_t rpc__bsd_socket_sendpeereid 726( 727 rpc_socket_t sock, 728 rpc_addr_p_t addr 729); 730 731INTERNAL rpc_socket_error_t rpc__bsd_socket_recvpeereid 732( 733 rpc_socket_t sock, 734 uid_t *euid, 735 gid_t *egid 736); 737 738#endif 739 740 741/* 742 * R P C _ _ S O C K E T _ C O N N E C T 743 * 744 * Connect a socket to a specified peer's address. 745 * This is used only by Connection oriented Protocol Services. 746 * 747 * (see BSD UNIX connect(2)). 748 */ 749 750INTERNAL rpc_socket_error_t rpc__bsd_socket_connect 751( 752 rpc_socket_t sock, 753 rpc_addr_p_t addr, 754 rpc_cn_assoc_t *assoc ATTRIBUTE_UNUSED 755) 756{ 757 rpc_socket_error_t serr; 758 //rpc_binding_rep_t *binding_rep; 759 unsigned_char_t *netaddr, *endpoint; 760 unsigned32 dbg_status; 761 rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer; 762 763 rpc__naf_addr_inq_netaddr (addr, 764 &netaddr, 765 &dbg_status); 766 rpc__naf_addr_inq_endpoint (addr, 767 &endpoint, 768 &dbg_status); 769 770 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL, 771 ("CN: connection request initiated to %s[%s]\n", 772 netaddr, 773 endpoint)); 774 775connect_again: 776 RPC_LOG_SOCKET_CONNECT_NTR; 777 serr = (connect ( 778 (int) lrpc->fd, 779 (struct sockaddr *) (&addr->sa), 780 (int) (addr->len)) 781 == -1) ? errno : RPC_C_SOCKET_OK; 782 RPC_LOG_SOCKET_CONNECT_XIT; 783 if (serr == EINTR) 784 { 785 goto connect_again; 786 } 787 else if (serr != RPC_C_SOCKET_OK) 788 { 789 goto error; 790 } 791 792#if !defined(SO_PEERCRED) && !defined(HAVE_GETPEEREID) 793 serr = rpc__bsd_socket_sendpeereid(sock, addr); 794#endif 795 796cleanup: 797 rpc_string_free (&netaddr, &dbg_status); 798 rpc_string_free (&endpoint, &dbg_status); 799 800 return serr; 801 802error: 803 goto cleanup; 804} 805 806/* 807 * R P C _ _ S O C K E T _ A C C E P T 808 * 809 * Accept a connection on a socket, creating a new socket for the new 810 * connection. A rpc_addr_t appropriate for the NAF corresponding to 811 * this socket must be provided. addr.len must set to the actual size 812 * of addr.sa. This operation fills in addr.sa and sets addr.len to 813 * the new size of the field. This is used only by Connection oriented 814 * Protocol Services. 815 * 816 * (see BSD UNIX accept(2)). 817 */ 818 819INTERNAL rpc_socket_error_t rpc__bsd_socket_accept 820( 821 rpc_socket_t sock, 822 rpc_addr_p_t addr, 823 rpc_socket_t *newsock 824) 825{ 826 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 827 rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer; 828 rpc_bsd_socket_p_t newlrpc = NULL; 829 uid_t euid = -1; 830 gid_t egid = -1; 831 832 *newsock = malloc(sizeof (**newsock)); 833 834 if (!*newsock) 835 { 836 return ENOMEM; 837 } 838 839 (*newsock)->vtbl = sock->vtbl; 840 (*newsock)->pseq_id = sock->pseq_id; 841 842 newlrpc = malloc(sizeof(*newlrpc)); 843 if (!newlrpc) 844 { 845 return ENOMEM; 846 } 847 848 newlrpc->info.peer_uid = -1; 849 newlrpc->info.peer_gid = -1; 850 851 (*newsock)->data.pointer = newlrpc; 852 853accept_again: 854 RPC_LOG_SOCKET_ACCEPT_NTR; 855 if (addr == NULL) 856 { 857 socklen_t addrlen; 858 859 addrlen = 0; 860 newlrpc->fd = accept 861 ((int) lrpc->fd, (struct sockaddr *) NULL, &addrlen); 862 } 863 else 864 { 865 newlrpc->fd = accept 866 ((int) lrpc->fd, (struct sockaddr *) (&addr->sa), (&addr->len)); 867 } 868 serr = (newlrpc->fd == -1) ? errno : RPC_C_SOCKET_OK; 869 RPC_LOG_SOCKET_ACCEPT_XIT; 870 871 if (!serr) 872 { 873 serr = rpc__bsd_socket_getpeereid((*newsock), &euid, &egid); 874 } 875 else 876 { 877 goto cleanup; 878 } 879 880 if (serr == EINTR) 881 { 882 goto accept_again; 883 } 884 885 newlrpc->info.peer_uid = euid; 886 newlrpc->info.peer_gid = egid; 887 888cleanup: 889 if (serr && newlrpc) 890 { 891 free(newlrpc); 892 } 893 894 if (serr && *newsock) 895 { 896 free(*newsock); 897 } 898 899 return serr; 900} 901 902/* 903 * R P C _ _ S O C K E T _ L I S T E N 904 * 905 * Listen for a connection on a socket. 906 * This is used only by Connection oriented Protocol Services. 907 * 908 * (see BSD UNIX listen(2)). 909 */ 910 911INTERNAL rpc_socket_error_t rpc__bsd_socket_listen 912( 913 rpc_socket_t sock, 914 int backlog 915) 916{ 917 rpc_socket_error_t serr; 918 rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer; 919 920 RPC_LOG_SOCKET_LISTEN_NTR; 921 RPC_SOCKET_DISABLE_CANCEL; 922 serr = (listen(lrpc->fd, backlog) == -1) ? errno : RPC_C_SOCKET_OK; 923 RPC_SOCKET_RESTORE_CANCEL; 924 RPC_LOG_SOCKET_LISTEN_XIT; 925 return (serr); 926} 927 928/* 929 * R P C _ _ S O C K E T _ S E N D M S G 930 * 931 * Send a message over a given socket. An error code as well as the 932 * actual number of bytes sent are returned. 933 * 934 * (see BSD UNIX sendmsg(2)). 935 */ 936 937INTERNAL rpc_socket_error_t rpc__bsd_socket_sendmsg 938( 939 rpc_socket_t sock, 940 rpc_socket_iovec_p_t iov, /* array of bufs of data to send */ 941 int iovcnt, /* number of bufs */ 942 rpc_addr_p_t addr, /* addr of receiver */ 943 size_t *cc /* returned number of bytes actually sent */ 944) 945{ 946 ssize_t ret; 947 rpc_socket_error_t serr; 948 struct msghdr msg; 949 rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer; 950 951 *cc = 0; 952 953sendmsg_again: 954 955 memset(&msg, 0, sizeof(msg)); 956 RPC_LOG_SOCKET_SENDMSG_NTR; 957 RPC_SOCKET_INIT_MSGHDR(&msg); 958 if ((addr) != NULL) 959 { 960 RPC_SOCKET_FIX_ADDRLEN(addr); 961 msg.msg_name = (caddr_t) &(addr)->sa; 962 msg.msg_namelen = (addr)->len; 963 } 964 else 965 { 966 msg.msg_name = (caddr_t) NULL; 967 } 968 msg.msg_iov = iov; 969 msg.msg_iovlen = iovcnt; 970 971 ret = dcethread_sendmsg (lrpc->fd, &msg, 0); 972 if (ret == (size_t) -1) 973 { 974 serr = errno; 975 } 976 else 977 { 978 serr = RPC_C_SOCKET_OK; 979 *cc = ret; 980 } 981 982 RPC_LOG_SOCKET_SENDMSG_XIT; 983 if (serr == EINTR) 984 { 985 goto sendmsg_again; 986 } 987 988 return (serr); 989} 990 991/* 992 * R P C _ _ S O C K E T _ R E C V F R O M 993 * 994 * Recieve the next buffer worth of information from a socket. A 995 * rpc_addr_t appropriate for the NAF corresponding to this socket must 996 * be provided. addr.len must set to the actual size of addr.sa. This 997 * operation fills in addr.sa and sets addr.len to the new size of the 998 * field. An error status as well as the actual number of bytes received 999 * are also returned. 1000 * 1001 * (see BSD UNIX recvfrom(2)). 1002 */ 1003 1004INTERNAL rpc_socket_error_t rpc__bsd_socket_recvfrom 1005( 1006 rpc_socket_t sock, 1007 byte_p_t buf, /* buf for rcvd data */ 1008 int len, /* len of above buf */ 1009 rpc_addr_p_t from, /* addr of sender */ 1010 size_t *cc /* returned number of bytes actually rcvd */ 1011) 1012{ 1013 ssize_t ret; 1014 rpc_socket_error_t serr; 1015 struct msghdr msg; 1016 rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer; 1017 1018 *cc = 0; 1019 1020recvfrom_again: 1021 if (from != NULL) 1022 { 1023 RPC_SOCKET_FIX_ADDRLEN(from); 1024 } 1025 1026 RPC_LOG_SOCKET_RECVFROM_NTR; 1027 1028 ret = dcethread_recvfrom(lrpc->fd, buf, len, 0 /* flags */, 1029 &from->sa, &from->len); 1030 if (ret == (size_t) -1) 1031 { 1032 serr = errno; 1033 } 1034 else 1035 { 1036 serr = RPC_C_SOCKET_OK; 1037 *cc = ret; 1038 } 1039 1040 RPC_LOG_SOCKET_RECVFROM_XIT; 1041 RPC_SOCKET_FIX_ADDRLEN(from); 1042 if (serr == EINTR) 1043 { 1044 goto recvfrom_again; 1045 } 1046 1047 return serr; 1048} 1049 1050/* 1051 * R P C _ _ S O C K E T _ R E C V M S G 1052 * 1053 * Receive a message over a given socket. A rpc_addr_t appropriate for 1054 * the NAF corresponding to this socket must be provided. addr.len must 1055 * set to the actual size of addr.sa. This operation fills in addr.sa 1056 * and sets addr.len to the new size of the field. An error code as 1057 * well as the actual number of bytes received are also returned. 1058 * 1059 * (see BSD UNIX recvmsg(2)). 1060 */ 1061 1062INTERNAL rpc_socket_error_t rpc__bsd_socket_recvmsg 1063( 1064 rpc_socket_t sock, 1065 rpc_socket_iovec_p_t iov, /* array of bufs for rcvd data */ 1066 int iovcnt, /* number of bufs */ 1067 rpc_addr_p_t addr, /* addr of sender */ 1068 size_t *cc /* returned number of bytes actually rcvd */ 1069) 1070{ 1071 ssize_t ret; 1072 rpc_socket_error_t serr; 1073 struct msghdr msg; 1074 rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer; 1075 1076 *cc = 0; 1077 1078recvmsg_again: 1079 1080 memset(&msg, 0, sizeof(msg)); 1081 RPC_LOG_SOCKET_RECVMSG_NTR; 1082 RPC_SOCKET_INIT_MSGHDR(&msg); 1083 if (addr != NULL) 1084 { 1085 RPC_SOCKET_FIX_ADDRLEN(addr); 1086 msg.msg_name = (caddr_t) &addr->sa; 1087 msg.msg_namelen = addr->len; 1088 } 1089 else 1090 { 1091 msg.msg_name = (caddr_t) NULL; 1092 } 1093 msg.msg_iov = iov; 1094 msg.msg_iovlen = iovcnt; 1095 1096 ret = dcethread_recvmsg (lrpc->fd, &msg, 0); 1097 if (ret == (ssize_t)-1) 1098 { 1099 serr = errno; 1100 } 1101 else 1102 { 1103 serr = RPC_C_SOCKET_OK; 1104 *cc = ret; 1105 } 1106 1107 RPC_LOG_SOCKET_RECVMSG_XIT; 1108 if (serr == EINTR) 1109 { 1110 goto recvmsg_again; 1111 } 1112 1113 if (addr != NULL) 1114 { 1115 addr->len = msg.msg_namelen; 1116 } 1117 1118 return serr; 1119} 1120 1121/* 1122 * R P C _ _ S O C K E T _ I N Q _ A D D R 1123 * 1124 * Return the local address associated with a socket. A rpc_addr_t 1125 * appropriate for the NAF corresponding to this socket must be provided. 1126 * addr.len must set to the actual size of addr.sa. This operation fills 1127 * in addr.sa and sets addr.len to the new size of the field. 1128 * 1129 * !!! NOTE: You should use rpc__naf_desc_inq_addr() !!! 1130 * 1131 * This routine is indended for use only by the internal routine: 1132 * rpc__naf_desc_inq_addr(). rpc__bsd_socket_inq_endpoint() only has the 1133 * functionality of BSD UNIX getsockname() which doesn't (at least not 1134 * on all systems) return the local network portion of a socket's address. 1135 * rpc__naf_desc_inq_addr() returns the complete address for a socket. 1136 * 1137 * (see BSD UNIX getsockname(2)). 1138 */ 1139 1140INTERNAL rpc_socket_error_t rpc__bsd_socket_inq_endpoint 1141( 1142 rpc_socket_t sock, 1143 rpc_addr_p_t addr 1144) 1145{ 1146 rpc_socket_error_t serr; 1147 rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer; 1148 1149 RPC_LOG_SOCKET_INQ_EP_NTR; 1150 RPC_SOCKET_FIX_ADDRLEN(addr); 1151 RPC_SOCKET_DISABLE_CANCEL; 1152 serr = (getsockname(lrpc->fd, (void*)&addr->sa, &addr->len) == -1) ? errno : RPC_C_SOCKET_OK; 1153 RPC_SOCKET_RESTORE_CANCEL; 1154 RPC_SOCKET_FIX_ADDRLEN(addr); 1155 RPC_LOG_SOCKET_INQ_EP_XIT; 1156 return (serr); 1157} 1158 1159/* 1160 * R P C _ _ S O C K E T _ S E T _ B R O A D C A S T 1161 * 1162 * Enable broadcasting for the socket (as best it can). 1163 * Used only by Datagram based Protocol Services. 1164 */ 1165 1166INTERNAL rpc_socket_error_t rpc__bsd_socket_set_broadcast 1167( 1168 rpc_socket_t sock 1169) 1170{ 1171#ifdef SO_BROADCAST 1172 int setsock_val = 1; 1173 rpc_socket_error_t serr; 1174 rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer; 1175 1176 RPC_SOCKET_DISABLE_CANCEL; 1177 serr = (setsockopt(lrpc->fd, SOL_SOCKET, SO_BROADCAST, 1178 &setsock_val, sizeof(setsock_val)) == -1) ? errno : RPC_C_SOCKET_OK; 1179 RPC_SOCKET_RESTORE_CANCEL; 1180 if (serr) 1181 { 1182 RPC_DBG_GPRINTF(("(rpc__bsd_socket_set_broadcast) error=%d\n", serr)); 1183 } 1184 1185 return(serr); 1186#else 1187 return(RPC_C_SOCKET_OK); 1188#endif 1189} 1190 1191/* 1192 * R P C _ _ S O C K E T _ S E T _ B U F S 1193 * 1194 * Set the socket's send and receive buffer sizes and return the new 1195 * values. Note that the sizes are min'd with 1196 * "rpc_c_socket_max_{snd,rcv}buf" because systems tend to fail the 1197 * operation rather than give the max buffering if the max is exceeded. 1198 * 1199 * If for some reason your system is screwed up and defines SOL_SOCKET 1200 * and SO_SNDBUF, but doesn't actually support the SO_SNDBUF and SO_RCVBUF 1201 * operations AND using them would result in nasty behaviour (i.e. they 1202 * don't just return some error code), define NO_SO_SNDBUF. 1203 * 1204 * If the buffer sizes provided are 0, then we use the operating 1205 * system default (i.e. we don't set anything at all). 1206 */ 1207 1208INTERNAL rpc_socket_error_t rpc__bsd_socket_set_bufs 1209( 1210 rpc_socket_t sock, 1211 unsigned32 txsize, 1212 unsigned32 rxsize, 1213 unsigned32 *ntxsize, 1214 unsigned32 *nrxsize 1215) 1216{ 1217 socklen_t sizelen; 1218 int e; 1219 rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer; 1220 1221 RPC_SOCKET_DISABLE_CANCEL; 1222 1223#if (defined (SOL_SOCKET) && defined(SO_SNDBUF)) && !defined(NO_SO_SNDBUF) 1224 1225 /* 1226 * Set the new sizes. 1227 */ 1228 1229 txsize = MIN(txsize, RPC_C_SOCKET_MAX_SNDBUF); 1230 if (txsize != 0) 1231 { 1232 e = setsockopt(lrpc->fd, SOL_SOCKET, SO_SNDBUF, &txsize, sizeof(txsize)); 1233 if (e == -1) 1234 { 1235 RPC_DBG_GPRINTF 1236 (("(rpc__bsd_socket_set_bufs) WARNING: set sndbuf (%d) failed - error = %d\n", 1237 txsize, errno)); 1238 } 1239 } 1240 1241 rxsize = MIN(rxsize, RPC_C_SOCKET_MAX_RCVBUF); 1242 if (rxsize != 0) 1243 { 1244 e = setsockopt(lrpc->fd, SOL_SOCKET, SO_RCVBUF, &rxsize, sizeof(rxsize)); 1245 if (e == -1) 1246 { 1247 RPC_DBG_GPRINTF 1248 (("(rpc__bsd_socket_set_bufs) WARNING: set rcvbuf (%d) failed - error = %d\n", 1249 rxsize, errno)); 1250 } 1251 } 1252 1253 /* 1254 * Get the new sizes. If this fails, just return some guessed sizes. 1255 */ 1256 *ntxsize = 0; 1257 sizelen = sizeof *ntxsize; 1258 e = getsockopt(lrpc->fd, SOL_SOCKET, SO_SNDBUF, ntxsize, &sizelen); 1259 if (e == -1) 1260 { 1261 RPC_DBG_GPRINTF 1262 (("(rpc__bsd_socket_set_bufs) WARNING: get sndbuf failed - error = %d\n", errno)); 1263 *ntxsize = RPC_C_SOCKET_GUESSED_SNDBUF; 1264 } 1265 1266 *nrxsize = 0; 1267 sizelen = sizeof *nrxsize; 1268 e = getsockopt(lrpc->fd, SOL_SOCKET, SO_RCVBUF, nrxsize, &sizelen); 1269 if (e == -1) 1270 { 1271 RPC_DBG_GPRINTF 1272 (("(rpc__bsd_socket_set_bufs) WARNING: get rcvbuf failed - error = %d\n", errno)); 1273 *nrxsize = RPC_C_SOCKET_GUESSED_RCVBUF; 1274 } 1275 1276# ifdef apollo 1277 /* 1278 * On Apollo, modifying the socket buffering doesn't actually do 1279 * anything on IP sockets, but the calls succeed anyway. We can 1280 * detect this by the fact that the new buffer length returned is 1281 * 0. Return what we think the actually length is. 1282 */ 1283 if (rxsize != 0 && *nrxsize == 0) 1284 { 1285 *nrxsize = (8 * 1024); 1286 } 1287 if (txsize != 0 && *ntxsize == 0) 1288 { 1289 *ntxsize = (8 * 1024); 1290 } 1291# endif 1292 1293#else 1294 1295 *ntxsize = RPC_C_SOCKET_GUESSED_SNDBUF; 1296 *nrxsize = RPC_C_SOCKET_GUESSED_RCVBUF; 1297 1298#endif 1299 1300 RPC_SOCKET_RESTORE_CANCEL; 1301 1302 return (RPC_C_SOCKET_OK); 1303} 1304 1305/* 1306 * R P C _ _ S O C K E T _ S E T _ N B I O 1307 * 1308 * Set a socket to non-blocking mode. 1309 * 1310 * Return RPC_C_SOCKET_OK on success, otherwise an error value. 1311 */ 1312 1313INTERNAL rpc_socket_error_t rpc__bsd_socket_set_nbio 1314( 1315 rpc_socket_t sock 1316) 1317{ 1318 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 1319 rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer; 1320 1321 RPC_SOCKET_DISABLE_CANCEL; 1322 serr = ((fcntl(lrpc->fd, F_SETFL, O_NDELAY) == -1) ? errno : RPC_C_SOCKET_OK); 1323 RPC_SOCKET_RESTORE_CANCEL; 1324 if (serr) 1325 { 1326 RPC_DBG_GPRINTF(("(rpc__bsd_socket_set_nbio) error=%d\n", serr)); 1327 } 1328 1329 return (serr); 1330} 1331 1332/* 1333 * R P C _ _ S O C K E T _ S E T _ C L O S E _ O N _ E X E C 1334 * 1335 * 1336 * Set a socket to a mode whereby it is not inherited by a spawned process 1337 * executing some new image. This is possibly a no-op on some systems. 1338 * 1339 * Return RPC_C_SOCKET_OK on success, otherwise an error value. 1340 */ 1341 1342INTERNAL rpc_socket_error_t rpc__bsd_socket_set_close_on_exec 1343( 1344 rpc_socket_t sock 1345) 1346{ 1347 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 1348 rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer; 1349 1350 RPC_SOCKET_DISABLE_CANCEL; 1351 serr = ((fcntl(lrpc->fd, F_SETFD, 1) == -1) ? errno : RPC_C_SOCKET_OK); 1352 RPC_SOCKET_RESTORE_CANCEL; 1353 if (serr) 1354 { 1355 RPC_DBG_GPRINTF(("(rpc__bsd_socket_set_close_on_exec) error=%d\n", serr)); 1356 } 1357 return (serr); 1358} 1359 1360/* 1361 * R P C _ _ S O C K E T _ G E T P E E R N A M E 1362 * 1363 * Get name of connected peer. 1364 * This is used only by Connection oriented Protocol Services. 1365 * 1366 * (see BSD UNIX getpeername(2)). 1367 */ 1368 1369INTERNAL rpc_socket_error_t rpc__bsd_socket_getpeername 1370( 1371 rpc_socket_t sock, 1372 rpc_addr_p_t addr 1373) 1374{ 1375 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 1376 rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer; 1377 1378 RPC_SOCKET_FIX_ADDRLEN(addr); 1379 RPC_SOCKET_DISABLE_CANCEL; 1380 serr = (getpeername(lrpc->fd, (void *)&addr->sa, &addr->len) == -1) ? errno : RPC_C_SOCKET_OK; 1381 RPC_SOCKET_RESTORE_CANCEL; 1382 RPC_SOCKET_FIX_ADDRLEN(addr); 1383 1384 return (serr); 1385} 1386 1387/* 1388 * R P C _ _ S O C K E T _ G E T _ I F _ I D 1389 * 1390 * Get socket network interface id (socket type). 1391 * 1392 * (see BSD UNIX getsockopt(2)). 1393 */ 1394 1395INTERNAL rpc_socket_error_t rpc__bsd_socket_get_if_id 1396( 1397 rpc_socket_t sock, 1398 rpc_network_if_id_t *network_if_id 1399) 1400{ 1401 socklen_t optlen = 0; 1402 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 1403 rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer; 1404 1405 optlen = sizeof(rpc_network_if_id_t); 1406 1407 RPC_SOCKET_DISABLE_CANCEL; 1408 serr = (getsockopt (lrpc->fd, 1409 SOL_SOCKET, 1410 SO_TYPE, 1411 network_if_id, 1412 &optlen) == -1 ? errno : RPC_C_SOCKET_OK); 1413 RPC_SOCKET_RESTORE_CANCEL; 1414 return serr; 1415} 1416 1417/* 1418 * R P C _ _ S O C K E T _ S E T _ K E E P A L I V E 1419 * 1420 * Enable periodic transmissions on a connected socket, when no 1421 * other data is being exchanged. If the other end does not respond to 1422 * these messages, the connection is considered broken and the 1423 * so_error variable is set to ETIMEDOUT. 1424 * Used only by Connection based Protocol Services. 1425 * 1426 * (see BSD UNIX setsockopt(2)). 1427 */ 1428 1429INTERNAL rpc_socket_error_t rpc__bsd_socket_set_keepalive 1430( 1431 rpc_socket_t sock 1432) 1433{ 1434#ifdef SO_KEEPALIVE 1435 int setsock_val = 1; 1436 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 1437 rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer; 1438 1439 RPC_SOCKET_DISABLE_CANCEL; 1440 serr = ((setsockopt(lrpc->fd, SOL_SOCKET, SO_KEEPALIVE, 1441 &setsock_val, sizeof(setsock_val)) == -1) ? errno : RPC_C_SOCKET_OK); 1442 RPC_SOCKET_RESTORE_CANCEL; 1443 if (serr) 1444 { 1445 RPC_DBG_GPRINTF(("(rpc__bsd_socket_set_keepalive) error=%d\n", serr)); 1446 } 1447 1448 return(serr); 1449#else 1450 return(RPC_C_SOCKET_OK); 1451#endif 1452} 1453 1454 1455/* 1456 * R P C _ _ S O C K E T _ N O W R I T E B L O C K _ W A I T 1457 * 1458 * Wait until the a write on the socket should succede without 1459 * blocking. If tmo is NULL, the wait is unbounded, otherwise 1460 * tmo specifies the max time to wait. RPC_C_SOCKET_ETIMEDOUT 1461 * if a timeout occurs. This operation in not cancellable. 1462 */ 1463 1464INTERNAL rpc_socket_error_t rpc__bsd_socket_nowriteblock_wait 1465( 1466 rpc_socket_t sock, 1467 struct timeval *tmo 1468) 1469{ 1470 fd_set write_fds; 1471 int nfds, num_found; 1472 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 1473 rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer; 1474 1475 FD_ZERO (&write_fds); 1476 FD_SET (lrpc->fd, &write_fds); 1477 nfds = lrpc->fd + 1; 1478 1479 RPC_SOCKET_DISABLE_CANCEL; 1480 num_found = dcethread_select(nfds, NULL, (void *)&write_fds, NULL, tmo); 1481 serr = ((num_found < 0) ? errno : RPC_C_SOCKET_OK); 1482 RPC_SOCKET_RESTORE_CANCEL; 1483 1484 if (serr) 1485 { 1486 RPC_DBG_GPRINTF(("(rpc__bsd_socket_nowriteblock_wait) error=%d\n", serr)); 1487 return serr; 1488 } 1489 1490 if (num_found == 0) 1491 { 1492 RPC_DBG_GPRINTF(("(rpc__bsd_socket_nowriteblock_wait) timeout\n")); 1493 return RPC_C_SOCKET_ETIMEDOUT; 1494 } 1495 1496 return RPC_C_SOCKET_OK; 1497} 1498 1499 1500/* 1501 * R P C _ _ S O C K E T _ S E T _ R C V T I M E O 1502 * 1503 * Set receive timeout on a socket 1504 * Used only by Connection based Protocol Services. 1505 * 1506 * (see BSD UNIX setsockopt(2)). 1507 */ 1508 1509INTERNAL rpc_socket_error_t rpc__bsd_socket_set_rcvtimeo 1510( 1511 rpc_socket_t sock, 1512 struct timeval *tmo 1513) 1514{ 1515#ifdef SO_RCVTIMEO 1516 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 1517 rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer; 1518 1519 RPC_SOCKET_DISABLE_CANCEL; 1520 serr = ((setsockopt(lrpc->fd, SOL_SOCKET, SO_RCVTIMEO, 1521 tmo, sizeof(*tmo)) == -1) ? errno : RPC_C_SOCKET_OK); 1522 RPC_SOCKET_RESTORE_CANCEL; 1523 if (serr) 1524 { 1525 RPC_DBG_GPRINTF(("(rpc__bsd_socket_set_rcvtimeo) error=%d\n", serr)); 1526 } 1527 1528 return(serr); 1529#else 1530 return(RPC_C_SOCKET_OK); 1531#endif 1532} 1533 1534/* 1535 * R P C _ _ S O C K E T _ G E T _ P E E R E I D 1536 * 1537 * Get UNIX domain socket peer credentials 1538 */ 1539 1540INTERNAL rpc_socket_error_t rpc__bsd_socket_getpeereid 1541( 1542 rpc_socket_t sock, 1543 uid_t *euid, 1544 gid_t *egid 1545) 1546{ 1547 rpc_socket_error_t serr = RPC_C_SOCKET_ENOTSUP; 1548 rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer; 1549 1550#if HAVE_GETPEEREID 1551 1552 RPC_SOCKET_DISABLE_CANCEL; 1553 serr = ((getpeereid(lrpc->fd, euid, egid) == -1) ? errno 1554 : RPC_C_SOCKET_OK); 1555 RPC_SOCKET_RESTORE_CANCEL; 1556 1557 if (serr != RPC_C_SOCKET_OK) 1558 { 1559 RPC_DBG_GPRINTF(("(rpc__bsd_socket_getpeereid) error=%d\n", serr)); 1560 } 1561 1562#elif defined(SO_PEERCRED) 1563 struct ucred peercred = {0}; 1564 socklen_t peercredlen = sizeof(peercred); 1565 1566 RPC_SOCKET_DISABLE_CANCEL; 1567 serr = ((getsockopt(lrpc->fd, SOL_SOCKET, SO_PEERCRED, 1568 &peercred, &peercredlen) == -1) ? errno : RPC_C_SOCKET_OK); 1569 RPC_SOCKET_RESTORE_CANCEL; 1570 if (serr == RPC_C_SOCKET_OK) 1571 { 1572 *euid = peercred.uid; 1573 *egid = peercred.gid; 1574 } 1575 else 1576 { 1577 RPC_DBG_GPRINTF(("(rpc__bsd_socket_getpeereid) error=%d\n", serr)); 1578 } 1579#else 1580 serr = rpc__bsd_socket_recvpeereid(sock, euid, egid); 1581#endif 1582 1583 return serr; 1584} 1585 1586#if !defined(SO_PEERCRED) && !defined(HAVE_GETPEEREID) 1587 1588INTERNAL rpc_socket_error_t rpc__bsd_socket_sendpeereid 1589( 1590 rpc_socket_t sock, 1591 rpc_addr_p_t addr 1592) 1593{ 1594 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 1595 rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer; 1596 struct sockaddr_un *endpoint_addr = NULL; 1597 struct stat endpoint_stat = {0}; 1598 uid_t ep_uid = -1; 1599 int pipefd[2] = {-1, -1}; 1600 char empty_buf[] = {'\0'}; 1601 rpc_socket_iovec_t iovec = {0}; 1602 union 1603 { 1604 /* Using union ensures correct alignment on some platforms */ 1605 struct cmsghdr cm; 1606 char buf[CMSG_SPACE(sizeof(pipefd[0]))]; 1607 } cm_un; 1608 struct msghdr msg = {0}; 1609 struct cmsghdr *cmsg = NULL; 1610 int bytes_sent = 0; 1611 1612 endpoint_addr = (struct sockaddr_un *)(&addr->sa); 1613 1614 if (stat(endpoint_addr->sun_path, &endpoint_stat)) 1615 { 1616 serr = errno; 1617 goto error; 1618 } 1619 1620 ep_uid = endpoint_stat.st_uid; 1621 if (ep_uid == 0 || ep_uid == getuid()) 1622 { 1623 if (pipe(pipefd) != 0) 1624 { 1625 serr = errno; 1626 goto error; 1627 } 1628 } 1629 1630 iovec.iov_base = &empty_buf; 1631 iovec.iov_len = sizeof(empty_buf); 1632 1633 msg.msg_iov = &iovec; 1634 msg.msg_iovlen = 1; 1635 msg.msg_control = cm_un.buf; 1636 msg.msg_controllen = sizeof(cm_un.buf); 1637 msg.msg_flags = 0; 1638 1639 memset(&cm_un, 0, sizeof(cm_un)); 1640 1641 cmsg = CMSG_FIRSTHDR(&msg); 1642 cmsg->cmsg_level = SOL_SOCKET; 1643 cmsg->cmsg_type = SCM_RIGHTS; 1644 cmsg->cmsg_len = CMSG_LEN(sizeof(pipefd[0])); 1645 1646 memcpy(CMSG_DATA(cmsg), &pipefd[0], sizeof(pipefd[0])); 1647 1648 RPC_SOCKET_DISABLE_CANCEL; 1649 bytes_sent = sendmsg(lrpc->fd, &msg, 0); 1650 RPC_SOCKET_RESTORE_CANCEL; 1651 if (bytes_sent == -1) 1652 { 1653 serr = errno; 1654 goto error; 1655 } 1656 1657cleanup: 1658 1659 if (pipefd[0] != -1) 1660 { 1661 close(pipefd[0]); 1662 } 1663 1664 if (pipefd[1] != -1) 1665 { 1666 close(pipefd[1]); 1667 } 1668 1669 return serr; 1670 1671error: 1672 1673 goto cleanup; 1674} 1675 1676INTERNAL rpc_socket_error_t rpc__bsd_socket_recvpeereid 1677( 1678 rpc_socket_t sock, 1679 uid_t *euid, 1680 gid_t *egid 1681) 1682{ 1683 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 1684 rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer; 1685 int fd = -1; 1686 int bytes_rcvd = 0; 1687 struct stat pipe_stat = {0}; 1688 char empty_buf[] = {'\0'}; 1689 rpc_socket_iovec_t iovec = {0}; 1690 union 1691 { 1692 /* Using union ensures correct alignment on some platforms */ 1693 struct cmsghdr cm; 1694 char buf[CMSG_SPACE(sizeof(fd))]; 1695 } cm_un; 1696 struct cmsghdr *cmsg = NULL; 1697 struct msghdr msg = {0}; 1698 1699 iovec.iov_base = &empty_buf; 1700 iovec.iov_len = sizeof(empty_buf); 1701 1702 memset(&cm_un, 0, sizeof(cm_un)); 1703 1704 msg.msg_iov = &iovec; 1705 msg.msg_iovlen = 1; 1706 msg.msg_control = cm_un.buf; 1707 msg.msg_controllen = sizeof(cm_un.buf); 1708 msg.msg_flags = 0; 1709 1710 RPC_SOCKET_DISABLE_CANCEL; 1711 bytes_rcvd = recvmsg(lrpc->fd, &msg, 0); 1712 RPC_SOCKET_RESTORE_CANCEL; 1713 if (bytes_rcvd == -1) 1714 { 1715 serr = errno; 1716 goto error; 1717 } 1718 1719 if (msg.msg_controllen == 0 || 1720 msg.msg_controllen > sizeof(cm_un)) 1721 { 1722 serr = RPC_C_SOCKET_EACCESS; 1723 goto error; 1724 } 1725 1726 cmsg = CMSG_FIRSTHDR(&msg); 1727 if (!cmsg || 1728 !(cmsg->cmsg_type == SCM_RIGHTS) || 1729 cmsg->cmsg_len - CMSG_ALIGN(sizeof(*cmsg)) != sizeof(fd)) 1730 { 1731 serr = RPC_C_SOCKET_EACCESS; 1732 goto error; 1733 } 1734 1735 memcpy(&fd, CMSG_DATA(cmsg), sizeof(fd)); 1736 1737 if (fstat(fd, &pipe_stat)) 1738 { 1739 serr = errno; 1740 goto error; 1741 } 1742 1743 if (!S_ISFIFO(pipe_stat.st_mode) || 1744 (pipe_stat.st_mode & (S_IRWXO | S_IRWXG)) != 0) 1745 { 1746 serr = RPC_C_SOCKET_EACCESS; 1747 goto error; 1748 } 1749 1750 *euid = pipe_stat.st_uid; 1751 *egid = pipe_stat.st_gid; 1752 1753cleanup: 1754 1755 if (fd > 0) 1756 { 1757 close(fd); 1758 } 1759 1760 return serr; 1761 1762error: 1763 1764 *euid = -1; 1765 *egid = -1; 1766 1767 goto cleanup; 1768} 1769 1770#endif 1771 1772INTERNAL 1773int rpc__bsd_socket_get_select_desc( 1774 rpc_socket_t sock 1775 ) 1776{ 1777 rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer; 1778 1779 return lrpc->fd; 1780} 1781 1782INTERNAL 1783rpc_socket_error_t 1784rpc__bsd_socket_enum_ifaces( 1785 rpc_socket_t sock, 1786 rpc_socket_enum_iface_fn_p_t efun, 1787 rpc_addr_vector_p_t *rpc_addr_vec, 1788 rpc_addr_vector_p_t *netmask_addr_vec, 1789 rpc_addr_vector_p_t *broadcast_addr_vec 1790) 1791{ 1792 rpc_ip_addr_p_t ip_addr = NULL; 1793 rpc_ip_addr_p_t netmask_addr = NULL; 1794 rpc_ip_addr_p_t broadcast_addr = NULL; 1795 int n_ifs; 1796 union 1797 { 1798 unsigned char buf[1024]; 1799 struct ifreq req; 1800 } reqbuf; 1801 struct ifconf ifc; 1802 struct ifreq *ifr, *last_ifr; 1803 struct ifreq ifreq; 1804 short if_flags; 1805 struct sockaddr if_addr; 1806 unsigned int i; 1807#ifdef _SOCKADDR_LEN 1808 int prev_size; 1809#else 1810 const int prev_size = sizeof(struct ifreq) ; 1811#endif 1812 rpc_socket_error_t err = 0; 1813 rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer; 1814 1815 /* 1816 * Get the list of network interfaces. 1817 */ 1818 ifc.ifc_len = sizeof (reqbuf.buf); 1819 ifc.ifc_buf = (caddr_t) reqbuf.buf; 1820 1821ifconf_again: 1822 if (ioctl (lrpc->fd, SIOCGIFCONF, (caddr_t) &ifc) < 0) 1823 { 1824 if (errno == EINTR) 1825 { 1826 goto ifconf_again; 1827 } 1828 err = errno; /* !!! */ 1829 goto done; 1830 } 1831 1832 /* 1833 * Figure out how many interfaces there must be and allocate an 1834 * RPC address vector with the appropriate number of elements. 1835 * (We may ask for a few too many in case some of the interfaces 1836 * are uninteresting.) 1837 */ 1838 n_ifs = ifc.ifc_len / sizeof (struct ifreq); 1839 RPC_DBG_PRINTF(rpc_e_dbg_general, 10, 1840 ("%lu bytes of ifreqs, ifreq is %lu bytes\n", 1841 (unsigned long)ifc.ifc_len, 1842 (unsigned long)sizeof(struct ifreq))); 1843 1844#ifdef MAX_DEBUG 1845 if (RPC_DBG2(rpc_e_dbg_general, 15)) 1846 { 1847 int i; 1848 char msgbuf[128]; 1849 1850 for (i=0; i<ifc.ifc_len; i++) { 1851 if ((i % 32) == 0) { 1852 if (i != 0) 1853 RPC_DBG_PRINTF(rpc_e_dbg_general, 15, ("%s\n",msgbuf)); 1854 sprintf(msgbuf, "%4x: ", i); 1855 } 1856 sprintf(msgbuf, "%s%02x ", msgbuf, reqbuf.buf[i]); 1857 } 1858 if (i != 0) 1859 RPC_DBG_PRINTF(rpc_e_dbg_general, 15, ("%s\n",msgbuf)); 1860 } 1861#endif 1862 1863 if (rpc_addr_vec != NULL) 1864 { 1865 RPC_MEM_ALLOC ( 1866 *rpc_addr_vec, 1867 rpc_addr_vector_p_t, 1868 (sizeof **rpc_addr_vec) + ((n_ifs - 1) * (sizeof (rpc_addr_p_t))), 1869 RPC_C_MEM_RPC_ADDR_VEC, 1870 RPC_C_MEM_WAITOK); 1871 1872 if (*rpc_addr_vec == NULL) 1873 { 1874 err = ENOMEM; 1875 goto done; 1876 } 1877 } 1878 1879 if (netmask_addr_vec != NULL) 1880 { 1881 RPC_MEM_ALLOC ( 1882 *netmask_addr_vec, 1883 rpc_addr_vector_p_t, 1884 (sizeof **netmask_addr_vec) + ((n_ifs - 1) * (sizeof (rpc_addr_p_t))), 1885 RPC_C_MEM_RPC_ADDR_VEC, 1886 RPC_C_MEM_WAITOK); 1887 1888 if (*netmask_addr_vec == NULL) 1889 { 1890 err = ENOMEM; 1891 RPC_MEM_FREE (*netmask_addr_vec, RPC_C_MEM_RPC_ADDR_VEC); 1892 goto done; 1893 } 1894 1895 (*netmask_addr_vec)->len = 0; 1896 } 1897 1898 if (broadcast_addr_vec != NULL) 1899 { 1900 RPC_MEM_ALLOC ( 1901 *broadcast_addr_vec, 1902 rpc_addr_vector_p_t, 1903 (sizeof **broadcast_addr_vec) + ((n_ifs - 1) * (sizeof (rpc_addr_p_t))), 1904 RPC_C_MEM_RPC_ADDR_VEC, 1905 RPC_C_MEM_WAITOK); 1906 1907 if (*broadcast_addr_vec == NULL) 1908 { 1909 err = ENOMEM; 1910 RPC_MEM_FREE (*broadcast_addr_vec, RPC_C_MEM_RPC_ADDR_VEC); 1911 goto done; 1912 } 1913 1914 (*broadcast_addr_vec)->len = 0; 1915 } 1916 1917 /* 1918 * Go through the interfaces and get the info associated with them. 1919 */ 1920 assert(rpc_addr_vec != NULL); 1921 (*rpc_addr_vec)->len = 0; 1922 last_ifr = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len); 1923 1924 for (i=0, ifr = ifc.ifc_req; ifr < last_ifr ; 1925 i++, ifr = (struct ifreq *)(( (char *) ifr ) + prev_size)) 1926 { 1927#ifdef _SOCKADDR_LEN 1928 prev_size = sizeof (struct ifreq) - sizeof(struct sockaddr) + ifr->ifr_addr.sa_len ; 1929#endif 1930 RPC_DBG_PRINTF(rpc_e_dbg_general, 10, ("interface %d: %s\n", 1931 i, ifr->ifr_name)); 1932 /* 1933 * Get the interface's flags. If the flags say that the interface 1934 * is not up or is the loopback interface, skip it. Do the 1935 * SIOCGIFFLAGS on a copy of the ifr so we don't lose the original 1936 * contents of the ifr. (ifr's are unions that hold only one 1937 * of the interesting interface attributes [address, flags, etc.] 1938 * at a time.) 1939 */ 1940 memcpy(&ifreq, ifr, sizeof(ifreq)); 1941ifflags_again: 1942 if (ioctl(lrpc->fd, SIOCGIFFLAGS, &ifreq) < 0) 1943 { 1944 RPC_DBG_PRINTF(rpc_e_dbg_general, 10, 1945 ("SIOCGIFFLAGS returned errno %d\n", errno)); 1946 if (errno == EINTR) 1947 { 1948 goto ifflags_again; 1949 } 1950 continue; 1951 } 1952 if_flags = ifreq.ifr_flags; /* Copy out the flags */ 1953 RPC_DBG_PRINTF(rpc_e_dbg_general, 10, ("flags are %x\n", if_flags)); 1954 1955 /* 1956 * Ignore interfaces which are not 'up'. 1957 */ 1958 if ((if_flags & IFF_UP) == 0) 1959 1960 continue; 1961 1962#ifndef USE_LOOPBACK 1963 /* 1964 * Ignore the loopback interface 1965 */ 1966 1967 if (if_flags & IFF_LOOPBACK) continue; 1968#endif 1969 /* 1970 * Ignore Point-to-Point interfaces (i.e. SLIP/PPP ) 1971 * *** NOTE: We need an Environment Variable Evaluation at 1972 * some point so we can selectively allow RPC servers to 1973 * some up with/without SLIP/PPP bindings. For Dynamic PPP/SLIP 1974 * interfaces, this creates problems for now. 1975 */ 1976 1977 if (if_flags & IFF_POINTOPOINT) continue; 1978 1979 /* 1980 * Get the addressing stuff for this interface. 1981 */ 1982 1983#ifdef NO_SIOCGIFADDR 1984 1985 /* 1986 * Note that some systems do not return the address for the 1987 * interface given. However the ifr array elts contained in 1988 * the ifc block returned from the SIOCGIFCONF ioctl above already 1989 * contains the correct addresses. So these systems should define 1990 * NO_SIOCGIFADDR in their platform specific include file. 1991 */ 1992 if_addr = ifr->ifr_addr; 1993 1994#else 1995 1996 /* 1997 * Do the SIOCGIFADDR on a copy of the ifr. See above. 1998 */ 1999 memcpy(&ifreq, ifr, sizeof(ifreq)); 2000 ifaddr_again: 2001 if (ioctl(lrpc->fd, SIOCGIFADDR, &ifreq) < 0) 2002 { 2003 /* 2004 * UP but no ip address, skip it 2005 */ 2006 if (errno == EADDRNOTAVAIL) continue; 2007 2008 RPC_DBG_PRINTF(rpc_e_dbg_general, 10, 2009 ("SIOCGIFADDR returned errno %d\n", errno)); 2010 if (errno == EINTR) 2011 { 2012 goto ifaddr_again; 2013 } 2014 2015 err = errno; 2016 goto FREE_IT; 2017 } 2018 2019 memcpy (&if_addr, &ifr->ifr_addr, sizeof(struct sockaddr)); 2020 2021#endif /* NO_SIOCGIFADDR */ 2022 2023 /* 2024 * If this isn't an Internet-family address, ignore it. 2025 */ 2026 if (if_addr.sa_family != AF_INET) 2027 { 2028 RPC_DBG_PRINTF(rpc_e_dbg_general, 10, ("AF %d not INET\n", 2029 if_addr.sa_family)); 2030 continue; 2031 } 2032 2033 if (rpc_addr_vec != NULL) 2034 { 2035 /* 2036 * Allocate and fill in an IP RPC address for this interface. 2037 */ 2038 RPC_MEM_ALLOC ( 2039 ip_addr, 2040 rpc_ip_addr_p_t, 2041 sizeof (rpc_ip_addr_t), 2042 RPC_C_MEM_RPC_ADDR, 2043 RPC_C_MEM_WAITOK); 2044 2045 if (ip_addr == NULL) 2046 { 2047 err = ENOMEM; 2048 goto FREE_IT; 2049 } 2050 2051 ip_addr->rpc_protseq_id = sock->pseq_id; 2052 ip_addr->len = sizeof (struct sockaddr_in); 2053 2054 memcpy (&ip_addr->sa, &if_addr, sizeof(struct sockaddr_in)); 2055 } 2056 else 2057 { 2058 ip_addr = NULL; 2059 } 2060 2061 if (netmask_addr_vec != NULL && (if_flags & IFF_LOOPBACK) == 0) 2062 { 2063 memcpy(&ifreq, ifr, sizeof(ifreq)); 2064 2065 while (ioctl(lrpc->fd, SIOCGIFNETMASK, &ifreq) == -1) 2066 { 2067 if (errno != EINTR) 2068 { 2069 err = errno; 2070 goto FREE_IT; 2071 } 2072 } 2073 2074 RPC_MEM_ALLOC ( 2075 netmask_addr, 2076 rpc_ip_addr_p_t, 2077 sizeof (rpc_ip_addr_t), 2078 RPC_C_MEM_RPC_ADDR, 2079 RPC_C_MEM_WAITOK); 2080 2081 if (netmask_addr == NULL) 2082 { 2083 err = ENOMEM; 2084 goto FREE_IT; 2085 } 2086 2087 netmask_addr->rpc_protseq_id = sock->pseq_id; 2088 netmask_addr->len = sizeof (struct sockaddr_in); 2089 memcpy(&netmask_addr->sa, &ifreq.ifr_addr, sizeof(struct sockaddr_in)); 2090 } 2091 else 2092 { 2093 netmask_addr = NULL; 2094 } 2095 2096 if (broadcast_addr_vec != NULL && (if_flags & IFF_BROADCAST)) 2097 { 2098 memcpy(&ifreq, ifr, sizeof(ifreq)); 2099 2100 while (ioctl(lrpc->fd, SIOCGIFBRDADDR, &ifreq) == -1) 2101 { 2102 if (errno != EINTR) 2103 { 2104 err = errno; 2105 goto FREE_IT; 2106 } 2107 } 2108 2109 RPC_MEM_ALLOC ( 2110 broadcast_addr, 2111 rpc_ip_addr_p_t, 2112 sizeof (rpc_ip_addr_t), 2113 RPC_C_MEM_RPC_ADDR, 2114 RPC_C_MEM_WAITOK); 2115 2116 if (broadcast_addr == NULL) 2117 { 2118 err = ENOMEM; 2119 goto FREE_IT; 2120 } 2121 2122 broadcast_addr->rpc_protseq_id = sock->pseq_id; 2123 broadcast_addr->len = sizeof (struct sockaddr_in); 2124 memcpy(&broadcast_addr->sa, &ifreq.ifr_broadaddr, sizeof(struct sockaddr_in)); 2125 } 2126 else 2127 { 2128 broadcast_addr = NULL; 2129 } 2130 2131 /* 2132 * Call out to do any final filtering and get the desired IP address 2133 * for this interface. If the callout function returns false, we 2134 * forget about this interface. 2135 */ 2136 if ((*efun) (sock, (rpc_addr_p_t) ip_addr, (rpc_addr_p_t) netmask_addr, (rpc_addr_p_t) broadcast_addr) == false) 2137 { 2138 if (ip_addr != NULL) 2139 { 2140 RPC_MEM_FREE (ip_addr, RPC_C_MEM_RPC_ADDR); 2141 ip_addr = NULL; 2142 } 2143 if (netmask_addr != NULL) 2144 { 2145 RPC_MEM_FREE (netmask_addr, RPC_C_MEM_RPC_ADDR); 2146 netmask_addr = NULL; 2147 } 2148 if (broadcast_addr != NULL) 2149 { 2150 RPC_MEM_FREE (broadcast_addr, RPC_C_MEM_RPC_ADDR); 2151 broadcast_addr = NULL; 2152 } 2153 continue; 2154 } 2155 2156 if (rpc_addr_vec != NULL && ip_addr != NULL) 2157 { 2158 (*rpc_addr_vec)->addrs[(*rpc_addr_vec)->len++] 2159 = (rpc_addr_p_t) ip_addr; 2160 ip_addr = NULL; 2161 } 2162 if (netmask_addr_vec != NULL && netmask_addr != NULL) 2163 { 2164 (*netmask_addr_vec)->addrs[(*netmask_addr_vec)->len++] 2165 = (rpc_addr_p_t) netmask_addr; 2166 netmask_addr = NULL; 2167 } 2168 if (broadcast_addr_vec != NULL && broadcast_addr != NULL) 2169 { 2170 (*broadcast_addr_vec)->addrs[(*broadcast_addr_vec)->len++] 2171 = (rpc_addr_p_t) broadcast_addr; 2172 broadcast_addr = NULL; 2173 } 2174 } 2175 2176 if ((*rpc_addr_vec)->len == 0) 2177 { 2178 err = EINVAL; /* !!! */ 2179 goto FREE_IT; 2180 } 2181 2182 err = RPC_C_SOCKET_OK; 2183done: 2184 2185 return err; 2186 2187FREE_IT: 2188 2189 if (ip_addr != NULL) 2190 { 2191 RPC_MEM_FREE (ip_addr, RPC_C_MEM_RPC_ADDR); 2192 } 2193 if (netmask_addr != NULL) 2194 { 2195 RPC_MEM_FREE (netmask_addr, RPC_C_MEM_RPC_ADDR); 2196 } 2197 if (broadcast_addr != NULL) 2198 { 2199 RPC_MEM_FREE (broadcast_addr, RPC_C_MEM_RPC_ADDR); 2200 } 2201 2202 if (rpc_addr_vec != NULL && *rpc_addr_vec != NULL) 2203 { 2204 for (i = 0; i < (*rpc_addr_vec)->len; i++) 2205 { 2206 RPC_MEM_FREE ((*rpc_addr_vec)->addrs[i], RPC_C_MEM_RPC_ADDR); 2207 } 2208 RPC_MEM_FREE (*rpc_addr_vec, RPC_C_MEM_RPC_ADDR_VEC); 2209 *rpc_addr_vec = NULL; 2210 } 2211 if (netmask_addr_vec != NULL && *netmask_addr_vec != NULL) 2212 { 2213 for (i = 0; i < (*netmask_addr_vec)->len; i++) 2214 { 2215 RPC_MEM_FREE ((*netmask_addr_vec)->addrs[i], RPC_C_MEM_RPC_ADDR); 2216 } 2217 RPC_MEM_FREE (*netmask_addr_vec, RPC_C_MEM_RPC_ADDR_VEC); 2218 *netmask_addr_vec = NULL; 2219 } 2220 if (broadcast_addr_vec != NULL && *broadcast_addr_vec != NULL) 2221 { 2222 assert(broadcast_addr_vec != NULL); 2223 for (i = 0; i < (*broadcast_addr_vec)->len; i++) 2224 { 2225 RPC_MEM_FREE ((*broadcast_addr_vec)->addrs[i], RPC_C_MEM_RPC_ADDR); 2226 } 2227 RPC_MEM_FREE (*broadcast_addr_vec, RPC_C_MEM_RPC_ADDR_VEC); 2228 *broadcast_addr_vec = NULL; 2229 } 2230 2231 goto done; 2232} 2233 2234INTERNAL 2235rpc_socket_error_t 2236rpc__bsd_socket_inq_transport_info( 2237 rpc_socket_t sock ATTRIBUTE_UNUSED, 2238 rpc_transport_info_handle_t* info 2239 ) 2240{ 2241 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 2242 rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer; 2243 rpc_bsd_transport_info_p_t lrpc_info = NULL; 2244 2245 lrpc_info = calloc(1, sizeof(*lrpc_info)); 2246 2247 if (!lrpc_info) 2248 { 2249 serr = ENOMEM; 2250 goto error; 2251 } 2252 2253 lrpc_info->peer_uid = lrpc->info.peer_uid; 2254 lrpc_info->peer_gid = lrpc->info.peer_gid; 2255 2256 *info = (rpc_transport_info_handle_t) lrpc_info; 2257 2258error: 2259 if (serr) 2260 { 2261 *info = NULL; 2262 2263 if (lrpc_info) 2264 { 2265 rpc_lrpc_transport_info_free((rpc_transport_info_handle_t) lrpc_info); 2266 } 2267 } 2268 2269 return serr; 2270} 2271 2272void 2273rpc_lrpc_transport_info_free( 2274 rpc_transport_info_handle_t info 2275 ) 2276{ 2277 if (info) 2278 { 2279 free(info); 2280 } 2281} 2282 2283void 2284rpc_lrpc_transport_info_inq_peer_eid( 2285 rpc_transport_info_handle_t info, 2286 unsigned32 *uid, 2287 unsigned32 *gid 2288 ) 2289{ 2290 rpc_bsd_transport_info_p_t lrpc_info = (rpc_bsd_transport_info_p_t) info; 2291 2292 if (uid) 2293 { 2294 *uid = lrpc_info->peer_uid; 2295 } 2296 2297 if (gid) 2298 { 2299 *gid = lrpc_info->peer_gid; 2300 } 2301} 2302 2303INTERNAL 2304boolean 2305rpc__bsd_socket_transport_info_equal( 2306 rpc_transport_info_handle_t info1, 2307 rpc_transport_info_handle_t info2 2308 ) 2309{ 2310 rpc_bsd_transport_info_p_t bsd_info1 = (rpc_bsd_transport_info_p_t) info1; 2311 rpc_bsd_transport_info_p_t bsd_info2 = (rpc_bsd_transport_info_p_t) info2; 2312 2313 if ((bsd_info1 != NULL) && (bsd_info2 != NULL)) 2314 { 2315 return 2316 (bsd_info1->peer_uid == bsd_info2->peer_uid && 2317 bsd_info1->peer_gid == bsd_info2->peer_gid); 2318 } else if (bsd_info1 == bsd_info2){ 2319 return true; 2320 } 2321 2322 rpc_bsd_transport_info_p_t tmp = bsd_info1 != NULL ? bsd_info1: bsd_info2; 2323 return (tmp->peer_uid == getuid() && tmp->peer_gid == getgid()); 2324} 2325 2326INTERNAL 2327rpc_socket_error_t 2328rpc__bsd_socket_transport_inq_access_token( 2329 rpc_transport_info_handle_t info ATTRIBUTE_UNUSED, 2330 rpc_access_token_p_t* token ATTRIBUTE_UNUSED 2331 ) 2332{ 2333#if HAVE_LIKEWISE_LWMAPSECURITY 2334 rpc_bsd_transport_info_p_t lrpc_info = (rpc_bsd_transport_info_p_t) info; 2335 NTSTATUS status = STATUS_SUCCESS; 2336 PLW_MAP_SECURITY_CONTEXT context = NULL; 2337 2338 status = LwMapSecurityCreateContext(&context); 2339 if (status) goto error; 2340 2341 status = LwMapSecurityCreateAccessTokenFromUidGid( 2342 context, 2343 token, 2344 lrpc_info->peer_uid, 2345 lrpc_info->peer_gid); 2346 if (status) goto error; 2347 2348error: 2349 2350 LwMapSecurityFreeContext(&context); 2351 2352 return LwNtStatusToErrno(status); 2353#else 2354 return RPC_C_SOCKET_ENOTSUP; 2355#endif 2356} 2357 2358PRIVATE const rpc_socket_vtbl_t rpc_g_bsd_socket_vtbl = 2359{ 2360 .socket_duplicate = rpc__bsd_socket_duplicate, 2361 .socket_construct = rpc__bsd_socket_construct, 2362 .socket_destruct = rpc__bsd_socket_destruct, 2363 .socket_bind = rpc__bsd_socket_bind, 2364 .socket_connect = rpc__bsd_socket_connect, 2365 .socket_accept = rpc__bsd_socket_accept, 2366 .socket_listen = rpc__bsd_socket_listen, 2367 .socket_sendmsg = rpc__bsd_socket_sendmsg, 2368 .socket_recvfrom = rpc__bsd_socket_recvfrom, 2369 .socket_recvmsg = rpc__bsd_socket_recvmsg, 2370 .socket_inq_endpoint = rpc__bsd_socket_inq_endpoint, 2371 .socket_set_broadcast = rpc__bsd_socket_set_broadcast, 2372 .socket_set_bufs = rpc__bsd_socket_set_bufs, 2373 .socket_set_nbio = rpc__bsd_socket_set_nbio, 2374 .socket_set_close_on_exec = rpc__bsd_socket_set_close_on_exec, 2375 .socket_getpeername = rpc__bsd_socket_getpeername, 2376 .socket_get_if_id = rpc__bsd_socket_get_if_id, 2377 .socket_set_keepalive = rpc__bsd_socket_set_keepalive, 2378 .socket_nowriteblock_wait = rpc__bsd_socket_nowriteblock_wait, 2379 .socket_set_rcvtimeo = rpc__bsd_socket_set_rcvtimeo, 2380 .socket_getpeereid = rpc__bsd_socket_getpeereid, 2381 .socket_get_select_desc = rpc__bsd_socket_get_select_desc, 2382 .socket_enum_ifaces = rpc__bsd_socket_enum_ifaces, 2383 .socket_inq_transport_info = rpc__bsd_socket_inq_transport_info, 2384 .transport_info_free = rpc_lrpc_transport_info_free, 2385 .transport_info_equal = rpc__bsd_socket_transport_info_equal, 2386 .transport_inq_access_token = rpc__bsd_socket_transport_inq_access_token 2387}; 2388