2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 //%% (c) Copyright 1993, 1994 Hewlett-Packard Company
24 //%% (c) Copyright 1993, 1994 International Business Machines Corp.
25 //%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
26 //%% (c) Copyright 1993, 1994 Novell, Inc.
27 //%% $TOG: tt_host_equiv.C /main/9 1999/10/14 18:41:50 mgreess $
32 * Copyright (c) 1994 by Sun Microsystems, Inc.
35 #include <util/tt_host_equiv.h>
37 #define X_INCLUDE_NETDB_H
38 #define XOS_USE_XT_LOCKING
39 #if defined(linux) || defined(CSRG_BASED)
43 #include <X11/Xos_r.h>
44 #if defined(linux) || defined(CSRG_BASED)
48 static int _cache_it(_Tt_hostname_cache_ptr, _Tt_string &);
50 // This null constructor is required by the _table_of macro:
51 // DO NOT use it! Use the one below that that's a _Tt_string &.
55 hostname = (_Tt_string) 0;
59 _Tt_hostname_cache(_Tt_string & new_hostname)
61 hostname = new_hostname;
62 addr_list = new _Tt_string_list;
71 _Tt_string _Tt_hostname_cache::
72 h_keyfn (_Tt_object_ptr & p)
74 return ((_Tt_hostname_cache *)p.c_pointer())->hostname_val();
81 new _Tt_hostname_cache_table((_Tt_object_table_keyfn) & _Tt_hostname_cache::h_keyfn);
90 // return a string which uniquely identifies host,
91 // based on the contents of host and the supplied
92 // string localhost. The intent of this function
93 // is to allow one to get a name which IDs
94 // a useful minimum string of a host across
96 // i.e. if you have A.Eng.Sun.COM,
97 // and localhost.Eng.Sun.COM, return A,
98 // because you both are in the same domain.
100 // However, if if you have B.Corp.Sun.COM and
101 // localhost.Eng.Sun.COM return B.Corp
103 _Tt_string _Tt_host_equiv::
104 prefix_host(const _Tt_string & host, const _Tt_string & localhost)
107 _Tt_string h_prefix = host, l_prefix = localhost,
108 h, l, rpart_host, rpart_localhost;
111 printf("DEBUG prefix_host: host = %s, localhost = %s\n",
112 (char *) host, (char *) localhost);
115 while (rpart_host == rpart_localhost) {
119 if ((i = h.rindex('.')) == -1 ||
120 (j = l.rindex('.')) == -1) {
124 rpart_host = h.split(i, h_prefix);
125 rpart_localhost = l.split(j, l_prefix);
129 printf("DEBUG prefix_host: returning %s\n", (char *) h);
134 // Determine if two hostnames refer to the same host.
135 // This is required because a user may pass in a
136 // simple hostname or a hostname with a fully qualified
137 // domain name (FQDN) attached.
140 hostname_equiv(const _Tt_string & host1, const _Tt_string & host2)
142 // First try a simple comparison.
143 if (host1 == host2) {
145 printf("DEBUG hostname_equiv: host1 == host2, returning 1\n");
150 int is_found = 0, long_count = 0, short_count = 0;
151 _Tt_string shorthost, longhost;
152 _Tt_string short_prefix, long_prefix;
153 _Tt_string short_tmp, long_tmp;
155 if (host1.len() > host2.len()) {
159 // "longhost" may actually be equal to the
160 // len of "shorthost".
165 // Find how many .'s are in the names, in case
166 // one or both of the names are an FQDN.
168 short_tmp = shorthost;
169 while (long_tmp.index('.') != -1) {
171 long_tmp = long_tmp.split('.', long_prefix);
174 while (short_tmp.index('.') != -1) {
176 short_tmp = short_tmp.split('.', short_prefix);
179 // loop until we determine short is a prefix of long, or
180 // until we run out of things to compare.
182 short_tmp = shorthost;
184 short_count >= 0 && long_count > 0;
185 long_count--, short_count--) {
187 // Get the chunk upto the next dot
188 long_tmp = long_tmp.split('.', long_prefix);
189 short_tmp = short_tmp.split('.', short_prefix);
191 if (short_prefix.len() == 0) {
192 // shorthost has no dots in it,
193 // so do just one comparison.
195 if (short_tmp != long_prefix) {
197 printf("DEBUG hostname_equiv: short_tmp %s != long_prefix %s, returning 0\n",
198 (char *) short_tmp, (char *) long_prefix);
206 if (short_prefix != long_prefix) {
208 printf("DEBUG hostname_equiv: short_prefix %s != long_prefix %s, returning 0\n",
209 (char *) short_prefix, (char *) long_prefix);
217 printf("DEBUG hostname_equiv: is_found != 1, returning 0\n");
219 return 0; // no prefix was found
222 // One name is a prefix of the other.
223 // Now do a name lookup on both strings,
224 // get the IP addresses, and compare them
225 // to determine if the names do truly
226 // reference the same machine.
229 // Lookup the both entries int the cache to see if we`ve
230 // already mapped them. If we haven't, map & cache them.
232 _Tt_hostname_cache_ptr sh, lh;
234 sh = _cache_table->lookup(shorthost);
236 sh = new _Tt_hostname_cache(shorthost);
238 if (_cache_it(sh, shorthost) == 1) {
239 _cache_table->insert(sh);
242 printf("DEBUG hostname_equiv: sh.is_null(): returning 0\n");
248 lh = _cache_table->lookup(longhost);
250 lh = new _Tt_hostname_cache(longhost);
252 if (_cache_it(lh, longhost) == 1) {
253 _cache_table->insert(lh);
256 printf("DEBUG hostname_equiv: lh.is_null(): returning 0\n");
262 // Now sort through the address list looking
265 // This will probably never happen but why
267 if (sh->addr_length != lh->addr_length) {
269 printf("DEBUG hostname_equiv: sh->addr_length %d != h->addr_length %d, returning 0\n",
270 sh->addr_length, lh->addr_length);
275 _Tt_string_list_cursor sh_c(sh->addr_list);
276 _Tt_string_list_cursor lh_c(lh->addr_list);
278 while (sh_c.next()) {
279 while (lh_c.next()) {
281 printf("DEBUG hostname_equiv: checking address at 0x%x w/ 0x%x\n",
282 (char *) *sh_c, (char *) *lh_c);
284 // Do the IP addresses match?
285 if (memcmp((char *) *sh_c, (char *) *lh_c,
286 sh->addr_length) == 0) {
289 printf("DEBUG hostname_equiv: found match!\n");
301 // This is done here instead of in the constructor because
302 // gethostbyname can fail and I don't want things that can fail
303 // to be in a constructor.
305 _cache_it(_Tt_hostname_cache_ptr cache_ptr, _Tt_string & hostname)
307 _Tt_hostname_cache_ptr sh, lh;
308 struct hostent *host_ret;
309 _Xgethostbynameparams host_buf;
314 memset((char*) &host_buf, 0, sizeof(_Xgethostbynameparams));
315 if ((host_ret = _XGethostbyname((char*) hostname, host_buf)) == NULL) {
319 // cache the parts of the entry we're
320 // interested in. We have to do this
321 // since gethostbyname() returns a pointer
322 // to static memory, and since struct hostent's
323 // have pointers in them.
325 cache_ptr->addr_length = host_ret->h_length;
327 // Copy the list of IP addresses
328 for (h_addr_list = host_ret->h_addr_list;
332 if (! *h_addr_list) {
333 break; // no more addresses
337 _Tt_string new_addr((const unsigned char *)h_addr_list,
340 cache_ptr->addr_list->append(new_addr);