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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27
28
29 #include <stdio.h>
30 #include <sys/types.h>
31 #include <sys/socket.h>
32 #include <netdb.h>
33 #include <unistd.h>
34 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <sys/sockio.h>
37 #include <net/if.h>
38 #include <netinet/in.h>
39 #include <arpa/inet.h>
40 #include <errno.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <libintl.h>
44
45 static int is_local_if(struct hostent *hp);
46
47 /*
48 * Given a host name, check to see if it points to the local host.
49 * If it does, return 1, else return 0.
50 *
51 * The strategy is this: translate the host name argument to a list of
52 * addresses. Then compare each of those addresses to the addresses of
53 * network interfaces on this host.
54 */
55 int
is_local_host(char * host)56 is_local_host(char *host)
57 {
58 struct hostent *hp;
59 int err;
60 int flags = AI_DEFAULT;
61
62 if (hp = getipnodebyname((const char *) host, AF_INET, flags, &err))
63 if (is_local_if(hp))
64 return (1);
65 if (hp = getipnodebyname((const char *) host, AF_INET6, flags, &err))
66 if (is_local_if(hp))
67 return (1);
68
69 return (0);
70 }
71
72 static int
is_local_if(struct hostent * hp)73 is_local_if(struct hostent *hp)
74 {
75 char *buf;
76 struct lifconf lifc;
77 struct lifnum lifn;
78 struct lifreq lifr;
79 struct lifreq *lifrp;
80 int bufsiz;
81 int nha;
82 int nif;
83 int s;
84
85 if ((s = socket(hp->h_addrtype, SOCK_DGRAM, 0)) == -1) {
86 perror("socket");
87 return (0);
88 }
89
90 lifn.lifn_family = hp->h_addrtype;
91 lifn.lifn_flags = LIFC_EXTERNAL_SOURCE;
92 if (ioctl(s, SIOCGLIFNUM, (char *)&lifn) == -1) {
93 perror("SIOCGLIFNUM");
94 (void) close(s);
95 return (0);
96 }
97 bufsiz = lifn.lifn_count * sizeof (struct lifreq);
98
99 if ((buf = malloc(bufsiz)) == NULL) {
100 perror("malloc");
101 (void) close(s);
102 return (0);
103 }
104
105 lifc.lifc_family = hp->h_addrtype;
106 lifc.lifc_flags = LIFC_EXTERNAL_SOURCE;
107 lifc.lifc_len = bufsiz;
108 lifc.lifc_buf = buf;
109 if (ioctl(s, SIOCGLIFCONF, (char *)&lifc) == -1) {
110 perror("SIOCGLIFCONF");
111 (void) close(s);
112 free(buf);
113 return (0);
114 }
115
116 #define lifraddrp(lifrp) ((lifrp->lifr_addr.ss_family == AF_INET6) ? \
117 (void *) &((struct sockaddr_in6 *)&lifrp->lifr_addr)->sin6_addr : \
118 (void *) &((struct sockaddr_in *)&lifrp->lifr_addr)->sin_addr)
119
120 for (lifrp = lifc.lifc_req,
121 nif = lifc.lifc_len / sizeof (struct lifreq);
122 nif > 0; nif--, lifrp++) {
123 if (lifrp->lifr_addr.ss_family != hp->h_addrtype) {
124 continue;
125 }
126 (void) memset(&lifr, 0, sizeof (lifr));
127 (void) strncpy(lifr.lifr_name, lifrp->lifr_name,
128 sizeof (lifr.lifr_name));
129 if (ioctl(s, SIOCGLIFFLAGS, (caddr_t)&lifr) == -1) {
130 perror("SIOCGLIFFLAGS");
131 (void) close(s);
132 free(buf);
133 return (0);
134 }
135
136 for (nha = 0; hp->h_addr_list[nha]; nha++) {
137 if (memcmp(hp->h_addr_list[nha], lifraddrp(lifrp),
138 hp->h_length) == 0) {
139 (void) close(s);
140 free(buf);
141 return (1);
142 }
143 }
144 }
145
146 #undef lifraddrp
147
148 (void) close(s);
149 free(buf);
150 return (0);
151 }
152