2 * Check if an address belongs to the local system. Adapted from:
4 * @(#)pmap_svc.c 1.32 91/03/11 Copyright 1984,1990 Sun Microsystems, Inc.
5 * @(#)get_myaddress.c 2.1 88/07/29 4.0 RPCSRC.
9 * Copyright (c) 2009, Sun Microsystems, Inc.
10 * All rights reserved.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 * - Redistributions of source code must retain the above copyright notice,
15 * this list of conditions and the following disclaimer.
16 * - Redistributions in binary form must reproduce the above copyright notice,
17 * this list of conditions and the following disclaimer in the documentation
18 * and/or other materials provided with the distribution.
19 * - Neither the name of Sun Microsystems, Inc. nor the names of its
20 * contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
37 static char sccsid[] = "@(#) from_local.c 1.3 96/05/31 15:52:57";
44 #include <sys/types.h>
45 #include <sys/socket.h>
50 #include <netinet/in.h>
52 #include <sys/ioctl.h>
57 #include "tcpwrapper.h"
65 #ifdef HAVE_GETIFADDRS
71 * from_local - determine whether request comes from the local system
72 * @sap: pointer to socket address to check
74 * With virtual hosting, each hardware network interface can have
75 * multiple network addresses. On such machines the number of machine
76 * addresses can be surprisingly large.
78 * We also expect the local network configuration to change over time,
79 * so call getifaddrs(3) more than once, but not too often.
81 * Returns TRUE if the sockaddr contains an address of one of the local
82 * network interfaces. Otherwise FALSE is returned.
85 from_local(const struct sockaddr *sap)
87 static struct ifaddrs *ifaddr = NULL;
88 static time_t last_update = 0;
93 if (time(&now) == ((time_t)-1)) {
94 xlog(L_ERROR, "%s: time(2): %m", __func__);
96 /* If we don't know what time it is, use the
97 * existing ifaddr list, if one exists */
102 if (now != last_update) {
103 xlog(D_GENERAL, "%s: updating local if addr list", __func__);
108 if (getifaddrs(&ifaddr) == -1) {
109 xlog(L_ERROR, "%s: getifaddrs(3): %m", __func__);
117 for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
118 if ((ifa->ifa_flags & IFF_UP) &&
119 nfs_compare_sockaddr(sap, ifa->ifa_addr)) {
120 xlog(D_GENERAL, "%s: incoming address matches "
121 "local interface address", __func__);
127 xlog(D_GENERAL, "%s: checked %u local if addrs; "
128 "incoming address not found", __func__, count);
132 #else /* !HAVE_GETIFADDRS */
134 static int num_local;
135 static int num_addrs;
136 static struct in_addr *addrs;
138 /* grow_addrs - extend list of local interface addresses */
140 static int grow_addrs(void)
142 struct in_addr *new_addrs;
146 * Keep the previous result if we run out of memory. The system would
147 * really get hosed if we simply give up.
149 new_num = (addrs == 0) ? 1 : num_addrs + num_addrs;
150 new_addrs = (struct in_addr *) malloc(sizeof(*addrs) * new_num);
151 if (new_addrs == 0) {
152 xlog_warn("%s: out of memory", __func__);
156 memcpy((char *) new_addrs, (char *) addrs,
157 sizeof(*addrs) * num_addrs);
158 free((char *) addrs);
166 /* find_local - find all IP addresses for this host */
173 struct ifreq *the_end;
178 * Get list of network interfaces. We use a huge buffer to allow for the
179 * presence of non-IP interfaces.
182 if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
183 xlog_warn("%s: socket(2): %m", __func__);
186 ifc.ifc_len = sizeof(buf);
188 if (ioctl(sock, SIOCGIFCONF, (char *) &ifc) < 0) {
189 xlog_warn("%s: ioctl(SIOCGIFCONF): %m", __func__);
193 /* Get IP address of each active IP network interface. */
195 the_end = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
197 for (ifr = ifc.ifc_req; ifr < the_end; ifr++) {
198 if (ifr->ifr_addr.sa_family == AF_INET) { /* IP net interface */
200 if (ioctl(sock, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
201 xlog_warn("%s: ioctl(SIOCGIFFLAGS): %m", __func__);
202 } else if (ifreq.ifr_flags & IFF_UP) { /* active interface */
203 if (ioctl(sock, SIOCGIFADDR, (char *) &ifreq) < 0) {
204 xlog_warn("%s: ioctl(SIOCGIFADDR): %m", __func__);
206 if (num_local >= num_addrs)
207 if (grow_addrs() == 0)
209 addrs[num_local++] = ((struct sockaddr_in *)
210 & ifreq.ifr_addr)->sin_addr;
214 /* Support for variable-length addresses. */
216 ifr = (struct ifreq *) ((caddr_t) ifr
217 + ifr->ifr_addr.sa_len - sizeof(struct sockaddr));
225 * from_local - determine whether request comes from the local system
226 * @sap: pointer to socket address to check
228 * With virtual hosting, each hardware network interface can have
229 * multiple network addresses. On such machines the number of machine
230 * addresses can be surprisingly large.
232 * Returns TRUE if the sockaddr contains an address of one of the local
233 * network interfaces. Otherwise FALSE is returned.
236 from_local(const struct sockaddr *sap)
238 const struct sockaddr_in *addr = (const struct sockaddr_in *)sap;
241 if (sap->sa_family != AF_INET)
244 if (addrs == 0 && find_local() == 0)
245 xlog(L_ERROR, "Cannot find any active local network interfaces");
247 for (i = 0; i < num_local; i++) {
248 if (memcmp((char *) &(addr->sin_addr), (char *) &(addrs[i]),
249 sizeof(struct in_addr)) == 0)
262 for (i = 0; i < num_local; i++)
263 printf("%s\n", inet_ntoa(addrs[i]));
268 #endif /* !HAVE_GETIFADDRS */