Watt-32 tcp/ip  2.2 dev-rel.10
gethost6.c
Go to the documentation of this file.
1 
6 /*
7  * Copyright (c) 1997-2002 Gisle Vanem <gvanem@yahoo.no>
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  * must display the following acknowledgement:
19  * This product includes software developed by Gisle Vanem
20  * Bergen, Norway.
21  *
22  * THIS SOFTWARE IS PROVIDED BY ME (Gisle Vanem) AND CONTRIBUTORS ``AS IS''
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED. IN NO EVENT SHALL I OR CONTRIBUTORS BE LIABLE FOR ANY
26  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  *
34  * 03.Aug 2002 (GV) - Created
35  */
36 
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <ctype.h>
41 #include <time.h>
42 #include <netdb.h>
43 #include <arpa/nameser.h>
44 #include <arpa/inet.h>
45 #include <netinet/in.h>
46 #include <resolv.h>
47 
48 #include "wattcp.h"
49 #include "strings.h"
50 #include "misc.h"
51 #include "run.h"
52 #include "timer.h"
53 #include "language.h"
54 #include "ip6_out.h"
55 #include "pcconfig.h"
56 #include "pctcp.h"
57 #include "netaddr.h"
58 #include "bsdname.h"
59 #include "bsddbug.h"
60 #include "pcdns.h"
61 #include "get_xby.h"
62 
63 /* \if USE_IPV6 */
64 #if defined(USE_BSD_API) && defined(USE_IPV6) /* whole file */
65 
66 static char *host6fname = NULL;
67 static FILE *host6file = NULL;
68 static BOOL hostClose = FALSE;
69 static struct _hostent6 *host0 = NULL;
70 
71 static BOOL did_lookup = FALSE; /* tried a DNS lookup */
72 static BOOL is_addr = FALSE; /* name is simply an IPv6 address */
73 
74 static BOOL gethostbyname6_internal (const char *name,
75  const char **alias,
76  struct _hostent6 *ret);
77 
78 static BOOL gethostbyaddr6_internal (const char *addr,
79  struct _hostent6 *ret);
80 
81 static struct hostent *fill_hostent6 (const struct _hostent6 *h);
82 
83 static struct _hostent6 *add_hostent6 (struct _hostent6 *h,
84  const char *name,
85  const char *cname,
86  const void *addr_list,
87  const void *addr,
88  DWORD ttl);
89 
90 static void _endhostent6 (void)
91 {
92  endhostent6();
93 }
94 
95 void W32_CALL ReadHosts6File (const char *fname)
96 {
97  static BOOL been_here = FALSE;
98 
99  if (!fname || !*fname)
100  return;
101 
102  if (been_here) /* loading multiple hosts6 files */
103  {
104  free (host6fname);
105  CloseHost6File();
106  }
107 
108  host6fname = strdup (fname);
109  if (!host6fname)
110  return;
111 
112  sethostent6 (1);
113  if (!host6file)
114  return;
115 
116  been_here = TRUE;
117 
118  while (1)
119  {
120  struct hostent *h = gethostent6();
121  struct _hostent6 *h2;
122  int i;
123 
124  if (!h)
125  break;
126 
127  h2 = calloc (sizeof(*h2), 1);
128  if (!h2)
129  {
130  outs (host6fname);
131  outsnl (_LANG(" too big!"));
132  break;
133  }
134  for (i = 0; h->h_aliases[i]; i++)
135  h2->h_aliases[i] = strdup (h->h_aliases[i]);
136  memcpy (&h2->h_address[0], h->h_addr_list[0], sizeof(h2->h_address[0]));
137  h2->h_num_addr = 1;
138  h2->h_name = strdup (h->h_name);
139  h2->h_timeout = 0; /* don't expire */
140  h2->h_real_ttl = 0;
141  if (!h2->h_name)
142  break;
143 
144  h2->h_next = host0;
145  host0 = h2;
146  }
147 
148 #if 0 /* test !! */
149  {
150  const struct _hostent6 *h;
151  int i;
152 
153  printf ("\n%s entries:\n", host6fname);
154  for (h = host0; h; h = h->h_next)
155  {
156  printf ("address %-40.40s name %-30.30s Aliases:",
157  _inet6_ntoa(&h->h_address[0]), h->h_name);
158  for (i = 0; h->h_aliases[i]; i++)
159  printf (" %s,", h->h_aliases[i]);
160  puts ("");
161  }
162  fflush (stdout);
163  }
164 #endif
165 
166  rewind (host6file);
167  RUNDOWN_ADD (_endhostent6, 256);
168 }
169 
170 const char * W32_CALL GetHosts6File (void)
171 {
172  return (host6fname);
173 }
174 
175 /*
176  * To prevent running out of file-handles, one should close the
177  * 'hosts' file before spawning a new shell.
178  */
179 void W32_CALL CloseHost6File (void)
180 {
181  if (!host6file)
182  return;
183  FCLOSE (host6file);
184  host6file = NULL;
185 }
186 
187 void W32_CALL ReopenHost6File (void)
188 {
189  ReadHosts6File (host6fname);
190 }
191 
192 /*
193  * Return the next (non-commented) line from the host6-file
194  * Format is:
195  * IPv6-address [=] host-name [alias..] {\n | # ..}
196  */
197 struct hostent * W32_CALL gethostent6 (void)
198 {
199  struct _hostent6 h;
200  char *tok, *ip, *name, *alias, *tok_buf = NULL;
201  char buf [2*MAX_HOSTLEN];
202  int i;
203 
204  if (!netdb_init() || !host6file)
205  {
206  h_errno = NO_RECOVERY;
207  return (NULL);
208  }
209 
210  memset (&h, 0, sizeof(h));
211 
212  while (1)
213  {
214  if (!fgets(buf,sizeof(buf),host6file))
215  return (NULL);
216 
217  tok = strltrim (buf);
218  if (*tok == '#' || *tok == ';' || *tok == '\n')
219  continue;
220 
221  ip = strtok_r (tok, " \t", &tok_buf);
222  name = strtok_r (NULL, " \t\n", &tok_buf);
223  if (ip && name && inet_pton(AF_INET6, ip, &h.h_address[0]) == 1)
224  break;
225  }
226 
227  if (hostClose)
228  endhostent6();
229 
230  h.h_num_addr = 1;
231  h.h_name = name;
232  alias = strtok_r (NULL, " \t\n", &tok_buf);
233 
234  for (i = 0; alias && i < MAX_HOST_ALIASES; i++)
235  {
236  static char aliases [MAX_HOST_ALIASES][MAX_HOSTLEN];
237 
238  if (*alias == '#' || *alias == ';')
239  break;
240 
241  h.h_aliases[i] = _strlcpy (aliases[i], alias, sizeof(aliases[i]));
242  alias = strtok_r (NULL, " \t\n", &tok_buf);
243  }
244  return fill_hostent6 (&h);
245 }
246 
247 /*------------------------------------------------------------------*/
248 
249 struct hostent * W32_CALL gethostbyname6 (const char *name)
250 {
251  struct _hostent6 h;
252  const char *alias;
253 
254  SOCK_DEBUGF (("\ngethostbyname6: `%s'", name));
255  is_addr = FALSE;
256 
257  if (gethostbyname6_internal(name, &alias, &h))
258  {
259 #if defined(USE_DEBUG)
260  int i;
261  for (i = 0; i < h.h_num_addr; i++)
262  SOCK_DEBUGF ((" %s,", _inet6_ntoa(&h.h_address[i])));
263 
264  if (!did_lookup)
265  SOCK_DEBUGF ((" %s", is_addr ? "" :
266  h.h_timeout ? "cached" :
267  "hosts6-file"));
268  if (alias)
269  SOCK_DEBUGF ((" (alias %s)", alias));
270 #endif
271  return fill_hostent6 (&h);
272  }
273 
274  SOCK_DEBUGF ((", failed (%s)", did_lookup ? dom_strerror(dom_errno) :
275  hstrerror(h_errno)));
276  return (NULL);
277 }
278 
279 static BOOL gethostbyname6_internal (const char *name, const char **alias,
280  struct _hostent6 *ret)
281 {
282  static char our_name[MAX_HOSTLEN];
283  struct in6_addr addr;
284  struct _hostent6 *h;
285  time_t now;
286  int rc;
287 
288  h_errno = HOST_NOT_FOUND;
289  did_lookup = FALSE;
290 
291  _resolve_exit = _resolve_timeout = 0;
292  memset (ret, 0, sizeof(*ret));
293  *alias = NULL;
294 
295  if (!netdb_init() || !name)
296  {
297  h_errno = NO_RECOVERY;
298  return (FALSE);
299  }
300 
301  if (inet_pton(AF_INET6,name,&addr) == 1)
302  {
303  ret->h_name = (char*) name;
304  memcpy (&ret->h_address[0], &addr, sizeof(ret->h_address[0]));
305  is_addr = TRUE;
306  return (TRUE);
307  }
308 
309  now = time (NULL);
310 
311  for (h = host0; h; h = h->h_next)
312  {
313  int i;
314 
315  if (h->h_name && !stricmp(h->h_name,name))
316  {
317  /* if cached entry expired, do DNS lookup
318  */
319  if (h->h_timeout && now > h->h_timeout)
320  goto expired;
321 
322  if (IN6_ARE_ADDR_EQUAL(&h->h_address[0], &in6addr_all_1))
323  return (FALSE);
324 
325  *ret = *h;
326  return (TRUE);
327  }
328  for (i = 0; i < MAX_HOST_ALIASES && h->h_aliases[i]; i++)
329  if (!stricmp(name,h->h_aliases[i]))
330  {
331  if (h->h_timeout && now > h->h_timeout)
332  goto expired;
333 
334  if (IN6_ARE_ADDR_EQUAL(&h->h_address[0], &in6addr_all_1))
335  return (FALSE);
336  *alias = h->h_aliases[i];
337  *ret = *h;
338  return (TRUE);
339  }
340  }
341 
342  /* Not found in linked list (hosts6 file or cache). Check name
343  * against our own host-name (short-name or FQDN)
344  */
345  if (hostname[0] && !stricmp(name,hostname))
346  {
347  memcpy (&ret->h_address[0], &in6addr_my_ip, sizeof(ret->h_address[0]));
348  ret->h_num_addr = 1;
349  ret->h_name = hostname;
350  return (TRUE);
351  }
352 
353  if (!gethostname(our_name,sizeof(our_name)) && !stricmp(name,our_name))
354  {
355  memcpy (&ret->h_address[0], &in6addr_my_ip, sizeof(ret->h_address[0]));
356  ret->h_num_addr = 1;
357  ret->h_name = our_name;
358  return (TRUE);
359  }
360 
361 expired:
362 
363  /* do a full DNS lookup
364  */
365  rc = resolve_ip6 (name, &addr);
366  did_lookup = TRUE;
367 
368  if (_resolve_exit || /* interrupted by _resolve_hook() */
369  _resolve_timeout) /* timed out resolving */
370  return (FALSE);
371 
372  if (rc) /* successfully resolved */
373  {
374  h = add_hostent6 (h, name, dom_cname, &dom_a6list, &addr, dom_ttl);
375  return (h ? *ret = *h, TRUE : FALSE);
376  }
377 
378  /* Add the IP to the list even if DNS failed (but not interrupted by
379  * _resolve_hook() or timedout). Thus the next call to gethostbyxxx6()
380  * will return immediately.
381  */
382  add_hostent6 (h, name, NULL, NULL, &in6addr_all_1, netdbCacheLife);
383  return (FALSE);
384 }
385 
386 /*------------------------------------------------------------------*/
387 
388 void W32_CALL sethostent6 (int stayopen)
389 {
390  hostClose = (stayopen == 0);
391  if (!netdb_init() || !host6fname)
392  return;
393 
394  if (!host6file)
395  FOPEN_TXT (host6file, host6fname);
396  else rewind (host6file);
397 }
398 
399 /*------------------------------------------------------------------*/
400 
401 void W32_CALL endhostent6 (void)
402 {
403  struct _hostent6 *h, *next;
404 
405  if (_watt_fatal_error)
406  return;
407 
408  if (host6fname)
409  free (host6fname);
410  host6fname = NULL;
411  CloseHost6File();
412 
413  for (h = host0; h; h = next)
414  {
415  int i;
416  for (i = 0; h->h_aliases[i]; i++)
417  free (h->h_aliases[i]);
418  next = h->h_next;
419  free (h->h_name);
420  free (h);
421  }
422  host0 = NULL;
423  hostClose = TRUE;
424 }
425 
426 /*
427  * Return a 'struct hostent *' for an IPv6 address.
428  */
429 struct hostent * W32_CALL gethostbyaddr6 (const void *addr)
430 {
431  struct _hostent6 h;
432 
433  SOCK_DEBUGF (("\ngethostbyaddr6: %s", _inet6_ntoa(addr)));
434 
435  if (gethostbyaddr6_internal (addr, &h))
436  {
437  SOCK_DEBUGF ((" `%s'", h.h_name));
438  if (!did_lookup)
439  SOCK_DEBUGF ((", %s", h.h_timeout ? "cached" : "hosts-file"));
440  return fill_hostent6 (&h);
441  }
442 
443  SOCK_DEBUGF ((", failed (%s) ", did_lookup ? dom_strerror(dom_errno) :
444  hstrerror(h_errno)));
445  return (NULL);
446 }
447 
448 static BOOL gethostbyaddr6_internal (const char *addr, struct _hostent6 *ret)
449 {
450  static char name [MAX_HOSTLEN];
451  struct _hostent6 *h;
452  ip6_address ip;
453  time_t now;
454  int rc;
455 
456  h_errno = HOST_NOT_FOUND;
457  did_lookup = FALSE;
458  _resolve_exit = _resolve_timeout = 0;
459  memset (ret, 0, sizeof(*ret));
460  memcpy (&ip, addr, sizeof(ip));
461 
462  if (!netdb_init())
463  {
464  h_errno = NO_RECOVERY;
465  return (FALSE);
466  }
467 
468  if ((IN6_ARE_ADDR_EQUAL(&ip, &in6addr_any) || /* :: -> in6addr_myip */
469  IN6_IS_ADDR_LINKLOCAL(&ip)) && /* FE8/119 */
470  gethostname(name,sizeof(name)) == 0)
471  {
472  memcpy (&ret->h_address[0], &in6addr_my_ip, sizeof(ret->h_address[0]));
473  ret->h_num_addr = 1;
474  ret->h_name = name;
475  return (TRUE);
476  }
477 
478  now = time (NULL);
479 
480  for (h = host0; h; h = h->h_next)
483  if (IN6_ARE_ADDR_EQUAL(&h->h_address[0],&ip))
484  {
485  /* if cached entry expired, do a new reverse lookup
486  */
487  if (h->h_timeout && now > h->h_timeout)
488  break;
489 
490  *ret = *h;
491  return (TRUE);
492  }
493 
494  /* do a reverse IPv6 lookup
495  */
496  did_lookup = TRUE;
497  rc = reverse_resolve_ip6 (&ip, name, sizeof(name));
498 
499  /* interrupted or timedout
500  */
501  if (!rc && (_resolve_exit || _resolve_timeout))
502  return (FALSE);
503 
504  if (rc) /* successfully resolved */
505  {
506  h = add_hostent6 (h, name, NULL, NULL, &ip, dom_ttl);
508  return (h ? *ret = *h, TRUE : FALSE);
509  }
510 
511  /* Add the IP to the list even if reverse lookup failed and not
512  * interrupted by _resolve_hook(). Thus the next call to gethostbyxx()
513  * will return immediately.
514  */
515  add_hostent6 (h, "*unknown*", NULL, NULL, &ip, 0UL);
516  return (FALSE);
517 }
518 
519 /*
520  * Return a 'struct hostent*' from an internal 'struct _hostent6*'
521  */
522 static struct hostent *fill_hostent6 (const struct _hostent6 *h)
523 {
524  static struct hostent ret;
525  static struct in6_addr addr [MAX_ADDRESSES+1];
526  static char *list [MAX_ADDRESSES+1];
527  static char hostname [MAX_HOSTLEN];
528  static char *aliases [MAX_HOST_ALIASES+1];
529  int i;
530 
531  if (!h->h_name)
532  return (NULL);
533 
534  memset (&addr, 0, sizeof(addr));
535  memcpy (&aliases, h->h_aliases, sizeof(aliases));
536 
537  for (i = 0; i < h->h_num_addr && i < MAX_ADDRESSES; i++)
538  {
539  memcpy (&addr[i].s6_addr, &h->h_address[i], sizeof(addr[i].s6_addr));
540  list[i] = (char*) &addr[i];
541  }
542 
543  list[i] = NULL;
544  ret.h_addr_list = list;
545  ret.h_name = _strlcpy (hostname, h->h_name, sizeof(hostname));
546  ret.h_aliases = aliases;
547  ret.h_addrtype = AF_INET6;
548  ret.h_length = sizeof (addr[0].s6_addr);
549  h_errno = NETDB_SUCCESS;
550  return (&ret);
551 }
552 
553 /*
554  * Modify an expired cached entry or add a new node to
555  * the linked list. Not used for entries in hosts-file.
556  */
557 static struct _hostent6 *add_hostent6 (
558  struct _hostent6 *h,
559  const char *name,
560  const char *cname, /* Canonical name (CNAME) */
561  const void *alist, /* List of alternate addr */
562  const void *addr, /* Main IP6-address */
563  DWORD ttl) /* Time-to-live (sec) */
564 {
565  DWORD real_ttl = ttl;
566  int i;
567 
568  ttl = min (ttl, netdbCacheLife); /* clamp the TTL */
569 
570  if (h) /* reuse expired entry */
571  {
572  if (h->h_name)
573  free (h->h_name);
574  if (h->h_aliases[0])
575  free (h->h_aliases[0]); /* !! max 1 alias */
576  memset (&h->h_address[1], 0, /* clear old addresses */
577  sizeof(h->h_address)-sizeof(ip6_address));
578  h->h_aliases[0] = NULL;
579  }
580  else /* create a new node */
581  {
582  h = calloc (sizeof(*h), 1);
583  if (h)
584  {
585  h->h_next = host0;
586  host0 = h;
587  }
588  }
589 
590  if (!cname || !cname[0])
591  cname = NULL;
592 
593  if (addr != &in6addr_all_1)
594  SOCK_DEBUGF ((", CNAME %s, ttl %lus,",
595  cname ? cname : "<none>", real_ttl));
596  if (h)
597  {
598  const ip6_address *a6list = (const ip6_address*) alist;
599 
600  h->h_timeout = ttl ? time (NULL) + ttl : 0;
601  h->h_real_ttl = real_ttl;
602  h->h_num_addr = 1;
603  memcpy (&h->h_address[0], addr, sizeof(h->h_address[0]));
604  for (i = 0; a6list && !IN6_IS_ADDR_UNSPECIFIED(a6list[i]); i++)
605  {
606  memcpy (&h->h_address[i+1], a6list[i], sizeof(ip6_address));
607  h->h_num_addr++;
608  }
609  if (cname) /* swap name with CNAME */
610  {
611  h->h_name = strdup (cname);
612  h->h_aliases[0] = strdup (name); /* !! only allow 1 alias */
613  }
614  else
615  h->h_name = strdup (name);
616  }
617  else
618  SOCK_DEBUGF ((" ENOMEM"));
619 
620  return (h);
621 }
622 
623 #if defined(USE_DEBUG)
624 /*
625  * Reverse the 'host0' list before printing it (a bit nicer and intuitive).
626  * I.e. on same order the host-names where put in the list by add_hostent().
627  */
628 static BOOL ReverseHosts6List (void)
629 {
630  struct _hostent6 *h, **list;
631  int i, num_total, num_dynamic;
632 
633  for (h = host0, num_total = num_dynamic = 0; h; h = h->h_next)
634  {
635  num_total++;
636  if (h->h_timeout > 0)
637  num_dynamic++;
638  }
639  if (num_total == 0 || num_dynamic == 0)
640  return (FALSE);
641 
642  list = malloc (num_total * sizeof(*list));
643  if (!list)
644  return (FALSE);
645 
646  for (h = host0, i = 0; h; h = h->h_next)
647  list[i++] = h;
648 
649  for (host0 = NULL, i = 0; i < num_total; i++)
650  {
651  h = list[i];
652  h->h_next = host0;
653  host0 = h;
654  }
655  free (list);
656  return (TRUE);
657 }
658 
659 void W32_CALL DumpHosts6Cache (void)
660 {
661  struct _hostent6 *h;
662  time_t now;
663 
664  if (!ReverseHosts6List())
665  return;
666 
667  SOCK_DEBUGF ((" \n\nCached IPv6 hosts: "
668  "Address TTL Alias\n"));
669  now = time (NULL);
670 
671  for (h = host0; h; h = h->h_next)
672  {
673  const char *addr;
674  int i;
675  long dT;
676 
677  if (h->h_real_ttl == 0) /* skip static records */
678  continue;
679 
680  dT = (long)(h->h_timeout - now);
681  if (IN6_ARE_ADDR_EQUAL(&h->h_address[0], &in6addr_all_1))
682  addr = "::";
683  else addr = _inet6_ntoa (&h->h_address[0]);
684 
685  SOCK_DEBUGF ((" %-50s %-40s %8s ", h->h_name, addr,
686  dT < 0 ? "timedout" : hms_str(h->h_real_ttl)));
687 
688  for (i = 0; h->h_aliases[i]; i++)
689  SOCK_DEBUGF (("%s ", h->h_aliases[i]));
690  if (i == 0)
691  SOCK_DEBUGF (("<none>\n"));
692  else SOCK_DEBUGF ((" \n"));
693 
694  for (i = 1; i < h->h_num_addr; i++)
695  SOCK_DEBUGF (("%62s %s\n", "", _inet6_ntoa(&h->h_address[i])));
696 
697  }
698 }
699 #endif /* USE_DEBUG */
700 
701 
702 /*------------------------------------------------------------------*/
703 
704 #ifdef TEST_PROG
705 
706 #include "pcdbug.h"
707 #include "sock_ini.h"
708 
709 /*
710  * Print list of hosts unsorted.
711  */
712 static void print_hosts (void)
713 {
714  const struct _hostent6 *h;
715 
716  for (h = host0; h; h = h->h_next)
717  {
718  int i;
719  printf ("%-40s -> %s; Aliases:", _inet6_ntoa(&h->h_address), h->h_name);
720 
721  for (i = 0; h->h_aliases[i]; i++)
722  printf (" %s,", h->h_aliases[i]);
723  puts ("");
724  }
725  fflush (stdout);
726 }
727 
728 int main (void)
729 {
730  dbug_init();
731  sock_init();
732  print_hosts();
733  return (0);
734 }
735 #endif /* TEST_PROG */
736 #endif /* USE_BSD_API && USE_IPV6 */
737 /* \endif */
738 
char * strltrim(const char *s)
Return pointer to first non-blank (space/tab) in a string.
Definition: strings.c:243
Definition: netdb.h:102
Core definitions.
char * _strlcpy(char *dst, const char *src, size_t len)
Similar to strncpy(), but always returns 'dst' with 0-termination.
Definition: strings.c:226
Definition: in.h:153
Definition: ip.h:67
int W32_CALL inet_pton(int af, const char *src, void *dst)
Convert from presentation format (which usually means ASCII printable) to network format (which is us...
Definition: presaddr.c:66
char hostname[MAX_HOSTLEN+1]
Our configured hostname.
Definition: pctcp.c:59
const char *W32_CALL dom_strerror(int err)
Return text for error code (dom_errno).
Definition: pcdns.c:746
BOOL _watt_fatal_error
Definition: misc.c:60
const char * _inet6_ntoa(const void *ip)
Convert an IPv6-address 'ip' into a string.
Definition: netaddr.c:401
int netdb_init(void)
Called from most <netdb.h> functions in case watt_sock_init() wasn't called first to initialise things...
Definition: pcconfig.c:1215
static BOOL gethostbyaddr6_internal(const char *addr, struct _hostent6 *ret)
Definition: gethost6.c:448
int main(int argc, char **argv)
Definition: echo.c:223