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