5252#endif /* !_WIN32 */
5353
5454// Temporary hack ... dusable new code because it seems to break CI
55- #undef HAVE_RESOLV_H
55+ // #undef HAVE_RESOLV_H
5656
5757#if defined(HAVE_RESOLV_H)
5858#include < resolv.h>
7575static NSMutableDictionary *_hostCache = nil ;
7676static id null = nil ;
7777
78-
7978/*
8079 * Max hostname length in line with RFC 1123
8180 */
8281#define GSMAXHOSTNAMELEN 255
8382
83+ static BOOL
84+ isName (const char *n)
85+ {
86+ if (NULL == n
87+ || (isdigit (n[0 ]) && sscanf (n, " %*d .%*d .%*d .%*d " ) == 4 )
88+ || 0 != strchr (n, ' :' ))
89+ {
90+ return NO ;
91+ }
92+ return YES ;
93+ }
94+
95+ static const char *
96+ getName (NSString *str)
97+ {
98+ const char *n = [str UTF8String ];
99+
100+ if (isName (n))
101+ {
102+ return n;
103+ }
104+ return NULL ;
105+ }
106+
84107/* *
85108 * Return the current host name ... may change if we are using dhcp etc
86109 */
@@ -195,6 +218,74 @@ - (id) _initWithAddress: (NSString*)name
195218
196219#if defined(HAVE_GETADDRINFO) && defined(HAVE_RESOLV_H)
197220
221+ static unsigned
222+ getCNames (NSString *host, NSMutableSet *cnames)
223+ {
224+ unsigned char response[NS_PACKETSZ];
225+ extern int h_errno;
226+ const char *name;
227+ unsigned added = 0 ;
228+ int len;
229+
230+ if ([cnames member: host] != nil )
231+ {
232+ return 0 ;
233+ }
234+ if (NULL == (name = getName (host)))
235+ {
236+ return 0 ;
237+ }
238+
239+ /* Perform DNS query for CNAME records so that we can get
240+ * any name pointed to by this one.
241+ */
242+ len = res_query (name, ns_c_in, ns_t_cname, response, sizeof (response));
243+ if (len < 0 )
244+ {
245+ if (h_errno != NO_DATA)
246+ {
247+ herror (name);
248+ }
249+ }
250+ else
251+ {
252+ ns_msg msg;
253+ int count;
254+ int i;
255+
256+ ns_initparse (response, len, &msg);
257+ count = ns_msg_count (msg, ns_s_an);
258+ for (i = 0 ; i < count; i++)
259+ {
260+ ns_rr rr;
261+
262+ ns_parserr (&msg, ns_s_an, i, &rr);
263+
264+ // Check if the record is a CNAME
265+ if (ns_rr_type (rr) == ns_t_cname)
266+ {
267+ char cname[NS_MAXDNAME];
268+
269+ if (ns_name_uncompress (ns_msg_base (msg), ns_msg_end (msg),
270+ ns_rr_rdata (rr), cname, sizeof (cname)) < 0 )
271+ {
272+ fprintf (stderr, " Failed to uncompress CNAME\n " );
273+ continue ;
274+ }
275+ NSDebugFLLog (@" NSHost" , @" res_query for '%@ ' found '%s '" ,
276+ host, cname);
277+ [cnames addObject: [NSString stringWithUTF8String: cname]];
278+ added++;
279+ }
280+ }
281+ }
282+ if (0 == added)
283+ {
284+ NSDebugFLLog (@" NSHost" , @" res_query for '%@ ' found no CNAMEs" , host);
285+ }
286+ return added;
287+ }
288+
198289- (id ) _initWithKey : (NSString *)key
199290{
200291 ENTER_POOL
@@ -205,6 +296,7 @@ - (id) _initWithKey: (NSString*)key
205296 struct addrinfo hints;
206297 struct addrinfo *tmp;
207298 int err;
299+ BOOL keyIsName;
208300
209301 memset (&hints, ' \0 ' , sizeof (hints));
210302 hints.ai_flags = AI_CANONNAME;
@@ -214,19 +306,27 @@ - (id) _initWithKey: (NSString*)key
214306 {
215307 [addresses unionSet: [hostClass _localAddresses ]];
216308 ptr = " localhost" ;
309+ keyIsName = NO ;
310+ }
311+ else
312+ {
313+ getCNames (key, names);
314+ ptr = [key UTF8String ];
315+ keyIsName = isName (ptr);
217316 }
218317
219318 err = getaddrinfo (ptr, 0 , &hints, &entry);
220319 if (err)
221320 {
222- fprintf (stderr, " getaddrinfo failed: %s \n " , gai_strerror (err));
321+ fprintf (stderr, " getaddrinfo ' %s ' failed: %s \n " , ptr , gai_strerror (err));
223322 entry = NULL ;
224323 }
225324 for (tmp = entry; tmp != NULL ; tmp = tmp->ai_next )
226325 {
227326 char ipstr[INET6_ADDRSTRLEN];
228327 char host[NI_MAXHOST];
229328 void *addr;
329+ NSString *a;
230330
231331#pragma clang diagnostic push
232332#pragma clang diagnostic ignored "-Wcast-align"
@@ -246,85 +346,71 @@ - (id) _initWithKey: (NSString*)key
246346 }
247347#pragma clang diagnostic pop
248348 inet_ntop (tmp->ai_family , addr, ipstr, sizeof (ipstr));
249- [addresses addObject: [NSString stringWithUTF8String: ipstr]];
250-
251- /* Possibly a reverse lookup of the address will give us a different
252- * result to our key (if the key was an address or an alias) so we
253- * might be able to get a new name for the host.
254- */
255- if (getnameinfo (tmp->ai_addr , tmp->ai_addrlen , host, sizeof (host),
256- NULL , 0 , NI_NAMEREQD) == 0 )
257- {
258- [names addObject: [NSString stringWithUTF8String: host]];
259- }
260-
261- /* If we have a conaonical name for the host, use it.
262- */
263- if (tmp->ai_canonname && *tmp->ai_canonname )
349+ a = [NSString stringWithUTF8String: ipstr];
350+ if (nil == [addresses member: a])
264351 {
265- unsigned char response[NS_PACKETSZ];
266- extern int h_errno;
267- ns_msg msg;
268- int count;
269- int len;
270- int i;
271- NSString *n;
272-
273- n = [NSString stringWithUTF8String: tmp->ai_canonname];
274- [names addObject: n];
275-
276- /* Perform DNS query for CNAME records so that we can get
277- * any name pointed to by this one.
278- */
279- len = res_query (tmp->ai_canonname , ns_c_in, ns_t_cname,
280- response, sizeof (response));
281- if (len < 0 )
352+ [addresses addObject: a];
353+
354+ /* Possibly a reverse lookup of the address will give us a different
355+ * result to our key (if the key was an address or an alias) so we
356+ * might be able to get a new name for the host.
357+ */
358+ if (getnameinfo (tmp->ai_addr , tmp->ai_addrlen , host, sizeof (host),
359+ NULL , 0 , NI_NAMEREQD) == 0 )
282360 {
283- if (h_errno != NO_DATA)
361+ NSString *n = [NSString stringWithUTF8String: host];
362+
363+ NSDebugMLog (@" NSHost" , @" getnameinfo for '%s ' found '%s '" ,
364+ ipstr, host);
365+ if (nil == [names member: n])
284366 {
285- herror (" res_query" );
367+ [names addObject: n];
368+ getCNames (n, names);
286369 }
287- continue ;
288370 }
289-
290- ns_initparse (response, len, &msg);
291- count = ns_msg_count (msg, ns_s_an);
292- for (i = 0 ; i < count; i++)
371+ else
293372 {
294- ns_rr rr;
373+ NSDebugMLog (@" NSHost" , @" getnameinfo for '%s ' found nothing" ,
374+ ipstr);
375+ *host = ' \0 ' ;
376+ }
295377
296- ns_parserr (&msg, ns_s_an, i, &rr);
378+ /* If we have a canonical name for the host, use it.
379+ */
380+ if (tmp->ai_canonname && *tmp->ai_canonname
381+ && strcmp (tmp->ai_canonname , host) != 0 )
382+ {
383+ NSString *n = [NSString stringWithUTF8String: tmp->ai_canonname];
297384
298- // Check if the record is a CNAME
299- if (ns_rr_type (rr) == ns_t_cname)
385+ if (nil == [names member: n])
300386 {
301- char cname[NS_MAXDNAME];
302-
303- if (ns_name_uncompress (ns_msg_base (msg), ns_msg_end (msg),
304- ns_rr_rdata (rr), cname, sizeof (cname)) < 0 )
305- {
306- fprintf (stderr, " Failed to uncompress CNAME\n " );
307- continue ;
308- }
309- [names addObject: [NSString stringWithUTF8String: cname]];
387+ [names addObject: n];
388+ getCNames (n, names);
310389 }
311390 }
312391 }
313392 }
314393 if (entry)
315394 {
316- if (nil == [addresses member: key])
317- {
318- /* The key was not an address ... so it must be a host name
319- */
320- [names addObject: key];
321- }
322395 freeaddrinfo (entry);
323396 }
324397 if ([names count ] || [addresses count ])
325398 {
326- _names = [names copy ];
327399 _addresses = [addresses copy ];
400+ if (keyIsName)
401+ {
402+ [names addObject: key];
403+ }
404+ if ([names count ])
405+ {
406+ _names = [names copy ];
407+ }
408+ else
409+ {
410+ /* No names, so we duplicate addresses as names
411+ */
412+ _names = [_addresses copy ];
413+ }
328414 }
329415 else
330416 {
@@ -490,7 +576,6 @@ + (NSHost*) currentHost
490576+ (NSHost *) hostWithName : (NSString *)name
491577{
492578 NSHost *host = nil ;
493- const char *n;
494579
495580 if (name == nil )
496581 {
@@ -506,9 +591,7 @@ + (NSHost*) hostWithName: (NSString*)name
506591 /* If this looks like an address rather than a host name ...
507592 * call the correct method instead of this one.
508593 */
509- n = [name UTF8String ];
510- if ((isdigit (n[0 ]) && sscanf (n, " %*d .%*d .%*d .%*d " ) == 4 )
511- || 0 != strchr (n, ' :' ))
594+ if (NULL == getName (name))
512595 {
513596 return [self hostWithAddress: name];
514597 }
@@ -536,7 +619,7 @@ + (NSHost*) hostWithName: (NSString*)name
536619 {
537620 struct hostent *h;
538621
539- h = gethostbyname ((char *)n );
622+ h = gethostbyname ((char *)[name UTF8String ] );
540623 if (0 == h)
541624 {
542625 if ([name isEqualToString: myHostName ()] == YES )
0 commit comments