Watt-32 tcp/ip  2.2 dev-rel.10
pcconfig.c
Go to the documentation of this file.
1 
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <io.h>
9 #include <ctype.h>
10 #include <string.h>
11 #include <limits.h>
12 #include <fcntl.h>
13 #include <arpa/inet.h>
14 
15 #include "copyrigh.h"
16 #include "wattcp.h"
17 #include "strings.h"
18 #include "misc.h"
19 #include "timer.h"
20 #include "language.h"
21 #include "pcdns.h"
22 #include "netaddr.h"
23 #include "bsdname.h"
24 #include "pcqueue.h"
25 #include "pcdbug.h"
26 #include "pcsed.h"
27 #include "pcpkt.h"
28 #include "pctcp.h"
29 #include "pcarp.h"
30 #include "pcrarp.h"
31 #include "pcdhcp.h"
32 #include "pcbootp.h"
33 #include "pcicmp.h"
34 #include "sock_ini.h"
35 #include "ip4_frag.h"
36 #include "ip4_out.h"
37 #include "ip6_out.h"
38 #include "loopback.h"
39 #include "get_xby.h"
40 #include "printk.h"
41 #include "profile.h"
42 #include "pcconfig.h"
43 
44 #if defined(USE_IPV6)
45 #include "pcicmp6.h"
46 #include "teredo64.h"
47 #endif
48 
49 #if (DOSX & DJGPP)
50  #include <crt0.h>
51 #endif
52 
53 #if (DOSX & PHARLAP)
54  #include <hw386.h>
55 #endif
56 
57 #if defined(__BORLANDC__)
58  #pragma warn -pro
59 #endif
60 
61 
62 int debug_on = 0; /* general debug level */
63 int ctrace_on = 0; /* tracing; on/off (High-C only) */
64 int sock_delay = 30;
65 int sock_inactive = 0; /* defaults to forever */
66 int sock_data_timeout = 0; /* timeout sending no data (forever) */
67 WORD multihomes = 0; /* We have more than 1 IP-addresses */
68 BOOL dynamic_host = 0; /* Reverse resolve assigned IP to true FQDN */
69 int stkwalk_details = 1; /* Win: simple (1) or detailed(2) stack-trace. */
70  /* Effective only with USE_STACKWALKER. */
71 int fortify_fail_rate = 0; /* The fail-rate for Fortify mallocer. */
72  /* Effective only with USE_FORTIFY. */
73 
74 DWORD cookies [MAX_COOKIES];
75 WORD last_cookie = 0;
76 
77 static void deprecated_key (const char *old_key, const char *new_key);
78 static void W32_CALL keyword_not_found (const char *key, const char *value);
79 
80 void (W32_CALL *print_hook) (const char*) = NULL;
81 void (W32_CALL *usr_init) (const char*, const char*) = keyword_not_found;
82 
85 void (W32_CALL *usr_post_init) (void) = NULL;
86 
87 static char *config_name = (char*) "WATTCP.CFG"; /* name of config file */
88 static char *current_file = NULL;
89 static UINT current_line = 0;
90 static BOOL got_eol = FALSE; /* got end-of-line in 'current_line' */
91 
92 static const char *environ_names[] = {
93  "WATTCP.CFG", /* pointer to config-file */
94  "WATTCP_CFG" /* ditto, for bash */
95  };
96 
97 enum ParseMode {
98  ModeKeyword = 0,
99  ModeValue,
100  ModeComment
101  };
102 
103 #if defined(USE_DEBUG)
104  #define CONFIG_DBG_MSG(lvl, args) \
105  do { \
106  if (debug_on >= lvl) { \
107  UINT line = got_eol ? current_line : current_line+1; \
108  if (current_file) \
109  (*_printf) ("%s (%u): ", current_file, line); \
110  else (*_printf) ("CONFIG: "); \
111  (*_printf) args; \
112  fflush (stdout); \
113  } \
114  } while (0)
115 
116  static const char *type_name (int type)
117  {
118  return (type == ARG_ATOI ? "ATOI " :
119  type == ARG_ATOB ? "ATOB " :
120  type == ARG_ATOW ? "ATOW " :
121  type == ARG_ATOIP ? "ATOIP " :
122  type == ARG_ATOX_B ? "ATOX_B " :
123  type == ARG_ATOX_W ? "ATOX_W " :
124  type == ARG_FUNC ? "FUNC " :
125  type == ARG_RESOLVE ? "RESOLVE" :
126  type == ARG_STRDUP ? "STRDUP " :
127  type == ARG_STRCPY ? "STRCPY " : "??");
128  }
129 
130  #define RANGE_CHECK(val,low,high) \
131  do { \
132  if (((val) < (low)) || ((val) > (high))) \
133  CONFIG_DBG_MSG (0, ("Value %ld exceedes range [%d - %d]\n", \
134  val, low, high)); \
135  } while (0)
136 #else
137  #define CONFIG_DBG_MSG(lvl, args) ((void)0)
138  #define RANGE_CHECK(val,low,high) ((void)0)
139 #endif
140 
141 
142 #if defined(USE_BSD_API)
143  /*
144  * Since ARG_FUNC handlers expect the default calling-convention
145  * (not W32_CALL), we must call the get_xby.h functions via these.
146  */
147  #define FUNC_TO_W32CALL(func) \
148  static void _##func (const char *fname) { func (fname); }
149  FUNC_TO_W32CALL (ReadHostsFile)
150  FUNC_TO_W32CALL (ReadHosts6File)
151  FUNC_TO_W32CALL (ReadServFile)
152  FUNC_TO_W32CALL (ReadProtoFile)
153  FUNC_TO_W32CALL (ReadNetworksFile)
154  FUNC_TO_W32CALL (InitEthersFile)
155 #endif
156 
157 /*
158  * Set 'debug_on' if not already set before tcp_config() called.
159  */
160 static void set_debug_on (const char *value)
161 {
162  if (debug_on == 0)
163  debug_on = ATOI (value);
164 }
165 
170 static void set_ethip (const char *value)
171 {
172  eth_address eth;
173  const char *trailer = _inet_atoeth (value, &eth);
174  DWORD ip4;
175 
176  if (!trailer)
177  return;
178 
179  ip4 = _inet_addr (trailer);
180 
181  /* Don't add our MAC/IP-address
182  */
183  if (!memcmp (&eth, _eth_real_addr, sizeof(eth)))
184  return;
185 
186  if (!ip4)
187  {
188 #if defined(USE_IPV6)
189  const void *ip6 = _inet6_addr (trailer);
190  if (ip6)
191  icmp6_ncache_insert_fix (ip6, &eth);
192 #endif
193  return;
194  }
195 
196  /* Add IPv4-addr to ARP-cache.
197  */
198  _arp_cache_add (ip4, (const eth_address*)&eth, FALSE);
199 }
200 
201 void _add_server (WORD *counter, DWORD *array, int array_dim, DWORD value)
202 {
203  if (value && *counter < array_dim)
204  {
205  int i, duplicate = 0;
206 
207  for (i = 0; i < *counter; i++)
208  if (array[i] == value)
209  {
210  duplicate = 1;
211  CONSOLE_MSG (3, ("value %lu duplicated in array %p\n", value, array));
212  }
213 
214  if (!duplicate)
215  array [(*counter)++] = value;
216  }
217  if (*counter >= array_dim)
218  CONSOLE_MSG (1, ("array %p to small\n", array));
219 }
220 
231 const char *expand_var_str (const char *str)
232 {
233  static char buf [MAX_PATHLEN+MAX_VALUELEN+1];
234  char env [30];
235  const char *e, *p = strstr (str, "$(");
236  const char *dollar = p;
237  size_t i;
238 
239  if (!p || strlen(p) < 4 || !strchr(p+3,')')) /* minimum "$(x)" */
240  return (str);
241 
242  for (i = 0, p += 2; i < sizeof(env)-1; i++)
243  {
244  if (*p == ')')
245  break;
246  env[i] = *p++;
247  }
248  env[i] = '\0';
249  strupr (env);
250  e = getenv (env);
251  if (!e)
252  {
253  e = env;
254  env[0] = '\0';
255  }
256 
257  i = dollar - str;
258  strncpy (buf, str, i);
259  buf[i] = '\0';
260  strncat (buf, e, sizeof(buf)-1-i);
261  return strcat (buf, p+1);
262 }
263 
264 const char *_w32_ExpandVarStr (const char *str)
265 {
266  return expand_var_str (str);
267 }
268 
273 static void W32_CALL keyword_not_found (const char *key, const char *value)
274 {
275  CONFIG_DBG_MSG (2, ("unhandled key/value: \"%s = %s\"\n", key, value));
276  ARGSUSED (key);
277  ARGSUSED (value);
278 }
279 
285 static BOOL set_value (BOOL is_hex, const char *value, void *arg, int size)
286 {
287  long val = 0;
288  BOOL ok = FALSE;
289  const char *s = value;
290 
291 #if (DOSX)
292  if (is_hex)
293  ok = (sscanf(s,"0x%8lX",&val) == 1 || sscanf(s,"x%8lX",&val) == 1);
294  if (!ok)
295  ok = (sscanf(s,"%10ld",&val) == 1); /* "2147483647"; 10 digits */
296 #else
297  if (is_hex)
298  {
299  int ch, len = 0;
300 
301  if (s[0] == '0' && s[1] == 'x' && strlen(s) >= 4)
302  {
303  len += 2;
304  s += 2;
305  }
306  else if (s[0] == 'x' && strlen(s) >= 3)
307  {
308  len++;
309  s++;
310  }
311 
312  ch = toupper (*s);
313  if (len > 0 && strchr(hex_chars_upper,ch))
314  {
315  val = atox (s-2);
316  if (strlen(s) >= 4)
317  val = (val << 8) + atox (s);
318  if (strlen(s) >= 6)
319  val = (val << 8) + atox (s+2);
320  if (strlen(s) >= 8)
321  val = (val << 8) + atox (s+4);
322  ok = TRUE;
323  }
324  }
325  if (!ok)
326  {
327  val = ATOI (value);
328  ok = TRUE; /* could be unconvertable */
329  }
330 #endif
331 
332  if (!ok)
333  {
334  CONFIG_DBG_MSG (0, ("failed to match `%s' as %sdecimal.\n",
335  s, is_hex ? "hex or " : ""));
336  return (FALSE);
337  }
338 
339  CONFIG_DBG_MSG (4, ("got value %ld/%#lx from `%s'\n",
340  val, val, value));
341  switch (size)
342  {
343  case 1:
344  RANGE_CHECK (val, 0, UCHAR_MAX);
345  *(BYTE*)arg = (BYTE) min (val, UCHAR_MAX);
346  break;
347  case 2:
348 #if (DOSX == 0)
349  RANGE_CHECK (val, INT_MIN, INT_MAX);
350  *(int*)arg = (int) min (max(val,INT_MIN), INT_MAX);
351 #else
352  RANGE_CHECK (val, 0, USHRT_MAX);
353  *(WORD*)arg = (WORD) min (val, USHRT_MAX);
354 #endif
355  break;
356  case 4:
357  *(DWORD*)arg = (DWORD)val;
358  break;
359 
360  default:
361 #if (DOSX)
362  if (!valid_addr(arg,sizeof(int)))
363  {
364  CONFIG_DBG_MSG (0, ("Illegal `arg' addr %" ADDR_FMT "\n", ADDR_CAST(arg)));
365  return (FALSE);
366  }
367 #endif
368  *(int*)arg = val;
369  break;
370  }
371  return (TRUE);
372 }
373 
379 int W32_CALL parse_config_table (const struct config_table *tab,
380  const char *section,
381  const char *name,
382  const char *value)
383 {
384  for ( ; tab && tab->keyword; tab++)
385  {
386  char keyword [MAX_NAMELEN], *p;
387  DWORD host;
388  void *arg;
389 
390  if (section)
391  {
392  if (strlen(section) + strlen(tab->keyword) >= sizeof(keyword))
393  continue;
394  strcpy (keyword, section);
395  strcat (keyword, tab->keyword); /* "SECTION.KEYWORD" */
396  }
397  else
398  _strlcpy (keyword, tab->keyword, sizeof(keyword));
399 
400  if (strcmp(name,keyword))
401  continue;
402 
403  arg = tab->arg_func; /* storage or function to call */
404  if (!arg)
405  {
406  CONFIG_DBG_MSG (2, ("No storage for \"%s\", type %s (%d)\n",
407  keyword, type_name(tab->type), tab->type));
408  return (1);
409  }
410 
411  switch (tab->type)
412  {
413  case ARG_ATOI:
414  set_value (FALSE, value, arg, sizeof(int));
415  break;
416 
417  case ARG_ATOB:
418  set_value (FALSE, value, arg, sizeof(BYTE));
419  break;
420 
421  case ARG_ATOX_B:
422  set_value (TRUE, value, arg, sizeof(BYTE));
423  break;
424 
425  case ARG_ATOW:
426  set_value (FALSE, value, arg, sizeof(WORD));
427  break;
428 
429  case ARG_ATOX_W:
430  set_value (TRUE, value, arg, sizeof(WORD));
431  break;
432 
433  case ARG_ATOX_D:
434  set_value (TRUE, value, arg, sizeof(DWORD));
435  break;
436 
437  case ARG_ATOIP:
438  *(DWORD*)arg = aton (value);
439  break;
440 
441  case ARG_FUNC: /* This only works if 'arg' is __cdecl */
442  (*(void(*)(const char*, size_t))arg) (value, strlen(value));
443  break;
444 
445  case ARG_RESOLVE:
446  host = resolve (value);
447  if (!host && !isaddr(value))
448  {
449  outs (name);
450  outs (_LANG(": Cannot resolve \""));
451  outs (value);
452  outsnl ("\"");
453  }
454  else
455  *(DWORD*)arg = host;
456  break;
457 
458  case ARG_STRDUP:
459  p = strdup (value);
460  if (!p)
461  {
462  outs (_LANG("No memory for \""));
463  outs (name);
464  outsnl ("\"");
465  }
466  else
467  *(char**)arg = p;
468  break;
469 
470  case ARG_STRCPY:
471  _strlcpy ((char*)arg, value, MAX_VALUELEN);
472  break;
473 
474  default:
475 #if defined(USE_DEBUG)
476  fprintf (stderr, "Something wrong in parse_config_table().\n"
477  "Section %s; `%s' = `%s'. type = %s (%d)\n",
478  section, name, value, type_name(tab->type), tab->type);
479  exit (-1);
480 #endif
481  break;
482  }
483 
484  CONSOLE_MSG (3, ("ARG_%s, matched `%s' = `%s'\n",
485  type_name(tab->type), keyword, value));
486  return (1);
487  }
488  return (0);
489 }
490 
491 static void set_my_ip (const char *value)
492 {
493  if (!stricmp(value,"bootp"))
494  _bootp_on = 1;
495  else if (!stricmp(value,"dhcp"))
496  _dhcp_on = 1;
497  else if (!stricmp(value,"rarp"))
498  _rarp_on = 1;
499  else my_ip_addr = resolve (value);
500 }
501 
502 static void set_hostname (const char *value)
503 {
504  _strlcpy (hostname, value, sizeof(hostname));
505 }
506 
507 static void set_gateway (const char *value)
508 {
509  _arp_add_gateway (value, 0L); /* accept gateip[,subnet[,mask]] */
510 }
511 
512 static void set_nameserv (const char *value)
513 {
514  DWORD ip = resolve (value);
515 
516  _add_server (&last_nameserver, def_nameservers,
517  DIM(def_nameservers), ip);
518 }
519 
520 static void set_cookie (const char *value)
521 {
522  DWORD ip = resolve (value);
523 
524  _add_server (&last_cookie, cookies, DIM(cookies), ip);
525 }
526 
530 static void set_eaddr (const char *value)
531 {
532  eth_address eth;
533 
534  if (!_inet_atoeth (value, &eth))
535  return;
536 
537  if (memcmp (&eth, _eth_real_addr, sizeof(eth)))
538  {
539  if (!_eth_set_addr(&eth))
540  outsnl (_LANG("Cannot set Ether-addr"));
541 #if defined(USE_RARP)
542  else
543  {
544  WORD save_to = _rarptimeout;
545  DWORD save_ip = my_ip_addr;
546 
547  /* We need to debug the RARP messages. It doesn't hurt to
548  * call dbug_open() again in sock_ini.c
549  */
550 #if defined(USE_DEBUG)
551  if (debug_xmit)
552  dbug_open();
553 #endif
554  _rarptimeout = 2; /* use only 2 sec timeout */
555  my_ip_addr = 0;
556  if (_dorarp() && my_ip_addr == save_ip)
557  outsnl (_LANG("Warning: MAC-addr already in use"));
558  my_ip_addr = save_ip;
559  _rarptimeout = save_to;
560  }
561 #endif
562  }
563 
564 }
565 
566 static void set_domain (const char *value)
567 {
568  setdomainname (value, sizeof(defaultdomain)-1);
569 }
570 
571 static void depr_set_domain1 (const char *value)
572 {
573  deprecated_key ("DOMAINSLIST", "DOMAIN.SUFFIX");
574  setdomainname (value, sizeof(defaultdomain)-1);
575 }
576 
577 static void depr_set_domain2 (const char *value)
578 {
579  deprecated_key ("DOMAIN_LIST", "DOMAIN.SUFFIX");
580  setdomainname (value, sizeof(defaultdomain)-1);
581 }
582 
583 static void do_print (const char *str)
584 {
585  if (print_hook)
586  (*print_hook) (str);
587  else outsnl (str);
588 }
589 
590 static void depr_dns_timeout1 (const char *value)
591 {
592  deprecated_key ("DOMAINTO", "DOMAIN.TIMEOUT");
593  dns_timeout = ATOI (value);
594 }
595 
596 static void depr_dns_timeout2 (const char *value)
597 {
598  deprecated_key ("DOMAIN_TO", "DOMAIN.TIMEOUT");
599  dns_timeout = ATOI (value);
600 }
601 
602 static void depr_dns_recurse (const char *value)
603 {
604  deprecated_key ("DOMAIN_RECURSE", "DOMAIN.RECURSE");
605  dns_recurse = ATOI (value);
606 }
607 
613 static long do_include_file (const char *value, int len)
614 {
615  const char *p = value;
616  long rc = 0;
617 
618  if (*p == '?' && len > 1)
619  ++p;
620 
621  /* If this is pass 1 of the parsing (ref. pcpkt.c), then return
622  */
623  if (usr_init == NULL)
624  {
625  CONFIG_DBG_MSG (2, ("Skipping include file `%s'\n", p));
626  return (0);
627  }
628 
629  if (FILE_EXIST(p))
630  {
631  /* Recursion, but we're reentrant.
632  * !!Fix-me: recursion depth should be limited.
633  */
634  UINT tmp_line = current_line;
635  char *tmp_file = current_file;
636 
637  rc = tcp_config (p);
638 
639  current_line = tmp_line;
640  current_file = tmp_file;
641  }
642  else if (*value != '?')
643  {
644  outs (_LANG("\nUnable to open \""));
645  outs (p);
646  outsnl ("\"");
647  rc = 0;
648  }
649  return (rc);
650 }
651 
652 static void deprecated_key (const char *old_key, const char *new_key)
653 {
654 #if defined(USE_DEBUG)
655  if (current_file && current_line > 0)
656  printf ("%s (%u): ", current_file, current_line);
657  printf ("Keyword \"%s\" is deprecated. Use \"%s\" instead.\n",
658  old_key, new_key);
659 #endif
660 
661  ARGSUSED (old_key);
662  ARGSUSED (new_key);
663 }
664 
668 const char *get_argv0 (void)
669 {
670  const char *ret;
671 
672 #if defined(WIN32)
673  static char buf [MAX_PATH];
674 
675  if (GetModuleFileNameA(NULL, buf, sizeof(buf)))
676  ret = buf;
677  else ret = NULL;
678 
679 #elif (DOSX & PHARLAP)
680  static char buf[MAX_PATHLEN];
681  CONFIG_INF cnf;
682  UINT limit;
683  CD_DES descr;
684  FARPTR fp;
685  char *env, *start;
686 
687  _dx_config_inf (&cnf, (UCHAR*)&cnf);
688 
689  if (_dx_ldt_rd(cnf.c_env_sel,(UCHAR*)&descr))
690  return (NULL);
691 
692  limit = descr.limit0_15 + ((descr.limit16_19 & 15) << 16);
693  env = malloc (limit);
694  if (!env)
695  return (NULL);
696 
697  start = env;
698  FP_SET (fp, 0, cnf.c_env_sel);
699  ReadFarMem ((void*)env, fp, limit);
700 
701  /* The environment is organised like this:
702  * 'PATH=c:\dos;c:\util',0
703  * ..
704  * 'COMSPEC=c:\dos\command.com',0,0,0
705  * 'program.exe',0
706  *
707  */
708  while (*(env+1))
709  env += 1 + strlen (env);
710  env += 2;
711  _strlcpy (buf, env, sizeof(buf));
712  free (start);
713  ret = buf;
714 
715 #elif defined(__DMC__)
716  ret = __argv[0];
717 
718 #elif defined(__DJGPP__)
719  ret = __crt0_argv[0];
720 
721 #elif defined(_MSC_VER)
722  extern char **__argv;
723  ret = __argv[0];
724 
725 #else
726  extern char **_argv; /* Borland, Watcom */
727  ret = _argv[0];
728 #endif
729 
730  if (!ret || !ret[0])
731  return (NULL);
732  return (ret);
733 }
734 
735 #if !defined(USE_UDP_ONLY)
736 static void set_recv_win (const char *value)
737 {
738  DWORD val = ATOL (value);
739 
740  if (val < tcp_MaxBufSize)
741  val = tcp_MaxBufSize;
742  if (val > MAX_WINDOW)
743  val = MAX_WINDOW; /* Window-scaling not yet supported */
744  tcp_recv_win = val;
745 }
746 #endif
747 
748 
749 
750 /*
751  * Our table of Wattcp "core" values. Other modules have their
752  * own tables which are hooked into the chain via `usr_init'.
753  * If `name' (left column) isn't found in table below, `usr_init'
754  * is called to pass on `name' and `value' to another module or
755  * application.
756  */
757 static const struct config_table normal_cfg[] = {
758  { "MY_IP", ARG_FUNC, (void*)set_my_ip },
759  { "HOSTNAME", ARG_FUNC, (void*)set_hostname },
760  { "NETMASK", ARG_ATOIP, (void*)&sin_mask },
761  { "GATEWAY", ARG_FUNC, (void*)set_gateway },
762  { "NAMESERVER", ARG_FUNC, (void*)set_nameserv },
763  { "COOKIE", ARG_FUNC, (void*)set_cookie },
764  { "EADDR", ARG_FUNC, (void*)set_eaddr },
765  { "ETHIP", ARG_FUNC, (void*)set_ethip },
766  { "DEBUG", ARG_FUNC, (void*)set_debug_on },
767  { "BOOTP", ARG_RESOLVE,(void*)&_bootp_host },
768  { "BOOTPTO", ARG_ATOI, (void*)&_bootp_timeout },
769  { "BOOTP_TO", ARG_ATOI, (void*)&_bootp_timeout },
770  { "SOCKDELAY", ARG_ATOI, (void*)&sock_delay },
771  { "MSS", ARG_ATOI, (void*)&_mss },
772  { "MTU", ARG_ATOI, (void*)&_mtu },
773 
774  { "DOMAIN.SUFFIX", ARG_FUNC, (void*)set_domain },
775  { "DOMAIN.TIMEOUT",ARG_ATOW, (void*)&dns_timeout },
776  { "DOMAIN.RECURSE",ARG_ATOI, (void*)&dns_recurse },
777  { "DOMAIN.IDNA", ARG_ATOI, (void*)&dns_do_idna },
778  { "DOMAIN.DO_IPV6",ARG_ATOI, (void*)&dns_do_ipv6 },
779  { "DOMAIN.WINDNS", ARG_ATOX_W, (void*)&dns_windns },
780 
781  /* These are kept for backward compatability. Delete
782  * them some day.
783  */
784  { "DOMAINSLIST", ARG_FUNC, (void*)depr_set_domain1 },
785  { "DOMAIN_LIST", ARG_FUNC, (void*)depr_set_domain2 },
786  { "DOMAINTO", ARG_FUNC, (void*)depr_dns_timeout1 },
787  { "DOMAIN_TO", ARG_FUNC, (void*)depr_dns_timeout2 },
788  { "DOMAIN_RECURSE",ARG_FUNC, (void*)depr_dns_recurse },
789 
790  { "MULTIHOMES", ARG_ATOI, (void*)&multihomes },
791  { "ICMP_MASK_REQ", ARG_ATOI, (void*)&_do_mask_req },
792  { "DYNAMIC_HOST", ARG_ATOI, (void*)&dynamic_host },
793  { "RAND_LPORT", ARG_ATOI, (void*)&use_rand_lport },
794  { "REDIRECTS", ARG_FUNC, (void*)icmp_doredirect },
795  { "PRINT", ARG_FUNC, (void*)do_print },
796  { "INCLUDE", ARG_FUNC, (void*)do_include_file },
797 #if defined(USE_PROFILER)
798  { "PROFILE.ENABLE",ARG_ATOI, (void*)&profile_enable },
799  { "PROFILE.FILE", ARG_STRCPY, (void*)&profile_file },
800 #endif
801 #if defined(USE_LANGUAGE)
802  { "LANGUAGE", ARG_FUNC, (void*)lang_init },
803 #endif
804 #if defined(USE_BSD_API)
805  { "HOSTS", ARG_FUNC, (void*)_ReadHostsFile },
806  { "HOSTS6", ARG_FUNC, (void*)_ReadHosts6File },
807  { "SERVICES", ARG_FUNC, (void*)_ReadServFile },
808  { "PROTOCOLS", ARG_FUNC, (void*)_ReadProtoFile },
809  { "NETWORKS", ARG_FUNC, (void*)_ReadNetworksFile },
810  { "NETDB_ALIVE", ARG_ATOI, (void*)&netdbCacheLife },
811  { "ETHERS", ARG_FUNC, (void*)_InitEthersFile },
812 #endif
813  { "IP.DEF_TTL", ARG_ATOI, (void*)&_default_ttl },
814  { "IP.DEF_TOS", ARG_ATOX_B, (void*)&_default_tos },
815  { "IP.ID_INCR", ARG_ATOI, (void*)&_ip4_id_increment },
816  { "IP.DONT_FRAG", ARG_ATOI, (void*)&_ip4_dont_frag },
817  { "IP.FRAG_REASM", ARG_ATOI, (void*)&_ip4_frag_reasm },
818  { "IP.LOOPBACK", ARG_ATOX_W, (void*)&loopback_mode },
819 #if !defined(USE_UDP_ONLY)
820  { "DATATIMEOUT", ARG_ATOI, (void*)&sock_data_timeout }, /* EE Aug-99 */
821  { "INACTIVE", ARG_ATOI, (void*)&sock_inactive },
822  { "TCP.NAGLE", ARG_ATOI, (void*)&tcp_nagle },
823  { "TCP.OPT.TS", ARG_ATOI, (void*)&tcp_opt_ts },
824  { "TCP.OPT.SACK", ARG_ATOI, (void*)&tcp_opt_sack },
825  { "TCP.OPT.WSCALE", ARG_ATOI, (void*)&tcp_opt_wscale },
826  { "TCP.TIMER.OPEN_TO", ARG_ATOI, (void*)&tcp_OPEN_TO },
827  { "TCP.TIMER.CLOSE_TO", ARG_ATOI, (void*)&tcp_CLOSE_TO },
828  { "TCP.TIMER.RTO_ADD", ARG_ATOI, (void*)&tcp_RTO_ADD },
829  { "TCP.TIMER.RTO_BASE", ARG_ATOI, (void*)&tcp_RTO_BASE },
830  { "TCP.TIMER.RTO_SCALE", ARG_ATOI, (void*)&tcp_RTO_SCALE },
831  { "TCP.TIMER.RESET_TO", ARG_ATOI, (void*)&tcp_RST_TIME },
832  { "TCP.TIMER.RETRAN_TO", ARG_ATOI, (void*)&tcp_RETRAN_TIME },
833  { "TCP.TIMER.KEEPALIVE", ARG_ATOI, (void*)&tcp_keep_idle },
834  { "TCP.TIMER.KEEPINTVL", ARG_ATOI, (void*)&tcp_keep_intvl },
835  { "TCP.TIMER.MAX_IDLE", ARG_ATOI, (void*)&tcp_max_idle },
836  { "TCP.TIMER.MAX_VJSA", ARG_ATOI, (void*)&tcp_MAX_VJSA },
837  { "TCP.TIMER.MAX_VJSD", ARG_ATOI, (void*)&tcp_MAX_VJSD },
838  { "TCP.MTU_DISCOVERY", ARG_ATOI, (void*)&mtu_discover },
839  { "TCP.BLACKHOLE_DETECT",ARG_ATOI, (void*)&mtu_blackhole },
840  { "TCP.RECV_WIN", ARG_FUNC, (void*)set_recv_win },
841 #endif
842  { "MEMDBG.STACK_DUMP", ARG_ATOI, (void*)&stkwalk_details }, /* put this somewehere else */
843  { "MEMDBG.FORTIFY_FAIL", ARG_ATOI, (void*)&fortify_fail_rate }, /* put this somewehere else */
844 
845  { NULL, 0, NULL }
846  };
847 
853 void W32_CALL tcp_set_debug_state (WORD val)
854 {
855  if (val >= debug_on)
856  debug_on = val;
857 }
858 
865  const struct config_table *cfg,
866  const char *key,
867  const char *value)
868 {
869  WATT_ASSERT (key);
870  WATT_ASSERT (value);
871 
872  if (!key[0])
873  {
874  CONFIG_DBG_MSG (1, ("empty keyword\n"));
875  return;
876  }
877  if (!value[0]) /* don't pass empty values to the parser */
878  {
879  CONFIG_DBG_MSG (1, ("keyword `%s' with no value\n", key));
880  return;
881  }
882 
883  value = expand_var_str (value);
884  if (!parse_config_table(cfg, NULL, key, value) && usr_init)
885  (*usr_init) (key, value);
886 }
887 
893 void W32_CALL tcp_inject_config (const struct config_table *cfg,
894  const char *key,
895  const char *value)
896 {
897  char theKey [MAX_NAMELEN +1];
898  char theValue[MAX_VALUELEN+1];
899  char *save_current_file = current_file;
900  UINT save_current_line = current_line;
901 
902  if (!key)
903  {
904  CONFIG_DBG_MSG (1, ("NULL keyword\n"));
905  return;
906  }
907 
908  strntrimcpy (theKey, key, MAX_NAMELEN);
909  theKey[MAX_NAMELEN] = '\0';
910  strupr (theKey);
911 
912  if (!value)
913  {
914  CONFIG_DBG_MSG (1, ("keyword `%s' with NULL value\n", theKey));
915  return;
916  }
917 
918  strntrimcpy (theValue, value, MAX_VALUELEN);
919  theValue[MAX_VALUELEN] = '\0';
920 
921  current_file = NULL;
922  current_line = 0;
923 
924  tcp_inject_config_direct (cfg, theKey, theValue);
925 
926  current_file = save_current_file;
927  current_line = save_current_line;
928 }
929 
930 
931 /*
932  * Read a character:
933  * - if failed (EOF/26) or read a ^Z, set 'eof' and return '\0'.
934  * - else update 'num_read' counter and return char read.
935  */
936 #define READ_NEXT_CH(ch, f) \
937  (ch = 0, (FREAD(&(ch), f) == 1) && (ch != 26) ? (++num_read, ch) : \
938  (last_eol = got_eol, got_eol = eof = TRUE, ch = '\0'))
939 
940 /* Either read a char or retrieve the one "read ahead" before.
941  */
942 #define READ_CH(ch, next, f) \
943  (next ? (ch = next, next = '\0', ch) : READ_NEXT_CH(ch, f))
944 
945 long tcp_parse_file (WFILE f, const struct config_table *cfg)
946 {
947  char key [MAX_NAMELEN+1];
948  char value[MAX_VALUELEN+1];
949  int ch, nextch; /* !! was 'char' */
950  size_t num; /* # of char in key/value */
951  long num_read; /* # of bytes read */
952  enum ParseMode mode;
953  BOOL quotemode;
954  BOOL stripping;
955  BOOL eof;
956  BOOL last_eol = FALSE;
957  BOOL equal_sign;
958 
959  num_read = 0;
960  nextch = '\0';
961  eof = FALSE;
962 
963  while (!eof)
964  {
965  *key = *value = '\0';
966  mode = ModeKeyword;
967  num = 0;
968  got_eol = FALSE;
969  quotemode = FALSE;
970  stripping = TRUE;
971  equal_sign = FALSE;
972 
973  for (;;)
974  {
975  switch (READ_CH(ch, nextch, f))
976  {
977  case '\0':
978  if (!last_eol && num)
979  CONFIG_DBG_MSG (0, ("Missing line-termination "
980  "could break old WatTcp programs.\n"));
981  break;
982 
983  case '\r':
984  if (READ_NEXT_CH(nextch, f) == '\n')
985  nextch = '\0';
986  /* Fall through */
987 
988  case '\n':
989  got_eol = TRUE;
990  ch = '\0'; /* Do not add */
991  break;
992 
993  case '#':
994  case ';':
995  if (!quotemode)
996  mode = ModeComment;
997  break;
998 
999  case '=':
1000  if (!quotemode && mode == ModeKeyword)
1001  {
1002  mode = ModeValue;
1003  num = 0;
1004  ch = '\0'; /* Don't add */
1005  stripping = TRUE;
1006  equal_sign = TRUE;
1007  }
1008  break;
1009 
1010  case '\"':
1011  if (mode != ModeValue)
1012  {
1013  ch = '\0';
1014  break;
1015  }
1016 
1017  /* Double quotes may be inserted by doubling them (VB-style)
1018  * Ex.: SETTING_1 = "This is a ""quoted"" string."
1019  * SETTING_2 = This_is_a_""quoted""_string.
1020  */
1021  if (READ_NEXT_CH(nextch, f) == '\"')
1022  {
1023  nextch = '\0'; /* Ignore next, but keep this 'ch' */
1024  }
1025  else
1026  {
1027  quotemode ^= 1;
1028  stripping = FALSE;
1029  ch = '\0'; /* Do not add */
1030  }
1031  break;
1032 
1033  case ' ':
1034  case '\t':
1035  if (stripping)
1036  ch = '\0';
1037  break;
1038  } /* end switch */
1039 
1040  if (ch)
1041  {
1042  switch (mode)
1043  {
1044  case ModeKeyword:
1045  stripping = FALSE;
1046  if (num <= sizeof(key)-2)
1047  {
1048  key[num++] = toupper (ch);
1049  key[num] = '\0';
1050  }
1051  break;
1052  case ModeValue:
1053  stripping = FALSE;
1054  if (num <= sizeof(value)-2)
1055  {
1056  value[num++] = ch;
1057  value[num] = '\0';
1058  }
1059  break;
1060  default: /* squelch gcc warning */
1061  break;
1062  }
1063  }
1064 
1065  if (got_eol)
1066  {
1067  if (!eof)
1068  current_line++;
1069  if (quotemode)
1070  CONFIG_DBG_MSG (0, ("Missing right \" in quoted string: `%s'\n",
1071  value));
1072  strrtrim (key);
1073  strrtrim (value);
1074  if (key[0] && value[0])
1075  tcp_inject_config_direct (cfg, key, value);
1076  else if (!key[0] && !value[0] && equal_sign)
1077  CONFIG_DBG_MSG (0, ("Both keyword and value missing\n"));
1078  break;
1079  }
1080  } /* end for (;;) */
1081  } /* end while (!eof) */
1082 
1083  return (num_read);
1084 }
1085 
1086 /*
1087  * Public only because of tcpinfo program.
1088  */
1089 int W32_CALL tcp_config_name (char *name, int max)
1090 {
1091  char *path, *temp;
1092  int i;
1093 
1094  for (i = 0; i < DIM(environ_names); i++)
1095  {
1096  path = getenv (environ_names[i]);
1097  if (path)
1098  {
1099  path = _strlcpy (name, path, max-2);
1100  break;
1101  }
1102  }
1103 
1104  if (path)
1105  {
1106  temp = strrchr (path, '\0');
1107  if (temp[-1] != '\\' && temp[-1] != '/')
1108  {
1109  *temp++ = '\\';
1110  *temp = '\0';
1111  }
1112  }
1113  else if (FILE_EXIST(config_name)) /* found in current directory */
1114  {
1115  strcpy (name, ".\\");
1116  path = name;
1117  }
1118  else if (_watt_os_ver >= 0x300) /* not found, get path from argv[0] */
1119  {
1120  const char *argv0 = get_argv0();
1121 
1122  if (!argv0 || !argv0[0])
1123  return (0);
1124 
1125  _strlcpy (name, argv0, max);
1126  strreplace ('/', '\\', name);
1127 
1128  /* If path == "x:", extract path.
1129  * temp -> last '\\' in path.
1130  */
1131  path = (isalpha((int)name[0]) && name[1] == ':') ? name+2 : name;
1132  temp = strrchr (path, '\\');
1133  if (!temp)
1134  temp = (char*)path;
1135  temp++;
1136  *temp = '\0'; /* 'name' = path of program ("x:\path\") */
1137  }
1138 
1139  i = max - (int)strlen(name) - 1;
1140  if (i < 0)
1141  return (0);
1142 
1143  strncat (name, config_name, i); /* 'name' = "x:\path\wattcp.cfg" */
1144  strlwr (name);
1145  return (1);
1146 }
1147 
1148 /*
1149  * Hack for pcpkt.c/winpkt.c: Bypass parsing of "normal_cfg".
1150  * tcp_config() is called in pcpkt.c/winpkt.c with another config-table.
1151  */
1152 const struct config_table *watt_init_cfg = normal_cfg;
1153 
1154 long W32_CALL tcp_config (const char *path)
1155 {
1156  char name[MAX_PATHLEN] = { 0 };
1157  char *fname = config_name;
1158  WFILE file;
1159  long len;
1160  int pass = (usr_init == NULL) ? 1 : 2;
1161 
1162  if (_watt_no_config && !path)
1163  {
1164  if (!_watt_user_config_fn)
1165  return (0);
1166  current_file = NULL;
1167  current_line = 0;
1168  return (*_watt_user_config_fn) (pass, watt_init_cfg);
1169  }
1170 
1171  if (!path)
1172  {
1173  if (!tcp_config_name(name, sizeof(name)))
1174  goto not_found;
1175  fname = name;
1176  }
1177  else
1178  {
1179  fname = name;
1180  _strlcpy (name, path, sizeof(name));
1181  if (!FILE_EXIST(fname))
1182  goto not_found;
1183  }
1184 
1185  if (!FOPEN_BIN(file,fname)) /* shouldn't happen */
1186  goto not_found;
1187 
1188  current_file = name;
1189  current_line = 0;
1190 
1191  CONSOLE_MSG (2, ("Parsing `%s' (pass %d)\n", fname, pass));
1192 
1193  len = tcp_parse_file (file, watt_init_cfg);
1194 
1195  FCLOSE (file);
1196  return (len);
1197 
1198 not_found:
1199 
1200  /* Warn unless parsing from pcpkt.c/winpkt.c.
1201  */
1202  if (watt_init_cfg == normal_cfg)
1203  {
1204  outs (fname);
1205  outsnl (_LANG(" not found"));
1206  }
1207  return (0);
1208 }
1209 
1210 #if defined(USE_BSD_API)
1211 
1215 int netdb_init (void)
1216 {
1217  int rc, save = _watt_do_exit;
1218 
1219  _watt_do_exit = 0; /* don't make watt_sock_init() call exit() */
1220  rc = watt_sock_init (0, 0, sizeof(time_t));
1221  _watt_do_exit = save;
1222  return (rc == 0);
1223 }
1224 
1225 void netdb_warn (const char *fname)
1226 {
1227  fprintf (stderr, "Warning: `%s' not found\n", fname);
1228 }
1229 #endif
1230 
1231 /*
1232  * A test program.
1233  */
1234 
1235 #if defined(TEST_PROG)
1236 
1237 const char *cfg_file;
1238 
1239 static void W32_CALL not_found2 (const char *key, const char *value)
1240 {
1241  size_t len = strlen (value);
1242  DWORD ret = 0;
1243 
1244  printf ("Unmatched: key `%s', value `%s', len %lu %s\n",
1245  key, value, len, (len >= MAX_VALUELEN-1) ? "(truncated)" : "");
1246 
1247  if (!stricmp("HEX_BYTE",key))
1248  set_value (TRUE, value, &ret, sizeof(BYTE));
1249 
1250  if (!stricmp("HEX_WORD",key))
1251  set_value (TRUE, value, &ret, sizeof(WORD));
1252 
1253  if (!stricmp("HEX_DWORD",key))
1254  set_value (TRUE, value, &ret, sizeof(DWORD));
1255 }
1256 
1257 static long my_injector (int pass, const struct config_table *cfg)
1258 {
1259  printf ("my_injector(), pass %d\n", pass);
1260  tcp_inject_config (cfg, "My_IP", "192.168.0.98");
1261  tcp_inject_config (cfg, "NetMask", "255.255.255.0");
1262 
1263  /* doing the file again doesn't work
1264  */
1265  tcp_inject_config (cfg, "include", cfg_file);
1266  return (1);
1267 }
1268 
1269 void Usage (void)
1270 {
1271  puts ("Usage: pcconfig [-d debug-level] [config-file]\n"
1272  "if config-file is omitted, the default "
1273  "$(WATTCP.CFG)\\WATTCP.CFG is used.");
1274  exit (0);
1275 }
1276 
1277 #ifdef __CYGWIN__
1278 #include <sys/stat.h>
1279 static long filelength (int fd)
1280 {
1281  struct stat st;
1282  if (fstat(fd,&st) != 0)
1283  return (-1);
1284  return (st.st_size);
1285 }
1286 #endif
1287 
1288 int main (int argc, char **argv)
1289 {
1290  int ch, cfg_len;
1291  long file_len = 0L;
1292 
1293  while ((ch = getopt(argc, argv, "h?d:")) != EOF)
1294  switch (ch)
1295  {
1296  case 'd':
1297  debug_on = ATOI (optarg);
1298  break;
1299  case '?':
1300  case 'h':
1301  default:
1302  Usage();
1303  break;
1304  }
1305 
1306  argc -= optind;
1307  argv += optind;
1308  cfg_file = NULL; /* use the default wattcp.cfg */
1309 
1310  if (*argv)
1311  {
1312  WFILE cfg;
1313 
1314  cfg_file = *argv;
1315  if (FOPEN_BIN(cfg,cfg_file))
1316  {
1317  file_len = filelength (fileno(cfg));
1318  FCLOSE (cfg);
1319  }
1320  }
1321 
1322  usr_init = not_found2;
1323  cfg_len = tcp_config (cfg_file);
1324 
1325  if (file_len > 0)
1326  printf ("filesize %ld, %d bytes parsed\n", file_len, cfg_len);
1327 
1328  printf ("\nTest the config injector:\n");
1329  _watt_user_config (my_injector);
1330  _watt_no_config = 1;
1331  tcp_config (NULL);
1332  return (0);
1333 }
1334 #endif
void(W32_CALL *print_hook)(const char *)
Hook to a function called after we're initialised.
convert to hex-word
Definition: tcp.h:429
int W32_CALL parse_config_table(const struct config_table *tab, const char *section, const char *name, const char *value)
Parse the config-table and if a match is found for ('section'+'.
Definition: pcconfig.c:379
void lang_init(const char *value)
Initialize the linked list for language.
Definition: lang.c:2389
DWORD W32_CALL aton(const char *str)
Converts [a.b.c.d] or a.b.c.d to 32 bit IPv4 address.
Definition: netaddr.c:86
const char * get_argv0(void)
Return argv[0] as passed to main().
Definition: pcconfig.c:668
convert to int
Definition: tcp.h:424
char * strreplace(int ch1, int ch2, char *str)
Replace 'ch1' to 'ch2' in string 'str'.
Definition: strings.c:207
call convertion function
Definition: tcp.h:434
int _default_ttl
Definition: ip4_out.c:54
BOOL W32_CALL _arp_cache_add(DWORD ip, const void *eth, BOOL expires)
Add given IP/Ether address to ARP-cache.
Definition: pcarp.c:1352
void W32_CALL tcp_inject_config(const struct config_table *cfg, const char *key, const char *value)
Callable from a user application to inject config values before the normal WATTCP.CFG is loaded and parsed.
Definition: pcconfig.c:893
WORD _watt_os_ver
Definition: misc.c:61
BOOL _watt_no_config
run with no config file (embedded/diskless)
Definition: sock_ini.c:135
static void tcp_inject_config_direct(const struct config_table *cfg, const char *key, const char *value)
Called from config-file parser after "key = value" is found.
Definition: pcconfig.c:864
unsigned tcp_RTO_BASE
Base time for RTO calculation.
Definition: pctcp.c:116
size_t strntrimcpy(char *dst, const char *src, size_t n)
Copy a string, stripping leading and trailing blanks (space/tab).
Definition: strings.c:277
static void set_eaddr(const char *value)
Set new ether-address from "ether" value.
Definition: pcconfig.c:530
BOOL W32_CALL _arp_add_gateway(const char *config_string, DWORD ip)
Add a gateway to the routing table.
Definition: pcarp.c:247
DWORD tcp_recv_win
RWIN for BSD sockets only.
Definition: pctcp.c:135
unsigned tcp_max_idle
max idle time before kill
Definition: pctcp.c:134
copy string value
Definition: tcp.h:432
BOOL mtu_blackhole
Definition: pctcp.c:64
resolve host to IPv4-address
Definition: tcp.h:433
static void set_my_ip(const char *value)
Functions called by config-file parser while reading c:/W32DHCP.TMP.
Definition: pcdhcp.c:1390
static BOOL set_value(BOOL is_hex, const char *value, void *arg, int size)
Parse and store ARG_ATOX_B, ARG_ATOX_W or ARG_ATOI value.
Definition: pcconfig.c:285
mac_address _eth_real_addr
Our real MAC address.
Definition: pcsed.c:53
Core definitions.
unsigned tcp_RTO_SCALE
Scaling used in RTO calculation.
Definition: pctcp.c:117
char * _strlcpy(char *dst, const char *src, size_t len)
Similar to strncpy(), but always returns 'dst' with 0-termination.
Definition: strings.c:226
BOOL _ip4_dont_frag
Definition: ip4_out.c:56
WattUserConfigFunc W32_CALL _watt_user_config(WattUserConfigFunc fn)
A user application may call the `_watt_user_config()' function prior to calling sock_init() to inject...
Definition: sock_ini.c:199
const char * expand_var_str(const char *str)
Return a string with a environment variable expanded (only one).
Definition: pcconfig.c:231
convert to 8-bit byte
Definition: tcp.h:425
unsigned tcp_RTO_ADD
Time added in RTO calculation.
Definition: pctcp.c:115
convert to hex-dword
Definition: tcp.h:430
int W32_CALL watt_sock_init(size_t tcp_Sock_size, size_t udp_Sock_size, size_t time_t_size)
Definition: sock_ini.c:749
void icmp_doredirect(const char *value)
Determine which protocols we shall act upon when ICMP redirect is received.
Definition: pcicmp.c:597
DWORD sin_mask
our net-mask, 255.255.255.0
Definition: pctcp.c:71
unsigned tcp_RST_TIME
Don't generate RST too often.
Definition: pctcp.c:118
unsigned tcp_MAX_VJSA
Default max VJ std.
Definition: pctcp.c:120
Definition: ip.h:67
int _ip4_id_increment
Definition: ip4_out.c:55
static void W32_CALL keyword_not_found(const char *key, const char *value)
This function eventually gets called if no keyword was matched.
Definition: pcconfig.c:273
int W32_CALL setdomainname(const char *name, size_t len)
BSD-style: Set the host's domain name.
Definition: bsdname.c:213
BOOL W32_CALL isaddr(const char *str)
Check if 'str' is simply an ip address.
Definition: netaddr.c:128
BOOL _rarp_on
Try booting using RARP ?
Definition: sock_ini.c:132
char * strrtrim(char *s)
Trim trailing blanks (space/tab) from a string.
Definition: strings.c:255
BOOL _watt_do_exit
exit program when all boot attempts failed
Definition: sock_ini.c:134
convert to 16-bit word
Definition: tcp.h:426
static long do_include_file(const char *value, int len)
Open and parse an include file.
Definition: pcconfig.c:613
DWORD W32_CALL _inet_addr(const char *s)
Convert a string into an IP-address.
Definition: netaddr.c:69
static void set_ethip(const char *value)
Add an "ether, IPv4-address" pair to the static ARP-cache.
Definition: pcconfig.c:170
BYTE atox(const char *hex)
Convert hexstring "0x??" to hex.
Definition: strings.c:194
BOOL _dhcp_on
Try booting using DHCP ?
Definition: sock_ini.c:130
BOOL mtu_discover
Definition: pctcp.c:63
char hostname[MAX_HOSTLEN+1]
Our configured hostname.
Definition: pctcp.c:59
BOOL tcp_opt_ts
TCP option config flags (RFC 1323).
Definition: pctcp.c:125
const char * _inet_atoeth(const char *src, eth_address *p_eth)
Parse string "ether-addr, ip-addr".
Definition: netaddr.c:205
duplicate string value
Definition: tcp.h:431
BOOL tcp_nagle
Misc TCP values.
Definition: pctcp.c:131
DWORD my_ip_addr
our IP address
Definition: pctcp.c:70
char defaultdomain[MAX_HOSTLEN+1]
The 2 next variables are loaded from WATTCP.CFG file.
Definition: pcdns.c:71
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
const ip6_address * _inet6_addr(const char *str)
Convert a string 'str' into an IPv6-address.
Definition: netaddr.c:419
unsigned tcp_CLOSE_TO
Default close timeout.
Definition: pctcp.c:114
unsigned tcp_MAX_VJSD
Default max VJ std.
Definition: pctcp.c:121
unsigned tcp_keep_idle
idle time before sending keepalive
Definition: pctcp.c:132
unsigned tcp_RETRAN_TIME
Default retransmission time.
Definition: pctcp.c:119
BOOL _do_mask_req
do an "ICMP Mask Request" when configured
Definition: sock_ini.c:133
convert to ip-address (host order)
Definition: tcp.h:427
unsigned tcp_keep_intvl
time between keepalive probes
Definition: pctcp.c:133
DWORD W32_CALL resolve(const char *name)
Convert host name to an address.
Definition: pcdns.c:775
int W32_CALL _eth_set_addr(const void *addr)
Sets a new MAC address for our interface.
Definition: pcsed.c:731
convert to hex-byte
Definition: tcp.h:428
void W32_CALL tcp_set_debug_state(WORD val)
Old comptibility function.
Definition: pcconfig.c:853
BYTE _default_tos
Definition: ip4_out.c:53
unsigned tcp_OPEN_TO
TCP timer values.
Definition: pctcp.c:113
BOOL _bootp_on
Try booting using BOOTP ?
Definition: sock_ini.c:129
int main(int argc, char **argv)
Definition: echo.c:223