Merge branch 'master' of https://git.code.sf.net/p/cdesktopenv/code
[oweals/cde.git] / cde / lib / tt / lib / util / tt_host_equiv.C
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
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)
10  * any later version.
11  *
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
16  * details.
17  *
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
22  */
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 $                                                       
28 /*
29  *
30  * @(#)tt_host_equiv.C
31  *
32  * Copyright (c) 1994 by Sun Microsystems, Inc.
33  */
34
35 #include <util/tt_host_equiv.h>
36
37 #define X_INCLUDE_NETDB_H
38 #define XOS_USE_XT_LOCKING
39 #if defined(linux) || defined(CSRG_BASED)
40 #define index
41 #define rindex
42 #endif
43 #include <X11/Xos_r.h>
44 #if defined(linux) || defined(CSRG_BASED)
45 #undef index
46 #undef rindex
47 #endif
48 static int _cache_it(_Tt_hostname_cache_ptr, _Tt_string &);
49
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 &.
52 _Tt_hostname_cache::
53 _Tt_hostname_cache()
54 {
55         hostname = (_Tt_string) 0;
56 }
57
58 _Tt_hostname_cache::
59 _Tt_hostname_cache(_Tt_string & new_hostname)
60 {
61         hostname = new_hostname;
62         addr_list = new _Tt_string_list;
63         addr_length = 0;
64 }
65
66 _Tt_hostname_cache::
67 ~_Tt_hostname_cache()
68 {
69 }
70
71 _Tt_string _Tt_hostname_cache::
72 h_keyfn (_Tt_object_ptr & p)
73 {
74         return ((_Tt_hostname_cache *)p.c_pointer())->hostname_val();
75 }
76
77 _Tt_host_equiv::
78 _Tt_host_equiv()
79 {
80         _cache_table =
81                 new _Tt_hostname_cache_table((_Tt_object_table_keyfn) & _Tt_hostname_cache::h_keyfn);
82 }
83
84 _Tt_host_equiv::
85 ~_Tt_host_equiv()
86 {
87 }
88
89
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
95 // multiple domains:
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.
99 //
100 //      However, if if you have B.Corp.Sun.COM and
101 //      localhost.Eng.Sun.COM return B.Corp
102 //
103 _Tt_string _Tt_host_equiv::
104 prefix_host(const _Tt_string & host, const _Tt_string & localhost)
105 {
106         int i, j;
107         _Tt_string h_prefix = host, l_prefix = localhost,
108                    h, l, rpart_host, rpart_localhost;
109
110 #ifdef notdef
111 printf("DEBUG prefix_host: host = %s, localhost = %s\n",
112         (char *) host, (char *) localhost);
113 #endif
114
115         while (rpart_host == rpart_localhost) {
116                 h = h_prefix;
117                 l = l_prefix;
118
119                 if ((i = h.rindex('.')) == -1 ||
120                     (j = l.rindex('.')) == -1) {
121                         break;
122                 }
123
124                 rpart_host = h.split(i, h_prefix);
125                 rpart_localhost = l.split(j, l_prefix);
126         }
127
128 #ifdef notdef
129 printf("DEBUG prefix_host: returning %s\n", (char *) h);
130 #endif
131         return h;
132 }
133
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.
138 //
139 int _Tt_host_equiv::
140 hostname_equiv(const _Tt_string & host1, const _Tt_string & host2)
141 {
142         // First try a simple comparison.
143         if (host1 == host2) {
144 #ifdef notdef
145 printf("DEBUG hostname_equiv: host1 == host2, returning 1\n");
146 #endif
147                 return 1;
148         }
149
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;
154  
155         if (host1.len() > host2.len()) {
156                 shorthost = host2;
157                 longhost = host1;
158         } else {
159                 // "longhost" may actually be equal to the
160                 // len of "shorthost".
161                 shorthost = host1;
162                 longhost = host2;
163         }
164  
165         // Find how many .'s are in the names, in case
166         // one or both of the names are an FQDN.
167         long_tmp = longhost;
168         short_tmp = shorthost;
169         while (long_tmp.index('.') != -1) {  
170                 long_count++;
171                 long_tmp = long_tmp.split('.', long_prefix);
172         }
173
174         while (short_tmp.index('.') != -1) {  
175                 short_count++;
176                 short_tmp = short_tmp.split('.', short_prefix);
177         }
178
179         // loop until we determine short is a prefix of long, or
180         // until we run out of things to compare.
181         long_tmp = longhost;
182         short_tmp = shorthost;
183         for (is_found = 0;
184              short_count >= 0 && long_count > 0;
185              long_count--, short_count--) {
186
187                 // Get the chunk upto the next dot
188                 long_tmp = long_tmp.split('.', long_prefix);
189                 short_tmp = short_tmp.split('.', short_prefix);
190
191                 if (short_prefix.len() == 0) {
192                         // shorthost has no dots in it,
193                         // so do just one comparison.
194
195                         if (short_tmp != long_prefix) {
196 #ifdef notdef
197 printf("DEBUG hostname_equiv: short_tmp %s != long_prefix %s, returning 0\n",
198         (char *) short_tmp, (char *) long_prefix);
199 #endif
200                                 return 0;
201                         }
202                         is_found = 1;
203                         break;
204                 }
205
206                 if (short_prefix != long_prefix) {
207 #ifdef notdef
208 printf("DEBUG hostname_equiv: short_prefix %s != long_prefix %s, returning 0\n",
209         (char *) short_prefix, (char *) long_prefix);
210 #endif
211                         return 0;
212                 }
213         }
214
215         if (is_found != 1) {
216 #ifdef notdef
217 printf("DEBUG hostname_equiv: is_found != 1, returning 0\n");
218 #endif
219                 return 0;       // no prefix was found
220         }
221
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.
227
228
229         // Lookup the both entries int the cache to see if we`ve
230         // already mapped them.  If we haven't, map & cache them.
231         //
232         _Tt_hostname_cache_ptr sh, lh;
233
234         sh = _cache_table->lookup(shorthost);
235         if (sh.is_null()) {
236                 sh = new _Tt_hostname_cache(shorthost);
237
238                 if (_cache_it(sh, shorthost) == 1) {
239                         _cache_table->insert(sh);
240                 } else {
241 #ifdef notdef
242 printf("DEBUG hostname_equiv: sh.is_null(): returning 0\n");
243 #endif
244                         return 0;
245                 }
246         }
247
248         lh = _cache_table->lookup(longhost);
249         if (lh.is_null()) {
250                 lh = new _Tt_hostname_cache(longhost);
251
252                 if (_cache_it(lh, longhost) == 1) {
253                         _cache_table->insert(lh);
254                 } else {
255 #ifdef notdef
256 printf("DEBUG hostname_equiv: lh.is_null(): returning 0\n");
257 #endif
258                         return 0;
259                 }
260         }
261
262         // Now sort through the address list looking
263         // for a match.
264
265         // This will probably never happen but why
266         // not be careful?
267         if (sh->addr_length != lh->addr_length) {
268 #ifdef notdef
269 printf("DEBUG hostname_equiv: sh->addr_length %d != h->addr_length %d, returning 0\n",
270         sh->addr_length, lh->addr_length);
271 #endif
272                 return 0;
273         }
274
275         _Tt_string_list_cursor sh_c(sh->addr_list);
276         _Tt_string_list_cursor lh_c(lh->addr_list);
277
278         while (sh_c.next()) {
279                 while (lh_c.next()) {
280 #ifdef notdef
281 printf("DEBUG hostname_equiv: checking address at 0x%x w/ 0x%x\n", 
282         (char *) *sh_c, (char *) *lh_c);
283 #endif
284                         // Do the IP addresses match?
285                         if (memcmp((char *) *sh_c, (char *) *lh_c,
286                                     sh->addr_length) == 0) {
287                                 // success!
288 #ifdef notdef
289 printf("DEBUG hostname_equiv: found match!\n");
290 #endif
291                                 return 1;
292                         }
293                 }
294         }
295
296         // failure
297         return 0;
298 }
299
300
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.
304 static int
305 _cache_it(_Tt_hostname_cache_ptr cache_ptr, _Tt_string & hostname)
306 {
307         _Tt_hostname_cache_ptr  sh, lh;
308         struct hostent         *host_ret;
309         _Xgethostbynameparams   host_buf;
310         int                     failed = 0;
311         char                    **h_addr_list;
312
313
314         memset((char*) &host_buf, 0, sizeof(_Xgethostbynameparams));
315         if ((host_ret = _XGethostbyname((char*) hostname, host_buf)) == NULL) {
316                 return 0;
317         }
318
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.
324
325         cache_ptr->addr_length = host_ret->h_length;
326
327         // Copy the list of IP addresses
328         for (h_addr_list = host_ret->h_addr_list; 
329              h_addr_list; 
330              h_addr_list++) {
331
332                 if (! *h_addr_list) {
333                         break;  // no more addresses
334                 }
335
336                 // copy the address
337                 _Tt_string new_addr((const unsigned char *)h_addr_list,
338                                     host_ret->h_length);
339                 // cache it
340                 cache_ptr->addr_list->append(new_addr);
341         }
342
343         return 1;
344 }