1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 #pragma ident "%Z%%M% %I% %E% SMI" 23 24 /* 25 * get_myaddress.c 26 * 27 * Get client's IP address via ioctl. This avoids using the NIS. 28 * Copyright (C) 1990, Sun Microsystems, Inc. 29 */ 30 31 #include <rpc/types.h> 32 #include <rpc/pmap_prot.h> 33 #include <sys/socket.h> 34 #include <sys/sockio.h> 35 #include <stdio.h> 36 #include <net/if.h> 37 #include <sys/ioctl.h> 38 #include <arpa/inet.h> 39 #include <netinet/in.h> 40 #include <syslog.h> 41 #include <malloc.h> 42 #include <unistd.h> 43 #include <stropts.h> 44 #include <stdlib.h> 45 #include <errno.h> 46 47 /* 48 * don't use gethostbyname, which would invoke NIS 49 */ 50 void 51 get_myaddress(struct sockaddr_in *addr) 52 { 53 int s; 54 struct ifconf ifc; 55 struct ifreq ifreq, *ifr; 56 int len, numifs; 57 int ret; 58 59 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 60 syslog(LOG_ERR, "get_myaddress: socket: %m"); 61 exit(1); 62 } 63 64 do { 65 ret = ioctl(s, SIOCGIFNUM, (char *)&numifs); 66 } while (ret < 0 && (errno == EINTR || errno == EAGAIN)); 67 if (ret < 0) { 68 syslog(LOG_ERR, "get_myaddress: ioctl: %m"); 69 exit(1); 70 } 71 72 ifc.ifc_len = numifs * sizeof (struct ifreq); 73 if ((ifc.ifc_buf = (caddr_t)malloc(ifc.ifc_len)) == NULL) { 74 syslog(LOG_ERR, "get_myaddress: malloc: %m"); 75 exit(1); 76 } 77 78 do { 79 ret = ioctl(s, SIOCGIFCONF, (char *)&ifc); 80 } while (ret < 0 && (errno == EINTR || errno == EAGAIN)); 81 if (ret < 0) { 82 syslog(LOG_ERR, 83 "get_myaddress: ioctl (get interface configuration): %m"); 84 exit(1); 85 } 86 87 /* 88 * set default to loopback in case nothing is found. 89 */ 90 addr->sin_family = AF_INET; 91 addr->sin_addr.s_addr = htonl(INADDR_LOOPBACK); 92 addr->sin_port = htons(PMAPPORT); 93 94 ifr = ifc.ifc_req; 95 for (len = ifc.ifc_len; len > 0; len -= sizeof (ifreq), ifr++) { 96 ifreq = *ifr; 97 do { 98 ret = ioctl(s, SIOCGIFFLAGS, (char *)&ifreq); 99 } while (ret < 0 && (errno == EINTR || errno == EAGAIN)); 100 if (ret < 0) { 101 syslog(LOG_ERR, "get_myaddress: ioctl: %m"); 102 exit(1); 103 } 104 if (ifr->ifr_addr.sa_family != AF_INET) 105 continue; 106 if ((ifreq.ifr_flags & IFF_UP) == 0) 107 continue; 108 if (ifreq.ifr_flags & IFF_LOOPBACK) 109 continue; 110 if ((ifreq.ifr_flags & (IFF_MULTICAST | IFF_BROADCAST)) == 0) 111 continue; 112 *addr = *((struct sockaddr_in *)&ifr->ifr_addr); 113 addr->sin_port = htons(PMAPPORT); 114 break; 115 } 116 free(ifc.ifc_buf); 117 (void) close(s); 118 } 119