Add GNU LGPL headers to all .c .C and .h files
[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 #include <X11/Xos_r.h>
40
41 static int _cache_it(_Tt_hostname_cache_ptr, _Tt_string &);
42
43 // This null constructor is required by the _table_of macro:
44 // DO NOT use it!  Use the one below that that's a _Tt_string &.
45 _Tt_hostname_cache::
46 _Tt_hostname_cache()
47 {
48         hostname = (_Tt_string) 0;
49 }
50
51 _Tt_hostname_cache::
52 _Tt_hostname_cache(_Tt_string & new_hostname)
53 {
54         hostname = new_hostname;
55         addr_list = new _Tt_string_list;
56         addr_length = 0;
57 }
58
59 _Tt_hostname_cache::
60 ~_Tt_hostname_cache()
61 {
62 }
63
64 _Tt_string _Tt_hostname_cache::
65 h_keyfn (_Tt_object_ptr & p)
66 {
67         return ((_Tt_hostname_cache *)p.c_pointer())->hostname_val();
68 }
69
70 _Tt_host_equiv::
71 _Tt_host_equiv()
72 {
73         _cache_table =
74                 new _Tt_hostname_cache_table((_Tt_object_table_keyfn) & _Tt_hostname_cache::h_keyfn);
75 }
76
77 _Tt_host_equiv::
78 ~_Tt_host_equiv()
79 {
80 }
81
82
83 // return a string which uniquely identifies host,
84 // based on the contents of host and the supplied
85 // string localhost. The intent of this function
86 // is to allow one to get a name which IDs
87 // a useful minimum string of a host across
88 // multiple domains:
89 //      i.e. if you have A.Eng.Sun.COM,
90 //      and localhost.Eng.Sun.COM, return A,
91 //      because you both are in the same domain.
92 //
93 //      However, if if you have B.Corp.Sun.COM and
94 //      localhost.Eng.Sun.COM return B.Corp
95 //
96 _Tt_string _Tt_host_equiv::
97 prefix_host(const _Tt_string & host, const _Tt_string & localhost)
98 {
99         int i, j;
100         _Tt_string h_prefix = host, l_prefix = localhost,
101                    h, l, rpart_host, rpart_localhost;
102
103 #ifdef notdef
104 printf("DEBUG prefix_host: host = %s, localhost = %s\n",
105         (char *) host, (char *) localhost);
106 #endif
107
108         while (rpart_host == rpart_localhost) {
109                 h = h_prefix;
110                 l = l_prefix;
111
112                 if ((i = h.rindex('.')) == -1 ||
113                     (j = l.rindex('.')) == -1) {
114                         break;
115                 }
116
117                 rpart_host = h.split(i, h_prefix);
118                 rpart_localhost = l.split(j, l_prefix);
119         }
120
121 #ifdef notdef
122 printf("DEBUG prefix_host: returning %s\n", (char *) h);
123 #endif
124         return h;
125 }
126
127 // Determine if two hostnames refer to the same host.
128 // This is required because a user may pass in a
129 // simple hostname or a hostname with a fully qualified
130 // domain name (FQDN) attached.
131 //
132 int _Tt_host_equiv::
133 hostname_equiv(const _Tt_string & host1, const _Tt_string & host2)
134 {
135         // First try a simple comparison.
136         if (host1 == host2) {
137 #ifdef notdef
138 printf("DEBUG hostname_equiv: host1 == host2, returning 1\n");
139 #endif
140                 return 1;
141         }
142
143         int     is_found = 0, long_count = 0, short_count = 0;
144         _Tt_string shorthost, longhost;
145         _Tt_string short_prefix, long_prefix;
146         _Tt_string short_tmp, long_tmp;
147  
148         if (host1.len() > host2.len()) {
149                 shorthost = host2;
150                 longhost = host1;
151         } else {
152                 // "longhost" may actually be equal to the
153                 // len of "shorthost".
154                 shorthost = host1;
155                 longhost = host2;
156         }
157  
158         // Find how many .'s are in the names, in case
159         // one or both of the names are an FQDN.
160         long_tmp = longhost;
161         short_tmp = shorthost;
162         while (long_tmp.index('.') != -1) {  
163                 long_count++;
164                 long_tmp = long_tmp.split('.', long_prefix);
165         }
166
167         while (short_tmp.index('.') != -1) {  
168                 short_count++;
169                 short_tmp = short_tmp.split('.', short_prefix);
170         }
171
172         // loop until we determine short is a prefix of long, or
173         // until we run out of things to compare.
174         long_tmp = longhost;
175         short_tmp = shorthost;
176         for (is_found = 0;
177              short_count >= 0 && long_count > 0;
178              long_count--, short_count--) {
179
180                 // Get the chunk upto the next dot
181                 long_tmp = long_tmp.split('.', long_prefix);
182                 short_tmp = short_tmp.split('.', short_prefix);
183
184                 if (short_prefix.len() == 0) {
185                         // shorthost has no dots in it,
186                         // so do just one comparison.
187
188                         if (short_tmp != long_prefix) {
189 #ifdef notdef
190 printf("DEBUG hostname_equiv: short_tmp %s != long_prefix %s, returning 0\n",
191         (char *) short_tmp, (char *) long_prefix);
192 #endif
193                                 return 0;
194                         }
195                         is_found = 1;
196                         break;
197                 }
198
199                 if (short_prefix != long_prefix) {
200 #ifdef notdef
201 printf("DEBUG hostname_equiv: short_prefix %s != long_prefix %s, returning 0\n",
202         (char *) short_prefix, (char *) long_prefix);
203 #endif
204                         return 0;
205                 }
206         }
207
208         if (is_found != 1) {
209 #ifdef notdef
210 printf("DEBUG hostname_equiv: is_found != 1, returning 0\n");
211 #endif
212                 return 0;       // no prefix was found
213         }
214
215         // One name is a prefix of the other.
216         // Now do a name lookup on both strings,
217         // get the IP addresses, and compare them
218         // to determine if the names do truly
219         // reference the same machine.
220
221
222         // Lookup the both entries int the cache to see if we`ve
223         // already mapped them.  If we haven't, map & cache them.
224         //
225         _Tt_hostname_cache_ptr sh, lh;
226
227         sh = _cache_table->lookup(shorthost);
228         if (sh.is_null()) {
229                 sh = new _Tt_hostname_cache(shorthost);
230
231                 if (_cache_it(sh, shorthost) == 1) {
232                         _cache_table->insert(sh);
233                 } else {
234 #ifdef notdef
235 printf("DEBUG hostname_equiv: sh.is_null(): returning 0\n");
236 #endif
237                         return 0;
238                 }
239         }
240
241         lh = _cache_table->lookup(longhost);
242         if (lh.is_null()) {
243                 lh = new _Tt_hostname_cache(longhost);
244
245                 if (_cache_it(lh, longhost) == 1) {
246                         _cache_table->insert(lh);
247                 } else {
248 #ifdef notdef
249 printf("DEBUG hostname_equiv: lh.is_null(): returning 0\n");
250 #endif
251                         return 0;
252                 }
253         }
254
255         // Now sort through the address list looking
256         // for a match.
257
258         // This will probably never happen but why
259         // not be careful?
260         if (sh->addr_length != lh->addr_length) {
261 #ifdef notdef
262 printf("DEBUG hostname_equiv: sh->addr_length %d != h->addr_length %d, returning 0\n",
263         sh->addr_length, lh->addr_length);
264 #endif
265                 return 0;
266         }
267
268         _Tt_string_list_cursor sh_c(sh->addr_list);
269         _Tt_string_list_cursor lh_c(lh->addr_list);
270
271         while (sh_c.next()) {
272                 while (lh_c.next()) {
273 #ifdef notdef
274 printf("DEBUG hostname_equiv: checking address at 0x%x w/ 0x%x\n", 
275         (char *) *sh_c, (char *) *lh_c);
276 #endif
277                         // Do the IP addresses match?
278                         if (memcmp((char *) *sh_c, (char *) *lh_c,
279                                     sh->addr_length) == 0) {
280                                 // success!
281 #ifdef notdef
282 printf("DEBUG hostname_equiv: found match!\n");
283 #endif
284                                 return 1;
285                         }
286                 }
287         }
288
289         // failure
290         return 0;
291 }
292
293
294 // This is done here instead of in the constructor because
295 // gethostbyname can fail  and I don't want things that can fail
296 // to be in a constructor.
297 static int
298 _cache_it(_Tt_hostname_cache_ptr cache_ptr, _Tt_string & hostname)
299 {
300         _Tt_hostname_cache_ptr  sh, lh;
301         struct hostent         *host_ret;
302         _Xgethostbynameparams   host_buf;
303         int                     failed = 0;
304         char                    **h_addr_list;
305
306
307         memset((char*) &host_buf, 0, sizeof(_Xgethostbynameparams));
308         if ((host_ret = _XGethostbyname((char*) hostname, host_buf)) == NULL) {
309                 return 0;
310         }
311
312         // cache the parts of the entry we're
313         // interested in.  We have to do this
314         // since gethostbyname() returns a pointer
315         // to static memory, and since struct hostent's
316         // have pointers in them.
317
318         cache_ptr->addr_length = host_ret->h_length;
319
320         // Copy the list of IP addresses
321         for (h_addr_list = host_ret->h_addr_list; 
322              h_addr_list; 
323              h_addr_list++) {
324
325                 if (! *h_addr_list) {
326                         break;  // no more addresses
327                 }
328
329                 // copy the address
330                 _Tt_string new_addr((const unsigned char *)h_addr_list,
331                                     host_ret->h_length);
332                 // cache it
333                 cache_ptr->addr_list->append(new_addr);
334         }
335
336         return 1;
337 }