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** ipnaf_bsd 82** 83** FACILITY: 84** 85** Remote Procedure Call (RPC) 86** 87** ABSTRACT: 88** 89** This module contains routines specific to the Internet Protocol, 90** the Internet Network Address Family extension service, and the 91** Berkeley Unix system. 92** 93** 94*/ 95 96#include <commonp.h> 97#include <com.h> 98#include <comnaf.h> 99#include <comsoc.h> 100#include <ipnaf.h> 101 102#include <net/if.h> 103#include <sys/ioctl.h> 104 105 106/*********************************************************************** 107 * 108 * Internal prototypes and typedefs. 109 */ 110 111typedef boolean (*enumerate_fn_p_t) (( 112 int /* in */ /*desc*/, 113 struct ifreq /* in */ * /*ifr*/, 114 unsigned32 /* in */ /*if_flags*/, 115 struct sockaddr /* in */ * /*if_addr*/, 116 rpc_ip_addr_p_t /* out */ /*ip_addr*/, 117 rpc_ip_addr_p_t /* out */ /*netmask_addr*/ 118 ); 119 120INTERNAL void enumerate_interfaces ( 121 rpc_protseq_id_t /*protseq_id*/, 122 rpc_socket_t /*desc*/, 123 enumerate_fn_p_t /*efun*/, 124 rpc_addr_vector_p_t * /*rpc_addr_vec*/, 125 rpc_addr_vector_p_t * /*netmask_addr_vec*/, 126 unsigned32 * /*st*/ 127 ); 128 129INTERNAL boolean get_addr ( 130 int /*desc*/, 131 struct ifreq * /*ifr*/, 132 unsigned32 /*if_flags*/, 133 struct sockaddr * /*if_addr*/, 134 rpc_ip_addr_p_t /*ip_addr*/, 135 rpc_ip_addr_p_t /*netmask_addr*/ 136 ); 137 138INTERNAL boolean get_broadcast_addr ( 139 int /*desc*/, 140 struct ifreq * /*ifr*/, 141 unsigned32 /*if_flags*/, 142 struct sockaddr * /*if_addr*/, 143 rpc_ip_addr_p_t /*ip_addr*/, 144 rpc_ip_addr_p_t /*netmask_addr*/ 145 ); 146 147#ifndef NO_SPRINTF 148# define RPC__IP_NETWORK_SPRINTF sprintf 149#else 150# define RPC__IP_NETWORK_SPRINTF rpc__ip_network_sprintf 151#endif 152 153typedef struct 154{ 155 unsigned32 num_elt; 156 struct 157 { 158 unsigned32 addr; 159 unsigned32 netmask; 160 } elt[1]; 161} rpc_ip_s_addr_vector_t, *rpc_ip_s_addr_vector_p_t; 162 163INTERNAL rpc_ip_s_addr_vector_p_t local_ip_addr_vec = NULL; 164 165/* 166**++ 167** 168** ROUTINE NAME: enumerate_interfaces 169** 170** SCOPE: INTERNAL - declared locally 171** 172** DESCRIPTION: 173** 174** Return a vector of IP RPC addresses. Note that this function is 175** shared by both "rpc__ip_desc_inq_addr" and "rpc__ip_get_broadcast" 176** so that we have to have only one copy of all the gore (ioctl's) 177** associated with inquiring about network interfaces. This routine 178** filters out all network interface information that doesn't correspond 179** to up, non-loopback, IP-addressed network interfaces. The supplied 180** procedure pointer (efun) does the rest of the work. 181** 182** 183** INPUTS: 184** 185** protseq_id Protocol Sequence ID representing a particular 186** Network Address Family, its Transport Protocol, 187** and type. 188** 189** desc Descriptor, indicating a socket that has been 190** created on the local operating platform. 191** 192** efun Procedure pointer supplied to "do the rest of the work". 193** 194** INPUTS/OUTPUTS: none 195** 196** OUTPUTS: 197** 198** rpc_addr_vec Returned vector of RPC addresses. 199** 200** netmask_addr_vec Returned vector of netmask RPC addresses. 201** 202** status A value indicating the status of the routine. 203** 204** IMPLICIT INPUTS: none 205** 206** IMPLICIT OUTPUTS: none 207** 208** FUNCTION VALUE: none 209** 210** SIDE EFFECTS: none 211** 212**-- 213**/ 214 215#ifdef _SOCKADDR_LEN 216/* 217 * Note that in the world of BSD 4.4, the struct ifreq's returned 218 * from SIOCGIFCONF are *varying length*, but a minimum of 32 bytes. 219 * 220 * This has some interesting implications on how to parse the result 221 * from SIOCGIFCONF. 222 */ 223#endif 224 225INTERNAL void enumerate_interfaces 226( 227 rpc_protseq_id_t protseq_id, 228 rpc_socket_t desc, 229 enumerate_fn_p_t efun, 230 rpc_addr_vector_p_t *rpc_addr_vec, 231 rpc_addr_vector_p_t *netmask_addr_vec, 232 unsigned32 *status 233) 234{ 235 rpc_ip_addr_p_t ip_addr; 236 int n_ifs; 237 unsigned char buf[1024]; 238 struct ifconf ifc; 239 struct ifreq *ifr, *last_ifr; 240 struct ifreq ifreq; 241 short if_flags; 242 struct sockaddr if_addr; 243 int i; 244#ifdef _SOCKADDR_LEN 245 int prev_size; 246#else 247 const int prev_size = sizeof(struct ifreq) ; 248#endif 249 rpc_ip_addr_p_t netmask_addr = NULL; 250 251 CODING_ERROR (status); 252 253 /* 254 * Get the list of network interfaces. 255 */ 256 ifc.ifc_len = sizeof (buf); 257 ifc.ifc_buf = (caddr_t) buf; 258 259ifconf_again: 260 if (ioctl (desc, (int) SIOCGIFCONF, (caddr_t) &ifc) < 0) 261 { 262 if (errno == EINTR) 263 { 264 goto ifconf_again; 265 } 266 *status = -2; /* !!! */ 267 return; 268 } 269 270 /* 271 * Figure out how many interfaces there must be and allocate an 272 * RPC address vector with the appropriate number of elements. 273 * (We may ask for a few too many in case some of the interfaces 274 * are uninteresting.) 275 */ 276 n_ifs = ifc.ifc_len / sizeof (struct ifreq); 277 RPC_DBG_PRINTF(rpc_e_dbg_general, 10, 278 ("%d bytes of ifreqs, ifreq is %d bytes\n", ifc.ifc_len, sizeof(struct ifreq))); 279 280#ifdef MAX_DEBUG 281 if (RPC_DBG2(rpc_e_dbg_general, 15)) 282 { 283 int i; 284 char msgbuf[128]; 285 286 for (i=0; i<ifc.ifc_len; i++) { 287 if ((i % 32) == 0) { 288 if (i != 0) 289 RPC_DBG_PRINTF(rpc_e_dbg_general, 15, ("%s\n",msgbuf)); 290 sprintf(msgbuf, "%4x: ", i); 291 } 292 sprintf(msgbuf, "%s%02x ", msgbuf, buf[i]); 293 } 294 if (i != 0) 295 RPC_DBG_PRINTF(rpc_e_dbg_general, 15, ("%s\n",msgbuf)); 296 } 297#endif 298 299 RPC_MEM_ALLOC ( 300 *rpc_addr_vec, 301 rpc_addr_vector_p_t, 302 (sizeof **rpc_addr_vec) + ((n_ifs - 1) * (sizeof (rpc_addr_p_t))), 303 RPC_C_MEM_RPC_ADDR_VEC, 304 RPC_C_MEM_WAITOK); 305 306 if (*rpc_addr_vec == NULL) 307 { 308 *status = rpc_s_no_memory; 309 return; 310 } 311 if (netmask_addr_vec != NULL) 312 { 313 RPC_MEM_ALLOC ( 314 *netmask_addr_vec, 315 rpc_addr_vector_p_t, 316 (sizeof **netmask_addr_vec) + ((n_ifs - 1) * (sizeof (rpc_addr_p_t))), 317 RPC_C_MEM_RPC_ADDR_VEC, 318 RPC_C_MEM_WAITOK); 319 320 if (*netmask_addr_vec == NULL) 321 { 322 *status = rpc_s_no_memory; 323 RPC_MEM_FREE (*rpc_addr_vec, RPC_C_MEM_RPC_ADDR_VEC); 324 return; 325 } 326 327 (*netmask_addr_vec)->len = 0; 328 } 329 330 /* 331 * Go through the interfaces and get the info associated with them. 332 */ 333 (*rpc_addr_vec)->len = 0; 334 last_ifr = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len); 335 336 for (i=0, ifr = ifc.ifc_req; ifr < last_ifr ; 337 i++, ifr = (struct ifreq *)(( (char *) ifr ) + prev_size)) 338 { 339#ifdef _SOCKADDR_LEN 340 prev_size = sizeof (struct ifreq) - sizeof(struct sockaddr) + ifr->ifr_addr.sa_len ; 341#endif 342 RPC_DBG_PRINTF(rpc_e_dbg_general, 10, ("interface %d: %s\n", 343 i, ifr->ifr_name)); 344 /* 345 * Get the interface's flags. If the flags say that the interface 346 * is not up or is the loopback interface, skip it. Do the 347 * SIOCGIFFLAGS on a copy of the ifr so we don't lose the original 348 * contents of the ifr. (ifr's are unions that hold only one 349 * of the interesting interface attributes [address, flags, etc.] 350 * at a time.) 351 */ 352 memcpy(&ifreq, ifr, sizeof(ifreq)); 353ifflags_again: 354 if (ioctl(desc, SIOCGIFFLAGS, &ifreq) < 0) 355 { 356 RPC_DBG_PRINTF(rpc_e_dbg_general, 10, 357 ("SIOCGIFFLAGS returned errno %d\n", errno)); 358 if (errno == EINTR) 359 { 360 goto ifflags_again; 361 } 362 continue; 363 } 364 if_flags = ifreq.ifr_flags; /* Copy out the flags */ 365 RPC_DBG_PRINTF(rpc_e_dbg_general, 10, ("flags are %x\n", if_flags)); 366 367 /* 368 * Ignore interfaces which are not 'up'. 369 */ 370 if ((if_flags & IFF_UP) == 0) 371 continue; 372 373 /* 374 * Get the addressing stuff for this interface. 375 */ 376 377#ifdef NO_SIOCGIFADDR 378 379 /* 380 * Note that some systems do not return the address for the 381 * interface given. However the ifr array elts contained in 382 * the ifc block returned from the SIOCGIFCONF ioctl above already 383 * contains the correct addresses. So these systems should define 384 * NO_SIOCGIFADDR in their platform specific include file. 385 */ 386 if_addr = ifr->ifr_addr; 387 388#else 389 390 /* 391 * Do the SIOCGIFADDR on a copy of the ifr. See above. 392 */ 393 memcpy(&ifreq, ifr, sizeof(ifreq)); 394ifaddr_again: 395 if (ioctl(desc, SIOCGIFADDR, &ifreq) < 0) 396 { 397 RPC_DBG_PRINTF(rpc_e_dbg_general, 10, 398 ("SIOCGIFADDR returned errno %d\n", errno)); 399 if (errno == EINTR) 400 { 401 goto ifaddr_again; 402 } 403 404 *status = -4; 405 goto FREE_IT; 406 } 407 408 memcpy (&if_addr, &ifr->ifr_addr, sizeof(struct sockaddr)); 409 410#endif /* NO_SIOCGIFADDR */ 411 412 /* 413 * If this isn't an Internet-family address, ignore it. 414 */ 415 if (if_addr.sa_family != AF_INET) 416 { 417 RPC_DBG_PRINTF(rpc_e_dbg_general, 10, ("AF %d not INET\n", 418 if_addr.sa_family)); 419 continue; 420 } 421 422 /* 423 * Allocate and fill in an IP RPC address for this interface. 424 */ 425 RPC_MEM_ALLOC ( 426 ip_addr, 427 rpc_ip_addr_p_t, 428 sizeof (rpc_ip_addr_t), 429 RPC_C_MEM_RPC_ADDR, 430 RPC_C_MEM_WAITOK); 431 432 if (ip_addr == NULL) 433 { 434 *status = rpc_s_no_memory; 435 goto FREE_IT; 436 } 437 438 ip_addr->rpc_protseq_id = protseq_id; 439 ip_addr->len = sizeof (struct sockaddr_in); 440 if (netmask_addr_vec != NULL) 441 { 442 RPC_MEM_ALLOC ( 443 netmask_addr, 444 rpc_ip_addr_p_t, 445 sizeof (rpc_ip_addr_t), 446 RPC_C_MEM_RPC_ADDR, 447 RPC_C_MEM_WAITOK); 448 449 if (netmask_addr == NULL) 450 { 451 *status = rpc_s_no_memory; 452 RPC_MEM_FREE (ip_addr, RPC_C_MEM_RPC_ADDR); 453 goto FREE_IT; 454 } 455 456 netmask_addr->rpc_protseq_id = protseq_id; 457 netmask_addr->len = sizeof (struct sockaddr_in); 458 } 459 460 /* 461 * Call out to do any final filtering and get the desired IP address 462 * for this interface. If the callout function returns false, we 463 * forget about this interface. 464 */ 465 if ((*efun) (desc, ifr, if_flags, &if_addr, ip_addr, netmask_addr) == false) 466 { 467 RPC_MEM_FREE (ip_addr, RPC_C_MEM_RPC_ADDR); 468 if (netmask_addr != NULL) 469 RPC_MEM_FREE (netmask_addr, RPC_C_MEM_RPC_ADDR); 470 continue; 471 } 472 473 RPC_SOCKET_FIX_ADDRLEN(ip_addr); 474 (*rpc_addr_vec)->addrs[(*rpc_addr_vec)->len++] = (rpc_addr_p_t) ip_addr; 475 if (netmask_addr_vec != NULL && netmask_addr != NULL) 476 (*netmask_addr_vec)->addrs[(*netmask_addr_vec)->len++] 477 = (rpc_addr_p_t) netmask_addr; 478 } 479 480 if ((*rpc_addr_vec)->len == 0) 481 { 482 *status = -5; /* !!! */ 483 goto FREE_IT; 484 } 485 486 *status = rpc_s_ok; 487 return; 488 489FREE_IT: 490 491 for (i = 0; i < (*rpc_addr_vec)->len; i++) 492 { 493 RPC_MEM_FREE ((*rpc_addr_vec)->addrs[i], RPC_C_MEM_RPC_ADDR); 494 } 495 496 RPC_MEM_FREE (*rpc_addr_vec, RPC_C_MEM_RPC_ADDR_VEC); 497 if (netmask_addr_vec != NULL) 498 { 499 for (i = 0; i < (*netmask_addr_vec)->len; i++) 500 { 501 RPC_MEM_FREE ((*netmask_addr_vec)->addrs[i], RPC_C_MEM_RPC_ADDR); 502 } 503 RPC_MEM_FREE (*netmask_addr_vec, RPC_C_MEM_RPC_ADDR_VEC); 504 } 505} 506 507/* 508**++ 509** 510** ROUTINE NAME: get_addr 511** 512** SCOPE: INTERNAL - declared locally 513** 514** DESCRIPTION: 515** 516** This function is called from "rpc__ip_desc_inq_addr" via 517** "enumerate_interfaces". See comments in "enumerate_interfaces" for 518** details. 519** 520** 521** INPUTS: none 522** 523** desc Socket being used for ioctl's. 524** 525** ifr Structure describing the interface. 526** 527** INPUTS/OUTPUTS: none 528** 529** OUTPUTS: 530** 531** ip_addr 532** 533** netmask_addr netmask address 534** 535** IMPLICIT INPUTS: none 536** 537** IMPLICIT OUTPUTS: none 538** 539** FUNCTION VALUE: 540** 541** result true => we generated up an address for this interface 542** false => we didn't. 543** 544** SIDE EFFECTS: none 545** 546**-- 547**/ 548 549INTERNAL boolean get_addr 550( 551 int desc, 552 struct ifreq *ifr, 553 unsigned32 if_flags, 554 struct sockaddr *if_addr, 555 rpc_ip_addr_p_t ip_addr, 556 rpc_ip_addr_p_t netmask_addr 557) 558{ 559 struct ifreq ifreq; 560 561 if (netmask_addr == NULL) 562 { 563 if ((if_flags & IFF_LOOPBACK) != 0) 564 { 565 return (false); 566 } 567 568 memcpy (&ip_addr->sa, if_addr, sizeof(struct sockaddr_in)); 569 return (true); 570 } 571 else 572 { 573 memcpy (&ip_addr->sa, if_addr, sizeof(struct sockaddr_in)); 574 575 /* 576 * Inquire the interface's netmask address. 577 */ 578 ifreq = *ifr; 579 ifnetaddr_again: 580 if (ioctl(desc, (int) SIOCGIFNETMASK, &ifreq) == -1) 581 { 582 if (errno == EINTR) 583 { 584 goto ifnetaddr_again; 585 } 586 587 return (false); 588 } 589 590 memcpy (&netmask_addr->sa, &ifreq.ifr_addr, sizeof(struct sockaddr_in)); 591 return (true); 592 } 593} 594 595/* 596**++ 597** 598** ROUTINE NAME: rpc__ip_desc_inq_addr 599** 600** SCOPE: PRIVATE - declared in ipnaf.h 601** 602** DESCRIPTION: 603** 604** Receive a socket descriptor which is queried to obtain family, endpoint 605** and network address. If this information appears valid for an IP 606** address, space is allocated for an RPC address which is initialized 607** with the information obtained from the socket. The address indicating 608** the created RPC address is returned in rpc_addr. 609** 610** INPUTS: 611** 612** protseq_id Protocol Sequence ID representing a particular 613** Network Address Family, its Transport Protocol, 614** and type. 615** 616** desc Descriptor, indicating a socket that has been 617** created on the local operating platform. 618** 619** INPUTS/OUTPUTS: none 620** 621** OUTPUTS: 622** 623** rpc_addr_vec 624** 625** status A value indicating the status of the routine. 626** 627** rpc_s_ok The call was successful. 628** 629** rpc_s_no_memory Call to malloc failed to allocate memory. 630** 631** rpc_s_cant_inq_socket Attempt to get info about socket failed. 632** 633** Any of the RPC Protocol Service status codes. 634** 635** IMPLICIT INPUTS: none 636** 637** IMPLICIT OUTPUTS: none 638** 639** FUNCTION VALUE: none 640** 641** SIDE EFFECTS: none 642** 643**-- 644**/ 645 646PRIVATE void rpc__ip_desc_inq_addr 647( 648 rpc_protseq_id_t protseq_id, 649 rpc_socket_t desc, 650 rpc_addr_vector_p_t *rpc_addr_vec, 651 unsigned32 *status 652) 653{ 654 rpc_ip_addr_p_t ip_addr; 655 rpc_ip_addr_t loc_ip_addr; 656 unsigned16 i; 657 658 CODING_ERROR (status); 659 660 /* 661 * Do a "getsockname" into a local IP RPC address. If the network 662 * address part of the result is non-zero, then the socket must be 663 * bound to a particular IP address and we can just return a RPC 664 * address vector with that one address (and endpoint) in it. 665 * Otherwise, we have to enumerate over all the local network 666 * interfaces the local host has and construct an RPC address for 667 * each one of them. 668 */ 669 loc_ip_addr.len = sizeof (rpc_ip_addr_t); 670 RPC_SOCKET_FIX_ADDRLEN(&loc_ip_addr); 671 672 if (getsockname (desc, (struct sockaddr *)&loc_ip_addr.sa, (int *)&loc_ip_addr.len) < 0) 673 { 674 *status = -1; /* !!! */ 675 return; 676 } 677 678 RPC_SOCKET_FIX_ADDRLEN(&loc_ip_addr); 679 680 if (loc_ip_addr.sa.sin_addr.s_addr == 0) 681 { 682 enumerate_interfaces 683 (protseq_id, desc, get_addr, rpc_addr_vec, NULL, status); 684 685 if (*status != rpc_s_ok) 686 { 687 return; 688 } 689 for (i = 0; i < (*rpc_addr_vec)->len; i++) 690 { 691 ((rpc_ip_addr_p_t) (*rpc_addr_vec)->addrs[i])->sa.sin_port = loc_ip_addr.sa.sin_port; 692 } 693 } 694 else 695 { 696 RPC_MEM_ALLOC ( 697 ip_addr, 698 rpc_ip_addr_p_t, 699 sizeof (rpc_ip_addr_t), 700 RPC_C_MEM_RPC_ADDR, 701 RPC_C_MEM_WAITOK); 702 703 if (ip_addr == NULL) 704 { 705 *status = rpc_s_no_memory; 706 return; 707 } 708 709 RPC_MEM_ALLOC ( 710 *rpc_addr_vec, 711 rpc_addr_vector_p_t, 712 sizeof **rpc_addr_vec, 713 RPC_C_MEM_RPC_ADDR_VEC, 714 RPC_C_MEM_WAITOK); 715 716 if (*rpc_addr_vec == NULL) 717 { 718 RPC_MEM_FREE (ip_addr, RPC_C_MEM_RPC_ADDR); 719 *status = rpc_s_no_memory; 720 return; 721 } 722 723 ip_addr->rpc_protseq_id = protseq_id; 724 ip_addr->len = sizeof (struct sockaddr_in); 725 ip_addr->sa = loc_ip_addr.sa; 726 727 (*rpc_addr_vec)->len = 1; 728 (*rpc_addr_vec)->addrs[0] = (rpc_addr_p_t) ip_addr; 729 730 *status = rpc_s_ok; 731 return; 732 } 733} 734 735/* 736**++ 737** 738** ROUTINE NAME: get_broadcast_addr 739** 740** SCOPE: INTERNAL - declared locally 741** 742** DESCRIPTION: 743** 744** This function is called from "rpc__ip_get_broadcast" via 745** "enumerate_interfaces". See comments in "enumerate_interfaces" for 746** details. 747** 748** 749** INPUTS: none 750** 751** desc Socket being used for ioctl's. 752** 753** ifr Structure describing the interface. 754** 755** INPUTS/OUTPUTS: none 756** 757** OUTPUTS: 758** 759** ip_addr 760** 761** IMPLICIT INPUTS: none 762** 763** IMPLICIT OUTPUTS: none 764** 765** FUNCTION VALUE: none 766** 767** result true => we generated up an address for this interface 768** false => we didn't. 769** 770** SIDE EFFECTS: none 771** 772**-- 773**/ 774 775INTERNAL boolean get_broadcast_addr 776( 777 int desc, 778 struct ifreq *ifr, 779 unsigned32 if_flags, 780 struct sockaddr *if_addr, 781 rpc_ip_addr_p_t ip_addr, 782 rpc_ip_addr_p_t netmask_addr 783) 784{ 785 struct ifreq ifreq; 786 787 /* 788 * If the interface's flags say this isn't a broadcast interface, 789 * or isn't up, ignore it. 790 */ 791 if ((if_flags & IFF_BROADCAST) == 0 || (if_flags & IFF_UP) == 0) 792 { 793 return (false); 794 } 795 796#ifndef BROADCAST_NEEDS_LOOPBACK 797 /* 798 * #define BROADCAST_NEEDS_LOOPBACK in case you need to broadcast 799 * over the loopback interface to see your own broadcasts. 800 */ 801 if ((if_flags & IFF_LOOPBACK) != 0) 802 { 803 return (false); 804 } 805#endif 806 807 /* 808 * Inquire the interface's broadcast address. 809 */ 810 ifreq = *ifr; 811 ifbrdaddr_again: 812 if (ioctl(desc, (int) SIOCGIFBRDADDR, &ifreq) < 0) 813 { 814 if (errno == EINTR) 815 { 816 goto ifbrdaddr_again; 817 } 818 819 return (false); 820 } 821 822 memcpy (&ip_addr->sa, &ifreq.ifr_broadaddr, sizeof(struct sockaddr_in)); 823 RPC_SOCKET_FIX_ADDRLEN(ip_addr); 824 return (true); 825} 826 827/* 828**++ 829** 830** ROUTINE NAME: rpc__ip_get_broadcast 831** 832** SCOPE: PRIVATE - EPV declared in ipnaf.h 833** 834** DESCRIPTION: 835** 836** Return a vector of RPC addresses that represent all the address 837** required so that sending on all of them results in broadcasting on 838** all the local network interfaces. 839** 840** 841** INPUTS: 842** 843** naf_id Network Address Family ID serves 844** as index into EPV for IP routines. 845** 846** rpc_protseq_id 847** 848** INPUTS/OUTPUTS: none 849** 850** OUTPUTS: 851** 852** rpc_addr_vec 853** 854** status A value indicating the status of the routine. 855** 856** IMPLICIT INPUTS: none 857** 858** IMPLICIT OUTPUTS: none 859** 860** FUNCTION VALUE: none 861** 862** SIDE EFFECTS: none 863** 864**-- 865**/ 866 867PRIVATE void rpc__ip_get_broadcast 868( 869 rpc_naf_id_t naf_id, 870 rpc_protseq_id_t protseq_id, 871 rpc_addr_vector_p_t *rpc_addr_vec, 872 unsigned32 *status 873) 874{ 875 int desc; 876 877 CODING_ERROR (status); 878 879 /* 880 * Open a socket to pass to "enumerate_interface". 881 */ 882 desc = socket(AF_INET, SOCK_DGRAM, 0); 883 884 if (desc < 0) 885 { 886 *status = -7; /* !!! */ 887 return; 888 } 889 890 enumerate_interfaces 891 (protseq_id, desc, get_broadcast_addr, rpc_addr_vec, NULL, status); 892 close(desc); 893} 894 895/* 896**++ 897** 898** ROUTINE NAME: rpc__ip_init_local_addr_vec 899** 900** SCOPE: PRIVATE - declared in ipnaf.h 901** 902** DESCRIPTION: 903** 904** Initialize the local address vectors. 905** 906** 907** INPUTS: none 908** 909** INPUTS/OUTPUTS: none 910** 911** OUTPUTS: 912** 913** status A value indicating the status of the routine. 914** 915** IMPLICIT INPUTS: none 916** 917** IMPLICIT OUTPUTS: none 918** 919** FUNCTION VALUE: none 920** 921** SIDE EFFECTS: 922** 923** Update local_ip_addr_vec 924** 925**-- 926**/ 927 928PRIVATE void rpc__ip_init_local_addr_vec 929( 930 unsigned32 *status 931) 932{ 933 int desc; 934 unsigned32 lstatus; 935 unsigned32 i; 936 rpc_addr_vector_p_t rpc_addr_vec = NULL; 937 rpc_addr_vector_p_t netmask_addr_vec = NULL; 938 939 CODING_ERROR (status); 940 941 /* 942 * Open a socket to pass to "enumerate_interface". 943 */ 944 desc = socket(AF_INET, SOCK_DGRAM, 0); 945 946 if (desc < 0) 947 { 948 *status = rpc_s_cant_create_socket; /* !!! */ 949 return; 950 } 951 952 enumerate_interfaces 953 (rpc_c_protseq_id_ncadg_ip_udp, desc, get_addr, 954 &rpc_addr_vec, &netmask_addr_vec, status); 955 close(desc); 956 957 if (*status != rpc_s_ok) 958 { 959 return; 960 } 961 962 /* 963 * Do some sanity check. 964 */ 965 966 if (rpc_addr_vec == NULL 967 || netmask_addr_vec == NULL 968 || rpc_addr_vec->len != netmask_addr_vec->len 969 || rpc_addr_vec->len == 0) 970 { 971 RPC_DBG_GPRINTF(("(rpc__ip_init_local_addr_vec) no local address\n")); 972 *status = rpc_s_no_addrs; 973 goto free_rpc_addrs; 974 } 975 976 RPC_MEM_ALLOC ( 977 local_ip_addr_vec, 978 rpc_ip_s_addr_vector_p_t, 979 (sizeof *local_ip_addr_vec) 980 + ((rpc_addr_vec->len - 1) * (sizeof (local_ip_addr_vec->elt[0]))), 981 RPC_C_MEM_UTIL, 982 RPC_C_MEM_WAITOK); 983 if (local_ip_addr_vec == NULL) 984 { 985 *status = rpc_s_no_memory; 986 goto free_rpc_addrs; 987 } 988 989 local_ip_addr_vec->num_elt = rpc_addr_vec->len; 990 991 for (i = 0; i < rpc_addr_vec->len; i++) 992 { 993 local_ip_addr_vec->elt[i].addr = 994 ((rpc_ip_addr_p_t) rpc_addr_vec->addrs[i])->sa.sin_addr.s_addr; 995 local_ip_addr_vec->elt[i].netmask = 996 ((rpc_ip_addr_p_t) netmask_addr_vec->addrs[i])->sa.sin_addr.s_addr; 997#ifdef DEBUG 998 if (RPC_DBG2(rpc_e_dbg_general, 10)) 999 { 1000 char buff[16], mbuff[16]; 1001 unsigned8 *p, *mp; 1002 1003 p = (unsigned8 *) &(local_ip_addr_vec->elt[i].addr); 1004 mp = (unsigned8 *) &(local_ip_addr_vec->elt[i].netmask); 1005 RPC__IP_NETWORK_SPRINTF(buff, "%d.%d.%d.%d", 1006 UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3])); 1007 RPC__IP_NETWORK_SPRINTF(mbuff, "%d.%d.%d.%d", 1008 UC(mp[0]), UC(mp[1]), UC(mp[2]), UC(mp[3])); 1009 RPC_DBG_PRINTF(rpc_e_dbg_general, 10, 1010 ("(rpc__ip_init_local_addr_vec) local network [%s] netmask [%s]\n", 1011 buff, mbuff)); 1012 } 1013#endif 1014 } 1015 1016free_rpc_addrs: 1017 if (rpc_addr_vec != NULL) 1018 { 1019 for (i = 0; i < rpc_addr_vec->len; i++) 1020 { 1021 RPC_MEM_FREE (rpc_addr_vec->addrs[i], RPC_C_MEM_RPC_ADDR); 1022 } 1023 RPC_MEM_FREE (rpc_addr_vec, RPC_C_MEM_RPC_ADDR_VEC); 1024 } 1025 if (netmask_addr_vec != NULL) 1026 { 1027 for (i = 0; i < netmask_addr_vec->len; i++) 1028 { 1029 RPC_MEM_FREE (netmask_addr_vec->addrs[i], RPC_C_MEM_RPC_ADDR); 1030 } 1031 RPC_MEM_FREE (netmask_addr_vec, RPC_C_MEM_RPC_ADDR_VEC); 1032 } 1033 return; 1034} 1035 1036/* 1037**++ 1038** 1039** ROUTINE NAME: rpc__ip_is_local_network 1040** 1041** SCOPE: PRIVATE - declared in ipnaf.h 1042** 1043** DESCRIPTION: 1044** 1045** Return a boolean value to indicate if the given RPC address is on 1046** the same IP subnet. 1047** 1048** 1049** INPUTS: 1050** 1051** rpc_addr The address that forms the path of interest 1052** 1053** INPUTS/OUTPUTS: none 1054** 1055** OUTPUTS: 1056** 1057** status A value indicating the status of the routine. 1058** 1059** IMPLICIT INPUTS: none 1060** 1061** IMPLICIT OUTPUTS: none 1062** 1063** FUNCTION VALUE: 1064** 1065** result true => the address is on the same subnet. 1066** false => not. 1067** 1068** SIDE EFFECTS: none 1069** 1070**-- 1071**/ 1072PRIVATE boolean32 rpc__ip_is_local_network 1073( 1074 rpc_addr_p_t rpc_addr, 1075 unsigned32 *status 1076) 1077{ 1078 rpc_ip_addr_p_t ip_addr = (rpc_ip_addr_p_t) rpc_addr; 1079 unsigned32 addr1; 1080 unsigned32 addr2; 1081 unsigned32 i; 1082 1083 CODING_ERROR (status); 1084 1085 if (rpc_addr == NULL) 1086 { 1087 *status = rpc_s_invalid_arg; 1088 return false; 1089 } 1090 1091 *status = rpc_s_ok; 1092 1093 if (local_ip_addr_vec == NULL) 1094 { 1095 /* 1096 * We should call rpc__ip_init_local_addr_vec() here. But, it 1097 * requires the mutex lock for local_ip_addr_vec. For now just return 1098 * false. 1099 */ 1100 return false; 1101 } 1102 1103 /* 1104 * Compare addresses. 1105 */ 1106 for (i = 0; i < local_ip_addr_vec->num_elt; i++) 1107 { 1108 if (ip_addr->sa.sin_family != AF_INET) 1109 { 1110 continue; 1111 } 1112 1113 addr1 = ip_addr->sa.sin_addr.s_addr & local_ip_addr_vec->elt[i].netmask; 1114 addr2 = local_ip_addr_vec->elt[i].addr & local_ip_addr_vec->elt[i].netmask; 1115 1116 if (addr1 == addr2) 1117 { 1118 return true; 1119 } 1120 } 1121 1122 return false; 1123} 1124 1125/* 1126**++ 1127** 1128** ROUTINE NAME: rpc__ip_is_local_addr 1129** 1130** SCOPE: PRIVATE - declared in ipnaf.h 1131** 1132** DESCRIPTION: 1133** 1134** Return a boolean value to indicate if the given RPC address is the 1135** the local IP address. 1136** 1137** 1138** INPUTS: 1139** 1140** rpc_addr The address that forms the path of interest 1141** 1142** INPUTS/OUTPUTS: none 1143** 1144** OUTPUTS: 1145** 1146** status A value indicating the status of the routine. 1147** 1148** IMPLICIT INPUTS: none 1149** 1150** IMPLICIT OUTPUTS: none 1151** 1152** FUNCTION VALUE: 1153** 1154** result true => the address is local. 1155** false => not. 1156** 1157** SIDE EFFECTS: none 1158** 1159**-- 1160**/ 1161 1162PRIVATE boolean32 rpc__ip_is_local_addr 1163( 1164 rpc_addr_p_t rpc_addr, 1165 unsigned32 *status 1166) 1167{ 1168 rpc_ip_addr_p_t ip_addr = (rpc_ip_addr_p_t) rpc_addr; 1169 unsigned32 i; 1170 1171 CODING_ERROR (status); 1172 1173 if (rpc_addr == NULL) 1174 { 1175 *status = rpc_s_invalid_arg; 1176 return false; 1177 } 1178 1179 *status = rpc_s_ok; 1180 1181 if (local_ip_addr_vec == NULL) 1182 { 1183 /* 1184 * We should call rpc__ip_init_local_addr_vec() here. But, it 1185 * requires the mutex lock for local_ip_addr_vec. For now just return 1186 * false. 1187 */ 1188 return false; 1189 } 1190 1191 /* 1192 * Compare addresses. 1193 */ 1194 for (i = 0; i < local_ip_addr_vec->num_elt; i++) 1195 { 1196 if (ip_addr->sa.sin_family != AF_INET) 1197 { 1198 continue; 1199 } 1200 1201 if (ip_addr->sa.sin_addr.s_addr == local_ip_addr_vec->elt[i].addr) 1202 { 1203 return true; 1204 } 1205 } 1206 1207 return false; 1208} 1209