CHANGES  (formerly readme.2nd)

If you are programming with the Waterloo TCP library, the following notes
may prove helpful. Latest changes are added at the top.

- - -

******************* Changes version 2.1 dev.rel.5 *******************

* PPP-over-Ethernet: Preliminary support for PPPoE encapsulation
  for Ethernet. Still requires full PPP implementation. Maybe later.

* pcconfig.c change: Added check for env-var `WATTCP_CFG' before
  checking `WATTCP.CFG'. This is to allow bash (the Unix shell) to
  work (it reportedly doesn't allow `.' in env-vars).

* timer.c changes: `set_timeout()' now uses `gettimeofday()' and
  `microsec_clock()' to get an absolute timestamp. This hopefully
  fixes the problem with timeouts around midnight.

* new files profile.[ch]: Used to measure execution speed. Activated
  by "PROFILE = 1" in wattcp.cfg. Only for djgpp and Watcom 32-bit
  targets running on Pentium (uses RDTSC instruction). Currently only
  `pkt_send()' uses profiling.

* neterr.c changes: `net_errno', `net_strerror' and `net_perror' renamed
  to `errno_s', `strerror_s' and `perror_s' (to be consistent with write_s
  etc.)

* ip_out.c change: Implemented `ip_do_fragment()' and `ip_free_fragment()'.
  These does not yet support IP-options.

* pctcp.[ch] changes: made some TCP-timer values configurable through
  new keywords in `WATTCP.CFG' file:
    "TCP.TIMER.OPEN_TO"   -> tcp_OPEN_TO      default 1 sec
    "TCP.TIMER.CLOSE_TO"  -> tcp_CLOSE_TO     default 1 sec
    "TCP.TIMER.RTO_ADD"   -> tcp_RTO_ADD      default 100 msec
    "TCP.TIMER.RTO_BASE"  -> tcp_RTO_BASE     default 10 msec
    "TCP.TIMER.RESET_TO"  -> tcp_RST_TIME     default 1 sec
    "TCP.TIMER.RETRAN_TO" -> tcp_RETRAN_TIME  default 50 msec

  Parser for these (and some others) moved to sock_ini.c; function
  `tcp_parse_config()'. Added argument `force' to `tcp_Retransmitter()'
  to force a retransmission check from receive.c and transmit.c
  functions.

* wattcp.h etc. change: Renamed struct member `sock_mode' to `sockmode'
  due to warning from linker; `sock_mode()' vs. `.sock_mode'.

* pcconfig.c change: Added `ARG_ATOB' and `ARG_ATOW' for storing bytes
  and words respectively.

* pcpkt.c change: `_pktretries' changed to BYTE. `tx_cnt' in `pkt_send()'
  modified to use range [1.._pktretries].

* ioctl.c change: Added command `SIOCGIFHWADDR' for Linux(?) compatibility.

* makefile.all / target.h changes for compiling with `cl32.exe' from
  MS Visual C 4.0. The only target currently is Pharlap DOSX. Not
  finished yet!

* pctcp.c change: `udp_open()' now only sets `ip = 255.255.255.255' if
  called with ip == 0. This change allows sending to limited broadcast
  addresses. E.g. `a.b.255.255' should no longer be mapped to
  `255.255.255.255'.

* pcdbug.c change: Rewritten decoding of IGMP packets in `igmp_dump()'.
  Only if `USE_MULTICAST' is defined.

* ioctl.c change: command `SIOCGIFADDR' didn't check for address family.
  Now returns local IP-address for `AF_INET' family. Otherwise MAC-
  address. Similarily for command `SIOCSIFADDR'. What should `SIOCDIFADDR'
  and `SIOCAIFADDR' do ?

* select.c change: selecting for exceptions (in `_sock_exc_select()')
  shall only (according to authoritative sources) count the arrival of
  "Out-Of-Band" data i.e. TCP-segments with URG flag set. Watt-32 does
  not yet support OOB data, so selecting for exceptions will never count.

* pcsed.c change: New hook pointers `_eth_xmit_hook' and `_eth_recv_hook'.
  These are meant to be used by libpcap (the promiscous mode network
  library).

* ioctl.c changes: debug printing name of commands. Set flag `IFF_RUNNING'
  for `SIOCGIFFLAGS' command.

* chksum.h / config.h changes: `USE_FAST_CKSUM' define removed. Default
  for all 32-bit targets is to use `inchksum_fast()'. 16-bit targets
  uses `inchksum()' in chksum.c.

* pcpkt.c changes: This module is now completely independant of the various
  link-layers. All MAC-header encoding and decoding is now done in pcsed.c.

* pcsed.[ch] changes: Removed `_pkttoken' variable. Uses `_pktdevclass
  == PD_TOKEN' instead. Fixed zero-padding problem in `eth_mac_xmit()'.
  `_eth_formatpacket()' now clears only the IP-header portion of the
  transmit buffer.

* pcpkt.[ch] changes: Preliminary support for FDDI with IEEE 802.2 headers
  (class 12 driver). New structures `fddi_Header' and `fddi_Packet' added
  to wattcp.h.

* pcpkt.c change: `PKT_TMP' area increased to 30 bytes because of Token-
  Ring type arrays may be 24 bytes (3 types, 8 bytes each).

* pcdbug.c change: Updated `link_head_dump()' function for printing
  Token-Ring header.

* pcpkt.c / pcsed.c changes: Simplified access to MAC-headers through
  new `union link_Packet' and new functions `_eth_mac_xxx()' for easier
  access to various fields in the MAC-header given an IP-packet.
  New function `_eth_get_hwtype()' used to fill ARP, RARP, BOOTP and
  DHCP headers.

* pcpkt.c / pcsed.c etc: Support for IEEE 802.5 Token-Ring contributed by
  Robert Gentz <rgentz@asdis.de>. Updated by me to support all targets.
  `check_tok_header()' is now done when polling queues and not when
  enqueueing (to save time copying packet twice).

* pcrarp.c fix: Polled link-layer packet from `_eth_arrived()' was not
  freed in function `_dorarp()'.


******************* Changes version 2.1 dev.rel.4 *******************

* timer.c change: New function `get_timediff()' returns difference
  between two timers compensating for any day rollover.

* socket.c change: In `_sock_dos_fd()' use `isatty()' instead of
  `_dos_getftime()' to check if file-handle is a valid DOS handle.

* listen.c bugfix: The `backlog' was not limited to range `1..SOMAXCONN'.

* socket.[ch] change: New `Socket' members `send_lowat' and `recv_lowat'
  for setting "low water marks". `socket->send_lowat' is used to determine
  if non-blocking sockets are writable (in `check_non_block_tx()').
  `socket->send_lowat' is also used in `_sock_write_select()'.
  `socket->recv_lowat' is used in `receive()' and `_sock_read_select()'.
  Initial size of both is 0 (controllable by socket options `SO_SNDLOWAT'
  and `SO_RCVLOWAT').

* connect.c change: Sets `errno = ECONNRESET' on failed returned from
  `_ip_delay0()'.  I'm unsure when to use `ECONNREFUSED' and when to use
  `ECONNRESET'.

* select.c change: `sock_signalled()' is now simplified for non-blocking
  sockets; it always returns 0 if `mask' argument not satisfied.

* receive.c / transmit.c change: When socket-state bit `SS_CONN_REFUSED'
  is set return either `ECONNRESET' or `ECONNREFUSED' in `errno'. This
  depends on whether we got a RST or an "ICMP Unreachable" message.

* pctcp.c changes: In `_tcp_sockreset()', sets `so_error = ECONNRESET'
  and not `ECONNREFUSED'.

* shutdown.c change: Don't call `close_s()' on `SHUT_WR'. Only close on
  `SHUT_RDWR' (2).

* select.c change: `read_signalled()' and `write_signalled()' merged
  into one function `sock_signalled()' with different masks. Non-blocking
  listen sockets (both `SS_NBIO' and `SO_ACCEPTCONN' set) shall not count
  as a readable socket in `sock_signalled()'.

* getname.c change: Verify read/write of arguments in `getsockname()'
  and `getpeername()'. Using macro `VERIFY_RW()' on name.

* pcpkt.c bug-fix: When `WATTCP.VEC' was specified only that vector
  should be checked in `find_vector()'. But the search loop was called
  with wrong first/last range. Modified to search [x..(x+num)>.

  `find_vector()' also modified so it never checks a real-mode NULL-
  vector for a matching "PKT DRVR" signature.

* pcconfig.c change: New keyword "DOMAIN_RECURSE" for assigning value to
  `dns_recurse' (see below).

* udp_dom.c change: New variable `dns_recurse' controlling recursive
  resolution of "dot-less" hostnames. Default is 1.

* socket.c change: In `socket()' check that a `SOCK_RAW' protocol is
  in range 0 - 255.

* socket.h change: Needed to call `kbhit()' in `SOCK_YIELD()' for all
  targets except djgpp.  This may cause performance drop in e.g. DOS4GW
  applications, but cannot be helped.  Applications MUST be able to
  break out of e.g. `select_s()' loops with very long timeouts (e.g.
  a server application),

* getserv.c change: Use a small hash-table for speeding up `getservbyport()'.
  (mainly to benefit tcpdump).

* fortify.c change: Use `inchksum_fast()' in `st_ChecksumHeader()' if
  `USE_FAST_CKSUM' is defined. `FORTIFY_CHECKSUM_VALUE' is then 0xFFFF.

* misc.c change: `inchksum()' moved to new module `chksum.c'. Other new
  files `chksum0.s' (for djgpp) and `chksum0.asm' (other DOSX-targets)
  implements `inchksum_fast()'.  `USE_FAST_CKSUM' in `config.h' selects
  if this function shall be used. Default is on for all DOSX targets.
  Anybody care to write a 16-bit version?

  Approx. speed increase, asm-version `inchksum_fast()' vs. C-version
  `inchksum()':

  AMD K6-2I    4:1    GNU gcc 2.95.2
  AMD K6-2I    2:1    Watcom 11.0 wcc386
  Pentium-II  12:1    GNU gcc 2.95.2
  Pentium-II  10:1    Watcom 11.0 wcc386

  The gain is significant because the `checksum()' macro is used 3 times
  when processing a received/sent tcp segment.

* gethost.c change: Made it possible to grow list of host/addresses by
  calling `ReadHostFile()' multiple times. We close previous file if
  called 2nd time.

* fragment.c bug-fix: `setup_first_frag()' potentially copied 20 bytes
  to little into fragment bucket which caused checksum error on higher
  level protocols. Solution was to replace `MAX_IP_DATA' with
  `mtu' in `min()' macro.

* tcp.h / pctcp.h changes: Redefined macros `sock_wait_established()',
  `sock_wait_input()', `sock_wait_closed()' and `sock_tick()' to allow
  using them in a "if () .. else" statement.

* tftp.[ch] changes: Modified to use header `<arpa/tftp.h>' instead.

* pctcp.c bug-fix: Enabling the TimeStamp option ("tcp.opt.ts = 1")
  caused some segments to be sent with MSS worth of rubbish data.
  This was caused by an overflow in the `min()' macro after calling
  `tcp_do_options()'.

* signal.c change (NOT YET): Terminate application on unhandled (not
  trapped) signal `SIGQUIT' assuming it's stuck due to recursive `alarm()'
  handler etc. For this reason we don't chain to previous owner of `SIGALRM'.
  In djgpp the `SIGQUIT' signal is normally mapped to <Ctrl>-<\> key. Can
  be changed by `__djgpp_set_sigquit_key()'


******************* Changes version 2.1 dev.rel.3 *******************

* sock_ini.c changes: Added variable `_watt_no_config' to support diskless
  (embedded) machines running with fixed IP configuration. Look at test
  program in `.\src\tftp.c' for an example. Similarily debug variables
  `dbg_mode_all', `dbg_print_stat' and `dbg_dns_details' are made public
  so an application may set these before calling `dbug_init()' and
  `sock_init()'. The debug file `WATTCP.DBG' will be created in current
  directory (provided the diskless machine have some filesystem).
  New public variables `_watt_environ_name' and `_watt_config_name' to
  override default configuration path and file.

* tftp.c changes: TFTP now works with PumpKIN tftp server
  (http://www.klever.net/kin/index.html). A simple test program is
  included in `tftp.c'.

* pcdhcp.c / tftp.c changes: `tcp_boot_load()' is moved to end of
  `sock_init()'. Thus TFTP is decoupled from DHCP. To actually enable
  the boot process, an application must supply a writer function through
  `tftp_writer' function pointer.

* pcstat.c change: Count and print of all possible ICMP message types.
  Added TCP count for retransmit timeouts (tcps_rexmttimeo) and delayed
  ACKs (tcps_delack) in `tcp_Retransmitter()'.

* pcdbug.c / pcicmp.c change: Check for and handle truncated (too short)
  ICMP messages. Must be at least 8 bytes.

* pcpkt.c change: A hack for building Perl 5.6 (djgpp) with sockets.
  To build Perl, we would normally need DOS memory for approx. 20
  levels of nesting (Perl calls itself recursively).

  If `__bss_count > 0' and environment variable "PERL_BUILD_HACK" is
  present don't allocate around 40kB of DOS memory in `setup_rmode_callback'.
  We simply pretend the packet-driver has been initialised properly.


******************* Changes version 2.1 dev.rel.2 *******************

* pctcp.c / pcconfig.c changes: New variables and WATTCP.CFG keywords
  for controlling (future) advanced TCP options:
   `tcp_opt_timstmp' = "TCP.OPT.TS"      Enable Timestamp option.
   `tcp_opt_sackok'  = "TCP.OPT.SACK"    Enable Selective ACK (not yet).
   `tcp_opt_wscale'  = "TCP.OPT.WSCALE"  Enable Window scale (not yet).

  Default values for all is 0 (off).

* sock_ini.c change: Removed call to `signal(SIGFPE,..)' for Watcom +
  Borland 32-bit targets. If handler was installed, then `SIGFPE' gets
  raised somewhere in the BSD-socket API (in select_s() ??). I've no
  idea why.

* pcdbug.c bug-fix: The parsing of tcp SACK option was wrong.

* pcdbug.c change: Added config-file keyword "debug.dns" for controlling
  detailed printing of DNS records. Defaults to 1.

* pcpkt.h + asmpkt4.asm change: Added 2 bytes to `ARP_SIZE' to make it
  multiple of dwords. asmpkt4.asm now uses dword fill (`rep stosd').

* pctcp.c change: New `tcp_Socket' members `ts_sent', `ts_recent' and
  `ts_echo'. Add TCP TimeStamp option to opening SYN packet (`_tcp_send').
  `tcp_ProcessData()' sets `ts_echo' from ACK packets. And sets `ts_recent'
  from SYN only packets. New `locflags' bit `LF_RCVD_TSTMP' controls when
  to send the TS echo value back to peer; `_tcp_send()' does this in a
  non-SYN (and non-RST) packet.

  IMPORTANT NOTE:
  ---------------
  This change have caused `tcp_Socket' in <tcp.h> to increase by 12 bytes.
  Hence one need to recompile applications that use `tcp_Socket'.

* wdpmi.c change: Added function `_fatal_runtime_error()' to print
  information and release packet-driver when stack overflows occurs.
  Printing e.g. "Stack overflow (400000 bytes) detected at CS:12AE0"
  means that function at 0x12AE0 (where __CHK was called) requested a
  stack-size of 400000 bytes. Stack overflow could also indicate other
  bugs. `_fatal_runtime_error()' also sets a new stack-low value to
  prevent further stack overflows.

* pcarp.c bug-fix: ping.exe and pcping.c revealed a bug in `_arp_handler()'
  An ARP Request/Response with a call to `_arp_search()' caused the old
  MAC address to be replaced by source MAC address in the ARP Request/
  Response message! `_arp_handler()' now requires "arp->ip == ip".

* pcarp.c change: In `_arp_handler()' check if requesting address is
  multicast. Class-D addresses don't use ARP, so don't do an ARP-reply.

* .\bin\finger.c change: Moved `sock_close()' call down after while-loop.
  There are problems with successfully receiving data after closing the
  sending side. Seems the generation of ACKs stops in the FINWT2 state.

* sock_in.c change: Added condition for breaking the loop in `_ip_delay1()'
  (used in macro `sock_wait_input'). When `s->locflags & LF_GOT_FIN' is
  TRUE this indicated we either got a FIN or we cannot receive more data.
  This is not used in `_ip_delay2()' (macro `sock_wait_closed'). Thus
  here we wait until connection is fully closed (entered CLOSED state).

* pctcp.c change: Function `_tcp_sendsoon()' increases the time for issuing
  retransmissions to 500msec while in `CLOSEWT' (or higher) states. This
  was done to relax retransmissions while having unACK'ed data when calling
  `sock_close()'. Refer the `.\bin\finger' program.

* tcp_fsm.c change: sets `LF_GOT_FIN' in `s->locflags' also when entering
  FINWT2 state (only from FINWT1 state) indicating we'll never receive more
  data.

* getprot.c change: call `netdb_init()' in start on all function.
  This function calls `sock_init()' in case it wasn't called beforehand.

* receive.c change: In `raw_receive()', drop raw-packet incase user
  suplied a too small buffer ( < sizeof(struct ip)). Still doesn't handle
  IP-options !.

* pcconfig.c change: New table-driven config-file parser
  `parse_config_table()'. Can also be used by applications (added to
  ../inc/tcp.h).  Parser can store integers (ARG_ATOI), network addresses
  (ARG_ATON), hex byte/words (ARG_ATOX_B/ARG_ATOX_W), duplicate a string
  (ARG_STRDUP), resolve a value to an address (ARG_RESOLVE) or call a
  specified function (ARG_FUNC) for finer control of parsing.

* pcdbug.c changes: Added decoding of PTR records in `dns_resource()'.
  Simplified printing of "class"; dropped "(Internet)" for class 1.
  Renamed record names to official names ("IP address" -> "A",
  "Name Server" -> "NS", "Canonical Name" -> "CNAME" etc. Uses
  `__p_type()' from res_debu.c if compiled with `USE_BIND'.

* config.h change: New flag `USE_BIND' for compiling res*.c files.
  `USE_BSD_FUNC' flag is now independant of resolver functions.

* ../inc/tcp.h change: Added define `WATTCP_DEVEL_REL' to enumerate
  developement releases. Value is also returned in `wattcpVersion()'.

* pctcp.c change: size of `hostname' changed to `MAX_HOSTLEN+1'.

* syslog.c / printk.c change: Argument for `%I' format is now in network
  order (previously in host order).

* pcconfig.change: new keyword `ETHERS = <file>' emulate Unix /etc/ethers
  feature. Read file of ether-address and host-names. Since this feature
  is hardly needed, it's only active if compiled with `config.h' option
  `USE_ETHERS' and `USE_BSD_FUNC'.

* pcconfig.c bug-fix: `netdb_init()' didn't preserve value of
  `_watt_do_exit' causing `sock_init()' *not* to exit when it should.

* pcconfig.c / gethost.c / sock_ini.c changes: when using PPP with dynamic
  IP-address, get FQDN by reverse lookup of assigned IP-address. New
  WATTCP.CFG keyword `DYNAMIC_HOST = 1' causes new function
  `reverse_lookup_myip()' to be called and do the reverse lookup. If
  successfull, replace `hostname' and `def_domain' with result. Otherwise
  print warning and exit.

* version.c bug-fix: The first part of "Watt-32 -" was overwritten by
  string specifying compiler options.

* socket.c change: For non-djgpp targets, let first socket start at 3
  in order not to confuse a socket with stdin/stdout/stderr handles.
  E.g. (Unix) code like:
    if (FD_ISSET(0, &readfd))
       read_keyboard();
    else if (FD_ISSET(s, &readfd))
       read_network();

  blindly assumes handle 0 is always stdin. Thus a real socket handle
  with value 0 will not work in such programs. Socket handles in djgpp
  will always be >3.

* pcstat.c change: added new IP-counter `ips_idropped' to differentiate
  dropped packets on input from packets on output (`ips_odropped').
  Changed `struct ipstat' in <netinet\ip_var.h> accordingly.

* pctcp.c change: New function pointer `_tcp_find_hook' set to
  `sock_find_tcp()' in socket.c when at least one SOCK_STREAM socket
  is allocated. To prevent pulling in too much code for simple non-BSD
  programs.

* pctcp.c change: New function pointer `_tcp_syn_hook' set to
  `_sock_append()' in accept.c when at least one listening SOCK_STREAM
  socket is allocated. To prevent pulling in too much code for simple
  non-BSD programs.

* pctcp.c change: New function pointer `_raw_ip_hook' set to
  `sock_raw_recv()' in socket.c when at least one SOCK_RAW socket is
  allocated. To prevent pulling in too much code for simple non-BSD
  programs.

* socket.c changes: `_sock_debug_exit()', `_sock_debug_on()' and
  `_sock_debug_off()' moved to new module bsddbug.c to prevent
  pulling in too much code for simple non-BSD programs.


******************* Changes version 2.1 dev.rel.1 *******************

* Version 2.1 dev.rel.1 released Apr 21, 2000.

* sock_dat.c merged with pcbuf.c

* pctcp.c had to split up in smaller chunks to prevent TurboC 2.01
  from running out of memory;  watt_largecheck() moved to misc.c.
  tcp_init(), tcp_shutdown() and tcp_post_init() are now static and
  moved to sock_ini.c.  New file ports.c handles local-ports.

* Revisited most sources for use of `const' pointers. `const' is now
  used to signal to reader that object pointed to is not modified.
  Some rewrite was needed to accomplish this. E.g. `resolve()' called
  `rip()' that potentially modified the input argument. It now store
  argument in local buffer.

* wattcp.h changes: Removed macros `in_GetTos', `in_GetTTL',
  `in_GetProtocol', `in_GetVersion' and `in_GetHdrlenBytes'. Macro
  `in_GetHdrLen' (previously called `in_GetHdrlen') now returns IP-
  header size in *bytes*.

* transmit.c changes: Major rewrite of `setup_non_stream()' (previously
  `setup_remote'). Only connectionless protocols (SOCK_DGRAM/SOCK_RAW)
  may transmit without calling `connect()' first and they may transmit
  to different host/port than on last transmission. Thus a reconnect to
  another address must preserve the receive buffer and local-port after
  `connect()' returns.

* wdpmi.c change: new function `dpmi_dos_yield()' for DOS4GW/WDOSX targets.
  Called in connect(), select_s() and accept() loops to reduce CPU-loading.
  Calling `kbhit()' doesn't seem to yield under Windows-NT.

* pcpkt.c change: new functions `pkt_get_params()' and `pkt_get_mtu()'
  (enhanced drivers only). Used to determine correct MTU and MAC-address
  length of driver. If no enhanced driver found, the MTU is taken from
  config-file.

* socket.c change: For sockets of type `SOCK_RAW', specifying protocol
  `IPPROTO_RAW' maps to `IPPROTO_IP' internally.

* receive.c change: Return size/data from `ip_receive()' (SOCK_RAW)
  shall always include IP-header and data.  Flag `INP_HDRINCL' is
  only used in `ip_transmit()' to specify that IP-header is part of
  user's buffer.

* sockopt.c change: Added handling of multicast options `IP_ADD_MEMBERSHIP'
  and `IP_DROP_MEMBERSHIP'. Contributed by Vlad Erochine <vlad@paragon.ru>

* sock_ini.c change: Simplified signal handlers for djgpp. Doesn't
  trap `SIGQUIT'. New define `USE_EXCHANDLER' defined for all targets
  by default. Only `SIGFPE' is trapped for real-mode targets.

* socket.c change: Return 1 in `_sock_dos_fd()' if socket is "stdin..
  stderr". `_sock_debugf()' changed to macro `SOCK_DEBUGF()' incase
  compiling without `USE_DEBUG'.

* loopback.c change: `loopback_device()' is given pointer to IP-header.
  Link-layer header is enqueued to IP-queue (dst/src swapped) after
  `loopback_device()' returns.

* All makefiles for Watcom targets now uses case-sensitive linking;
  "option caseexact".

* To ease compiling for embedded targets, "#include <stdio.h>" is put
  first in all source files and socket.h/resolver.h. This may also
  speed-up generation and parsing of precompiled headers.

* timer.c change: New function `set_timediff()' should be called by
  user just after changing the DOS-time via some function;
  `_dos_settime()', `settime()' or `settimeofday()'. The argument to
  `set_timediff()' is number of milli-seconds added (>0) or subtracted (<0).

* getserv.c, gethost.c change: remove calls to `uninit_warn()' and
  instead call new function `netdb_init()' (in pcbsd.c). This function
  calls `sock_init()' in case it wasn't called beforehand.

* More variables are renamed by prefixing them with `_w32_':
    `_mtu'              -> `_w32_mtu'
    `_mss'              -> `_w32_mss'
    `my_ip_addr'        -> `_w32_my_ip_addr'
    `sin_mask  '        -> `_w32_sin_mask  '
    `_block_tcp '       -> `_w32_block_tcp '
    `_block_udp '       -> `_w32_block_udp '
    `_block_ip  '       -> `_w32_block_ip  '
    `_block_icmp'       -> `_w32_block_icmp'
    `_hostname'         -> `_w32_hostname'
    `_sock_inactive'    -> `_w32_sock_inactive'
    `_sock_datatimeout' -> `_w32_sock_datatimeout'
    `_sock_delay'       -> `_w32_sock_delay'
    `_multihomes'       -> `_w32_multihomes'
    `_usr_init'         -> `_w32_usr_init'
    `_mtu_discover '    -> `_w32_mtu_discover '
    `_tcp_nagle    '    -> `_w32_tcp_nagle    '
    `_tcp_keepalive'    -> `_w32_tcp_keepalive'
    `_ctrace_on'        -> `_w32_ctrace_on'
    `_arp_cache_data'   -> `_w32_arp_cache_data'
    `_arp_gate_list'    -> `_w32_arp_gate_list'
    `_arp_last_gateway' -> `_w32_arp_last_gateway'
    `_arp_timeout'      -> `_w32_arp_timeout'
    `_arp_alive'        -> `_w32_arp_alive'
    `_defaultdomain'    -> `_w32_defaultdomain'
    `_def_domain'       -> `_w32_def_domain'
    `_loc_domain'       -> `_w32_loc_domain'
    `_def_nameservers'  -> `_w32_def_nameservers'
    `_dns_timeout'      -> `_w32_dns_timeout'
    `_last_nameserver'  -> `_w32_last_nameserver'
    `last_cookie'       -> `_w32_last_cookie'
    `cookie'            -> `_w32_cookies'
    `cpu_type'          -> `_w32_cpu_type'
    `init_misc'         -> `_w32_init_misc'
    `inchksum'          -> `_w32_inchksum'
    `Random'            -> `_w32_Random'
    `valid_addr'        -> `_w32_valid_addr'
    `hex_chars'         -> `_w32_hex_chars'
    `hex_CHARS'         -> `_w32_hex_CHARS'
    `has_8254'          -> `_w32_has_8254'
    `init_timers'       -> `_w32_init_timers'
    `set_timeout'       -> `_w32_set_timeout'
    `chk_timeout'       -> `_w32_chk_timeout'
    `cmp_timeout'       -> `_w32_cmp_timeout'
    `hires_timer'       -> `_w32_hires_timer'
    `set_timediff'      -> `_w32_set_timediff'
    `time_str'          -> `_w32_time_str'
    `timer_set'         -> `_w32_timer_set'
    `timer_clr'         -> `_w32_timer_clr'
    `timer_chk'         -> `_w32_timer_chk'
    `calltimeout'       -> `_w32_calltimeout'


  The reason for this naming is to prevent name clashing with other
  libraries and forcing user to include <tcp.h> to get the correct
  name for symbols. Drawback is that most applications using Watt-32
  libs MUST be recompiled.

* connect.c change: set keepalive timer on DGRAM/STREAM socket after
  succesful connection.

* pcarp.c change: ARP-request is sent with ether destination address
  of 00:00:00:00:00:00 (not the link-layer broadcast address).

* pctcp.c change: calls to `reuse_localport()' changed to new function
  `maybe_reuse_localport()'. If tcp/udp-socket is owned by a STREAM/
  DGRAM socket, let `sock_deamon()' free the local port when linger
  period is over.

* receive.c change: Rewritten tcp_receive() loop to shorten the wait
  after FIN is received.  It previously introduced a 2sec delay. Now
  returns 0 when `tcp.locflags & LF_GOT_FIN' is non-zero, i.e. when FIN
  received *and* no un-ACK'ed data detected.

* tcp_fsm.c bug-fix: In `tcp_estab_state()' the ACK-number *after*
  `tcp_ProcessData()' was used in comparision with SEQ-number. It
  should be compared with ACK-number *before* it gets modified.

* tcp_fsm.c change: added local-flag-bit `LF_GOT_FIN' to `tcp.locflags'.
  Set when `FIN' received in `tcp_estab_state()', `tcp_finwt1_state()',
  `tcp_finwt2_state()' or `tcp_lastack_state()'. Used to determine when
  no more data is expected.

* signal.c change: Added `SIGQUIT' to signals to handle (djgpp).

* getprot.c bug-fix: `getprotobyname("tcp")' returned protocol entry
  for "udp".

* socket.c changes: A bit more robust checks for valid `protocol'.
  SOCK_STREAM accepts only `0' or `IPPROTO_TCP'.
  SOCK_DGRAM accepts only `0' or `IPPROTO_UDP'.

* pcstat.c change: Don't print statistics for zero-events.

* crit.c change: Turn off stack-check code generation.

* New file `.\inc\sys\swap.h' defines `intel()', `ntohl()' etc. as
  inline functions for GNU and Watcom compilers (all models).

* New files:
   `linkaddr.c' for functions in <net/if_dl.h>.
   `adr2asc.c' and `asc2adr.c' for functions in recent <arpa/inet.h>.

* misc.c changes: timer handling stuff moved to new module `timer.c'
  Cleaned up the namespace by prefixing several "internal" functions with
  `_w32_'.

* pcbuf.c changes: `sock_rbused()' etc. handles raw-sockets also (VALID_IP).
  Used by `ip_receive()' etc. to check for raw-socket data.

* wattcp.h change: New type `raw_Socket' added to `union sock_type'. This
  is for receiving raw IP-packets in the BSD-socket API.

* makefile.all/dos4gw.mak/common.mak changes: Use option `-zm' for Watcom
  targets. Thus causes each function to be put in a separate code-segment.
  Using `wlink' linker option `option eliminate' causes unused code to be
  removed.

* receive.c changes: Check for `SS_CONN_REFUSED' errors resulting from
  "ICMP Unreachable" messages while looping in `tcp_receive()' and
  `udp_receive()'.

* tcp_fsm.c change: In `tcp_finwt1_state()' simply unthread socket and
  enter `CLOSED' state if `LF_DONTLINGER' flag set.

* config.h changes: New defines for future additions:
    USE_LIBPCAP - Handle sockets of type `SOCK_PACKET' for receiving
                  all network traffic.
    USE_TTCP    - Support T/TCP (Transaction TCP) protocol.

* tcp_fsm.c change: Silently discard incoming `SYN' when listen-queue
  becomes full.

* pcconfig.c changes: Use buffered I/O (`fopen()', `fread()') for DOSX-
  targets when reading `WATTCP.CFG' config-file. Use `open()'/`read()'
  for non-DOSX (small/large) targets to conserve code and data.

* pcdbug.c changes: Fixed some bugs in address matching logic in
  `MatchEthAddr()', `MatchArpRarp()' and `MatchIpAddr()'.
  Rearranged for inlining some functions (GNU-C).

* signal.c change: djgpp 2.03 seems to support `SIGALRM' properly.
  Thus needs to rethink the signal catching logic.

* receive.c/transmit.c/accept.c/connect.c/select.c changes:
  Print signal-number when `setjmp()' catches a signal. djgpp might
  catch `SIGALRM' in these loops. Should we restart the functions?

* fsext.c change: Forgot to clear fd_sets before calling `select_s()'
  at `case __FSEXT_ready'.

* misc.c change: Removed "#ifdef" for BorlandC/TurboC in `_w32_time()'.
  Still don't know what the problem is.


******************* Changes version 2.1 *****************************

* misc.c changes: All timer routines now takes milli-seconds as argument.
  The `set_ttimeout()' routine is gone. This change affects all files that
  calls `set_timeout()'. Timer resolution falls back to 55msec if a 8254
  timer chip isn't found.
  In `_w32_time()' BorlandC/TurboC seems to require "lf" for arguments of
  "double" type.

* Removed file `ffs.asm'. `ffs()' is now included in misc.c for all targets.
  Even djgpp which had a buggy `ffs()' in djgpp <= 2.01.

* signal change.c: Handle also `SIGALRM' for those who have that (djgpp).

* select.c bug-fix: `timeval_diff()' did wrong calculation. Changed to
  return micro-second difference.

* connect.c change: `_nblk_connect()' sets/resets `socket->so_error' so
  that `getsockopt(..SO_ERROR..)' will return proper error when non-blocking
  connection fails. If non-blocking, `_tcp_connect()' sets `socket->so_error'
  to `EALREADY' in case user calls `getsockopt()' before calling `connect()'
  the 2nd time.

* version.c change: `wattcpVersion' changed to a function returning version-
  string.

* pctcp.h / wattcp.h changes: Removed `procref' typedef and made proper
  typedefs for protocol-handler and user-handler respectively. MS Quick-C
  v6.0 didn't handle function-pointers with undefined argument list.
  `ProtoHandler' is for handling udp and tcp-packets from `tcp_tick()'.
  `UserHandler' is for calling user-functions called from wait-loops in
  _ip_delay{0-2}. <tcp.h> updated accordingly.

* select.c changes: Reorganised and simplified. The criterias for a readable
  or writable socket is taken from BSD 4.4; This counts errors as valid
  events for read/write. Hence next recv() or send() will return the proper
  `errno'.

* receive.c change: In `tcp_receive()', don't set `SS_CANTRECVMORE' if
  socket is a listening socket (`SO_ACCEPTCONN').

* sys/socket.h change: `SOMAXCONN' increased from 5 to 32.

* Several changes regarding the listen-queue: listen() no longer allocates
  the listen-queue, it only remembers the backlog count in a new `Socket'
  structure variable.

  When a tcp-packet with SYN-flag set is received on the TCB of this listening
  socket (`SO_ACCEPTCONN' is set in `so_option'), then this TCB is first
  duplicated and if allocation and room in listen-queue, appended to a vacant
  slot in the listen-queue.  The `tcp_listen_state()' then continues to work
  with the copy of this TCB.  The original TCB is unchanged and accepts further
  SYNs on the same port.  The `accept()' loops over the listen-queue and
  creates a new socket (clone) from the first connected TCB.

* sock_ini.c change: Don't install exception handlers for 32-bit targets
  if environment variable "WATT32-NOEXC" is defined.

* config.h changes:  Because some preprocessors (Borland's among others)
  have problems with "#if (W_OPT & O_xx)" where `W_OPT' is > 16bit, all
  of these constructions have been changed to "#if (USE_xx)".
  New define `USE_LOOPBACK' to exclude loopback device for small-model
  targets.

* receive.c + transmit.c changes: Added macro `VERIFY_RW()' to start of
  functions.

* config.h change: New option `O_UDP_ONLY' for making more compact (small
  model) applications supporting only UDP (and IP+ICMP).

* pcsed.c change: Number of transmit retries (`_pktretries') reduced to
  2. The meaning of this variable is changed so that total number of
  transmit attempts in `_pkt_send()' is "_pktretries + 1".

* select.c change: Calling `_sock_start_crit()' and `_sock_stop_crit()'
  prevents `tcp_tick()' and hence `sock_daemon()' from deleting a socket
  from `sk_list' while we're in read/write/exc select functions.

* socket.c changes:
    - Return NULL in `_socklist_add()' on failed protocol allocations
      (`sock->tcp_sock' etc.). Prevents memory leaks and frees `sock'
      also. Tidy up also when djgpp's `__FSEXT_set_data()' fails.
    - New functions `_sock_start_crit()' and `_sock_stop_crit()' controls
      running `sock_daemon()' while in critical regions like in `select_s()'.
    - `tcp_sock_daemon()' "lingers" even when socket was reset or aborted.
      This is to prevent destroying sockets in loop where `sk_list' should
      be contant.

* accept.c changes:
    - Whole `accept()' function is defined as a critical region. Work now
      done in `_accept()' wrapped inside critical region.
    - `_sock_dup_bind()' clones the connection created by the listening
      socket. It's state is similar to it's parent, but defined as a normal
      `SS_CONNECTED' socket and not `SS_LISTENING'. Any data in the listen
      socket is moved over to the clone socket.
    - After cloning the listening socket in `_sock_dup_bind()', it must
      still be listening for further connections on the same port. Undo
      what `tcp_handler()' and `tcp_listen_state()' did to the listening
      socket.

* pcpkt.c changes:
    - Forgot to set Carry flag in `pkt_api_entry()' for non-debug version.
    - Support for WDOSX with any supported compiler (wcc386,bcc32,cl).
      DOSX4GW variable defined as (4|WDOSX).
    - Turn off/on stack-checking for bcc32 also.
    - `pkt_poll_arp()' didn't check for `_pktserial' and Ether protocol
      in non-debug version.
    - `pkt_poll_arp()' now tests for RARP protocol only in RARP version.

* New DOSX combination; WDOSX 0.96+ and Borland's BCC32. Hence renamed
  `watcom.[ch]' to `wdpmi.[ch]'.

* pcarp.[ch] change: Max number of gateways (`MAX_GATE_DATA') reduced
  to 5. `_arp_add_gateway()' now uses `qsort()' after adding gateway to list.

* close.c change: Added `sock_flush()' in `close_stream()' before
  closing socket.

* transmit.c change: Requirement for allowing to send in `tcp_transmit()'
  is now more liberal. Don't send if:
   - TCB-state is <  `ESTAB'.   i.e. not connected or listening.
   - TCP-state is >= `LASTACK'. i.e. FIN received and FIN sent.

* bind.c change: disallow binding `STREAM_SOCK' sockets to a multicast
  address.

* connect.c change: disallow connecting `STREAM_SOCK' sockets to a
  multicast address.

* transmit.c change: removed test on `MSG_WAITALL' in `tcp_transmit()'.
  Always send using `sock_write()' is more efficient and kept Nagle's
  algorithm in effect.

* wattcp.h change: `vj_sa' and `vj_sd' (Van Jacobson's RT algorithm)
  changed to DWORDs because of new milli-second timers. Adds 4 bytes
  to `tcp_Socket' in <tcp.h> also.

* misc.c change: new functions for milli-second timers taken from Phil
  Karn's KA9Q; `set_ms_timeout()' and `chk_ms_timeout()' works similar
  to `set_timeout()' and `chk_timeout()'. Only works with a 8254 PIT so
  only DOSX targets use these for RTT calculations. (PC/XT's may have
  an older 8253 PIT).

* config.h change: option `O_RARP' removed from `W_OPT' (i.e. added to
  `W_EXCLUDE'). I've never heard anybody using a RARP server and hence
  dropped it. Remember to "make clean" after upgrading to this version.

* pctcp.c + sock_ini.c changes: new function `tcp_post_init()' does
  various things after config-file has been read.

* .\bin\ changes: Added file `djcommon,mak' which is included in all
  `makefile.dj' files in sub-directories under `.\bin\'. djgpp users
  are now no longer required to have Borland's maker.exe to compile
  any binaries. Only free tools are used in the process.

* pcpkt.h + asmpkt4.asm change: `IP_BUFS' increased to 20 for DOSX
  targets. This seems to reduce dropped packets (`pkt_dropped()')
  experienced with the Netio test program.  But the Rx rate didn't
  increase noticably. Still some troubles with delayed ACKs in
  `tcp_Retransmitter()' I think.

* receive.c change: Replaced `kbhit()' with `__dpmi_yield()' for djgpp.
  This reduces CPU-loading under e.g. Win-NT.  Under plain DOS there's
  no problem catching SIGINT anyway.

* accept.c change: Replaced `kbhit()' with `__dpmi_yield()' at end of
  while-loop. This drastically reduces CPU-loading under e.g. Win-NT.
  It also makes it safe to interrupt a program (^C/^Break) without
  killing the DOS-box.

* select.c change: function `read_select()' will return 1 for a socket
  which is listening and which have sent ACK/SYN. Thus an `accept()'
  will block until the 3-way handshake is complete.

* pctcp.c and tcp_fsm.c changes: Integrated changes from Steve Lawson's
  `wat9909' RC5 package (October 1999);
  - Some fixes for `missed_seg' logic.

* pcmulti.c/pctcp.c changes: `is_multicast()' moved to pcconfig.c.
  Used in `tcp_handler()' to silentlt discard packets with Multicast
  source address.

* Makefile.all changed for Watcom-386 compilation to use register based
  calls (default). i.e. option `-3s' replaced with `-3r'. Also updated
  `.\bin\dos4gw.mak'.

* pcdbug.c changes: Dropped last SEQ/ACK from debug-file. It now prints
  changes in SEQ/ACK values ("dSEQ" and "dACK").  Last SEQ/ACKs sent and
  received are stored in tcp_Socket at `last_acknum' and `last_seqnum'.

* pctcp.c change: New function `tcp_upd_wind()' sends a receive window
  update to peer.

* Some djgpp programs in `.\bin\' assumed a math coprocessor was present.
  Therefore distributing the emulator `emu387.dxe' is required. I'm also
  looking into using `wemu387.dxe' instead.

* select.c changes:
   - select for exception condition set when state `SS_CONN_REFUSED' is
     set on socket.
   - Condition for setting `EPIPE' in `read_select()' changed to failed
     `tcp_tick()' AND no more data in receive buffer. This causes `EPIPE'
     to be set AFTER all expected data has been read.
   - `usec' and `elapsed' changed to use milli-sec in order to handle long
     timeouts (`long' overflow if `timeout->tv_sec' > 2147 seconds).

* socket.c change: `_TCP_listen()' sets a larger 16kB receive-window
  (`DEFAULT_RCV_WIN'). `_socklist_add()' sets `sock->so_state' to
  `SS_UNCONNECTED'.

* misc.c changes: New function `_watt_valid_addr()' for DOSX targets
  returns TRUE if address is within DS (data segment) limit. Used by
  BSD-socket API to return `EFAULT' (ref. macro `VERIFY_RW()').

* transmit.c changes:
   - Since transmission may take long time, call `SOCK_SIG_SETUP()'
     before transmit routines.

   - In `tcp_transmit()', use `sock_write()' if not enough room in
     tx-buffer. `sock_write()' will loop until all data is sent.

* sockopt.c changes:
   - Added handling of `getsockopt (s,SOL_SOCKET,SO_SNDBUF,..)' and
     `getsockopt (s,SOL_SOCKET,SO_RCVBUF,..)'. SOCK_DGRAM and SOCK_RAW
     does not have transmit buffers, so will return zero for these.

   - Handling `setsockopt (s,SOL_SOCKET,SO_SNDBUF,..)' copies any remaining
     data over to newly allocated buffer. Also clear rest of buffer.

   - Don't allow setting zero buffer size for SO_RCVBUF. Although allowed in
     BSD, the meaning to Watt-32 is unclear.

* pctcp.c changes:
   - `sock_write()' now tests for "if (written < 0)" (was "<=").
     This causes transmit error in `_eth_send()' to `return (0)' from
     `sock_write()',

   - Was wrong calculation of free space (room) in transmit buffer.
     It tested against `s->maxrdatalen'. Now changed to:
     `room = tcp_MaxTxBufSize - s->datalen'.  Thanks to Andreas Fisher
     <a.fischer@aicoss.de> for addressing these bugs.

* pctcp.c change: `udp_handler()' and `tcp_handler()' now returns matched
  socket for IP-packet.  Used to determine if peer allows IP-fragments to
  be sent.

* fcntl.c change: handles command `F_GETFL'; returns `O_NONBLOCK' if
  socket is non-blocking.

* accept.c changes: Contributed fixes from Claus Oberste-Brandenburg.
  New function `_sock_dup_bind()' to be used in creating listen-queued
  backlog in `listen()'.

* Reintroduced the config-option `O_USE_FSEXT' for djgpp. It may be
  desired to disable this for performance reasons etc.

* receive.c change: Extra test for timeout. Timeout only when no new
  data received AND no segments received within time limit.

* pctcp.c and tcp_fsm.c changes: Integrated several changes from Steve
  Lawson's upcoming `wat9909' package (Sept 1999);
   - Handling of missed segments. A new member in `tcp_Socket' remembers
     `missed_seg[2]'.


******************* Changes version 2.0 dev.rel.6 *******************

* pcdhcp.c changes: Added handling of option 52 (option overload) where
  options are present in `dh_file' and/or `dh_sname' fields.
  Parsing TFTP-server name and BOOT-file options for tftp.c module.

* New module tftp.c. Not finished because I didn't have access to a
  server with tftp-extensions. The idea is to be able to load *any*
  file from a TFTP-server after DHCP/BOOTP module have done their things.
  The function pointer `tftp_writer' must be set in order to store the
  file.

* pcpkt.c changes: The ARP-queue receives all non-IP packets.
  `pkt_poll_arp()' drops all if using serial-driver or packets who's
  Ether-type is not ARP or RARP.
  Allocating RARP-handle for receiving RARP-replies if compiling with
  `(W_OPT & O_RARP)'. This is default.
  ARP_SIZE (in pcpkt.h) is now set to (ETH_MIN+10). setup_pkt_inf()
  checks that ARP_SIZE could fit an ARP/RARP packet (plus margin).

* More changes for Watcom+DOS4GW extender;

   - bugfixes in asmpkt4.asm; pkt_enqueue() was buggy. And is now
     simplified. asmpkt.asm is now compiled as 16-bit `USE16' segment.
     Hope this doesn't produces fixup overflows. Segment `ASMPKT4_TEXT'
     should now be linked after `BEGTEXT' (in the AUTO group) to prevent
     this from happening.
   - `buf_size' for the ARP-queue was too small. Minimum ethernet size is
     60 which caused to buffers to be destroyed. `buf_size' is now set to
     `ETH_MIN + PKT_MARGIN'.

   - bugfixes in pcpkt.c; `asmpkt_inf' and `queue->buf_start' was in wrong
     format. Should be on `SEG:OFS' format. `queue->dos_ofs' is only used
     by real-mode asmpkt4.asm to calculate head pointer.

* wattcp.h change: added extra `safetytcp' field at end of `tcp_Socket'.
  tcp_handler()' checks both `safetysig' and `safetytcp'. Always print
  warning if markers destroyed.

* New files poll.[ch].  Function poll() is Linux-specific (to aid
  porting Linux applications to Watt-32). Taken from HTTP-tunnel,
  GPL'ed copyright Lars Brinkhoff <lars@nocrew.org>.

* pcbsd.c change: `_inet_addr()' updated to support dotless IP-address.

* udp_nds.c additions: added functions `isaddr_dotless()' and
  `aton_dotless()' to accept dotless IP-addresses;
  a.b.c.d = X = ((a * 256 + b) * 256 + c) * 256 + d.
  Functions requires that `a' and `d' must be non-zero.

* fcntl.c change: `fcntlsocket()' chains to `ioctlsocket()' for unknown
  commands so that calls like `fcntl (sock,FIONREAD,&length)' may
  succeed.

* signal.c change: don't set `wathndlcbrk' in `_sock_sig_setup()'.
  This hopefully prevents "Interrupting" from beeing printed while
  in BSD-function loops.

* transmit.c change: allow calling `udp_transmit()' without a local
  address. Only `SOCK_STREAM' requires `sock->local_addr' set.

* receive.c change: `udp_receiver()' sets up `socket->local_addr' if
  not done in `bind()'.

* sock_ini.c change: `ExcHandler()' for djgpp target calls `dbug_exit()'
  and `_sock_dbug_exit()' after `_eth_release()' has released PKTDRVR.

* Bugfix in pcdhcp.c, `arp_add_server()'. It was storing the Ethernet
  broadcast address to the ARP-cache for DHCP-server's IP-address.

* misc.c change: I don't trust gcc's handling of `register' variables
  in inchksum(). Hence will let gcc optimize use of local variables.

* pcpkt.c, pcarp.c, pcrarp.c changes for preliminary Token-Ring support.
  New HW-type `arp_TypeToken 0x600' in wattcp.h is used if `_pkttoken'
  is set in pcpkt.c. Never tried a Token-Ring driver so I don't know
  how this works in real-life..

* pctcp.c change: Added `s->err_msg = _LANG("Tx Error")' when `tcp_write'
  or `udp_write' fails in `sock_write()'. Also for UDP in `sock_enqueue()'.

* wattcp.h change: `tcp_Header' changed to use:
        BYTE   unused : 4;
        BYTE   offset : 4;
        BYTE   flags;
  instead of fumbling with:
        WORD   flags;
  Change affects tcp_fsm.c, pctcp.c, pcdbug.c and pcstat.c.

* pcsed.c change: Clear whole `outbuf.data' in _eth_formatpacket().
  Seems that when using serial-drivers (PPP,SLIP) we often cause
  TCP check-sum errors at peer's receiving side because small packets
  (< 60bytes) are not zero-padded.

* udp_dom.c change: dropped `num' argument from `send_dom()'. Put a
  random identifier in `q->h.ident'.

* sock_ini.c change: in `sock_exit()' don't call `dbug_exit()' if
  `watcbroke' is non-zero. I found out it's not a good idea to use DOS
  functions (in dbug_exit) after ^C/^Break is pressed. This may cause
  `_eth_release()' and `pkt_release()' never to be called. Hence will
  cause a hang on next pkt-driver upcall.

* pc_cbrk.c change: save original ^Break state. Restore state on exit.
  Increment `watcbroke' before calling `sock_exit()'.

* pcintr.c changes: updated for Watcom-386 + DOS4GW. Never tested though.

* Removed Borland C flag `-RT-' from `.\bin\common.mak' and `.\bin\makefile'.
  It's not understood by BC <= 3.1 and doesn't make a difference in BC >= 4.0.

* pcstat.c change: in `update_out_stat(), only count higher level
  protocols when IP is not fragmented or when fragment with offset 0
  is sent.

* pcpkt.c/asmpkt4.asm change: receive buffer length (_pkt_inf->rx_len)
  no longer needed. Now using CX value on 1st and 2nd upcall.

* pcdhcp.c change: Any configure DNS nameserver or gateways are deleted
  when `DNS_SRV' or `ROUTERS_ON_SNET' options are received from DHCP-
  server. Better to trust DHCP-server for correct network configuration
  than illegal `wattcp.cfg' data.

* loopback.c change: First call `_chk_ip_header()', then check if packet
  is fragmented. Return if fragmented and let `_ip_defragment()' handle
  it on next poll in `_pkt_poll_ip()'.  Last, check for ICMP "Echo Request"
  and return an "Echo Reply" to sender.

* sock_ini change: set default value for `_survivebootp' to 1 if
  O_DHCP is set.  set default value for `_survivedhcp' to 1 if
  O_RARP is set. Hence BOOTP, DHCP and RARP may be tried until an
  IP-address is obtained.

* pcbootp.c/pcdhcp.c changes: added parsing of option 7 (log-server).
  If syslog-host not specified in config-file, this host is used.

* syslog.c changes: added support for sending messages to log-host
  via UDP. New module `syslog2.c' contains config-parser and data.
  That way `syslog.c' isn't linked in by default.

* pcdbug.c change: Added keyword "DEBUG.STAT" to enable printing
  statistics counters to debug-file at program exit.

* pcpkt.c change: `pkt_enqueue()' will zero-pad remaining of buffer
  after copying to ring-buffer. This seemed to fix the tcp-checksum
  errors.

* sockopt.c change: The local-port fix below allowed socket option
  SO_REUSEADDR to be handled. calls `reuse_localport()' for UDP/TCP.

* pctcp.c changes: `findfreeport()' only tested for ports in use by
  UDP/TCP socket that where open. Since WatTCP goes to CLOSED state
  so quickly, the local port was reused too early. Thanks to Lynx
  which opens sockets all the time, I noted the local/remote ports
  where 1025/80 all the time. New routine `reuse_localport()' clears
  the inuse bit.

* pctcp.c changes: Rearranged some input checks in tcp_handler;
  tcp_chksum() moved after test for RST. Inactivity timer restarted
  before checking for RST.


******************* Changes version 2.0 dev.rel.5 *******************

* Fixed bug in gethost.c / `reverse_lookup()'. Didn't break loop on good
  result. Also in `resolve_ip()', the loop was broken on first fail; it
  didn't try next name-server.

* fragment change: Added TOS and IP-version in fragment matching.
  These must me same on all fragments. TTL and header length may differ
  for each fragment (IP-options).

* transmit.c change: `ip_transmit()' didn't use same IP-identifier if
  sending IP-fragments. New function `_get_this_ip_id()' (in ip_out.c)
  fixes that.

* New module fcntl.c contributed by Claus Oberste-Brandenburg.
  Integrated with djgpp's FS-extension feature (fsext.c).

* sockopt.c change: A bit more testing in setsockopt(). User may not
  set MSS less than 1 or larger than MAX_WINDOW (32767).

* pctcp.c change: Initial SEQ-number changed to use low-word from
  system timer. Previous version used high-word that caused problems
  with ISN reuse.

* misc.c change: Random() didn't work. Now uses mod operations and
  added more checks.

* pctcp.c change: in `udp_handler(): Don't send "ICMP Port Unreachable"
  when receiving "late" responses from DNS on UDP-port 53. Reason being
  that we closed UDP-socket in `lookup_domain()'.

* pcdbug.c change: New `atexit()' function `dbug_exit()' writes statistics
  counters to Watt-debug file before closing it.

* More changes for Watcom+DOS4GW extender;
   - added `dpmi_real_interrupt()' to watcom.c. `intr()' cannot
     be used to issue real-mode interrupt.
   - new module asmpkt4.asm for buffer enqueueing on packet-driver
     upcalls. This module implements the equivalents of `pkt_receiver_pm()'
     and `pkt_enqueue()'.
   - But there's still problems with DOS4GW port. Random crashes
     experienced !

* socket.c change: New function `_sock_dos_fd()' is used to determine
  if EBADF or ENOTSOCK should be set. If socket is a valid DOS-handle,
  then errno is set to ENOTSOCK, else errno = EBADF. Refer new macro
  `SOCK_PROLOGUE()'.

* socket.c change: failing `_sock_get_fd()' is no longer fatal.
  `errno' is not set when returning -1. Caller sets either ENFILE or
  ENOMEM.

* pcsed.c change: Watcom/DOS4GW target used a DOS-allocated buffer
  for transmission (outbuf). Now uses same static buffer as other
  targets. This improves reliability (cannot overwrite DOS-memory).
  The overhead of copying to DOS-memory (PKT_TMP in pcpkt.c) is
  neglible.

* Compiling with `gcc -Winline', revealed some functions in select.c
  and sockopt.c that couldn't be inlined. Thus removing `__inline'.

* pctcp.c change: new function `_get_machine_name()' called from
  `tcp_init()' tries to get host-name from a DOS network extension
  (NetBIOS, LANtastic etc) before `tcp_config()' parses `wattcp.cfg'.

* bsdname.c changes for better conformance to BSD:
    `gethostname()' returns the FQDN (Fully Qualified Domain Name)
    by concatenating `_hostname' + `.' + `def_domain'.

    `sethostname()' now expects a FQDN name. `_hostname' and
    `def_domain' are extracted from this name.

     `getdomainname()' and `setdomainname()' also changed. Doesn't
     touch `_hostname'

* buffer `buf' in sock_prn.c changed from static to auto.

* Compiled the djgpp version (libwatt.a) with gcc 2.9.5. This caused
  only one change; the linker map-file for .\bin\ programs is now
  printed to `stderr' and not to `stdout'. See `.\bin\common.mak' for
  use of `redir' command.

* Added support for "ICMP Address Mask Rquest/Reply" from RFC950.
  The value `sin_mask' (obtained from config-file or DHCP/BOOTP) is
  optionally checked with a "ICMP Address Mask Request".  A warning
  is given when the `sin_mask' and "ICMP Address Mask Reply" differs
  in value.

* Adapted `makefile.all' to accept option `W_OPT=0x????' be put on the
  make command line. If not specified, `W_OPT' is set to default value
  in `.\src\config.h'.

* Preliminary support for builing embedded targets. .\src\config.h
  specifies `O_EMBEDDED' for adding to the `W_OPT' variable. It's
  users responsibility to decide what code should be disabled for
  embedded targets. Sprinkle the code with "#if (W_OPT & O_EMBEDDED)"
  to include special embedded features; like making outch() send a
  character to a RS-232 port. Insert "#if !(W_OPT & O_EMBEDDED)"
  wherever you need to exclude things; like prevent calling file/disk
  related DOS-functions.

* Some C-files under .\bin\ had public function `Abort()' which clashes
  with same in Watcom's clib. Renamed to `Exit()'.

* Watcom large model now works. All .\bin\*.c programs compiled okay.
  But if compiling with `-s' (no stack checking), the programs all
  behave strange. Might be a register that should be saved.

* wattcp.h change of `in_Header': I discovered that Watcom handles
  bit-fields differently from others (GNU,HighC,Borland). The
  following caused `tos' to align at offset 2. Other aligned at 1:
      WORD  hdrlen: 4;
      WORD  ver   : 4;
      BYTE  tos;

  Now changed to:
      BYTE  hdrlen: 4;
      BYTE  ver   : 4;
      BYTE  tos;

  Which is what <netinet/ip.h> also does.

* pcicmp.c change: call `_udp_cancel()' or `_tcp_cancel()' on receiving
  `ICMP_PARAMPROB'. This is usually caused by error in the IP-header.

* pctcp.c changes:
    1) ensure correct structure packing on "struct _pkt" in _tcp_send()
       and udp_write().
    2) update of VJ algorithm, Karn count, RTT and cwin/wwin moved from
       `tcp_handler()' to new routine `tcp_rtt_win()'.

* asmpkt.asm change: Because Watcom assumes SS==DS in `pkt_enqueue()',
  we switch to a small work stack before calling.

* bug in pcsed.c caused ip-header not to be properly cleared.
  Was:
    BYTE *ip = SET_TX (&outbuf,data[0]);
    memset (ip,0,sizeof(*ip));

  Now:
    BYTE *ip = SET_TX (&outbuf,data[0]);
    memset (ip,0,sizeof(in_Header));

* socket.c change for djgpp: `_sock_get_fd()' calls `__FSEXT_alloc_fd()'
  to allocate a DOS-handle.  This is required if socket is to be used
  with e.g. `fdopen()' and normal stdio calls.  Checks are made to ensure
  the handle is < FD_SETSIZE.

* .\src\makefile.all updates for Watcom and Microsoft C compilers.

* pc_cbrk.c change: For djgpp; `set_ctrl_break()' simply calls
  `setcbrk (mode ? 1 : 0)' (D.Kaufman). Don't know if this works under
  Windows-NT; The NTVDM behaves different from plain DOS (or QEMM/EMM386).

* watcom.c change: added function `dpmi_cpu_type()'. Used by `init_misc()'
  before patching `intel()' and `intel16()' to use `bswap' instruction.

* pcpkt.c changes: DOSX targets didn't unlock the pages locked
  during init. Function `unlock_code_and_data()' now called last
  in `pkt_release()'.

* Rearranged pctcp.c: moved TCP state-machine, `tcp_ProcessData()'
  and `_tcp_reset()' to new module tcp_fsm.c.

* Preliminary LADsoft C v1.8 support; .\inc\sys\pack*.h updated.

* wattcp.h + pcdbug.c: removed `tcp_StateCLOSEMSL' (never used).

* Deleted .\src\pack*.h. Source/header files now includes
  "..\inc\sys\pack*.h"

* .\src\neterr.c change: forgot to include "borland\syserr.c" for
  Turbo-C <= 3.1

* Updated <netinet/tcp*.h> for BSD patches from PSC. (Pittsburg
  Supercomputing Centre).  These tcp modifications are for SACK
  (Selective ACK), FACK (Forward ACK) and TCP Auto-tuning. These
  features are not yet implemented though.

* sock_ini.c change: Give warning if `sin_mask' is zero. (caused
  by bad cfg-file).

* pcconfig.c change: Use `sin_mask = aton (value)' and not
  `sin_mask = resolve (value)'. Netmask should never be a name.

* .\src\tests\makefile and test programs rewritten for djgpp only.

* sockopt.c and pctcp.c changes: Added support for `SO_LINGER' option.

* socket.c changes: Added `udp->locflags |= LF_BROADCAST' after calling
  `sock_recv_init()'.

* pctcp.c changes: bitwise constructions like "foo &= ~bar" written
  as "foo ^= bar". I think this is more effective.

* Changed .\src\makefile.all for djgpp: replaced `-mpentium' with
  `-m486' in hope that everybody with djgpp now have at least a
  80486 CPU.

* fsext.c changes (djgpp only): handle reference counting for dup()
  and close(). Handle FS-extension for `fcntl (fd,F_SETFL, O_NONBLOCK)'
  and `fcntl (fd,F_DUPFD)'. Any else needed ?

* Removed files .\src\dgram.? (no longer used)

* syslog.c + printk.c added for syslog() API. Currentrly only prints to
  file. Later will print to log-server (cfg-file or DHCP/BOOTP log-srv
  option). These modules really belongs to the application layer, but is
  included in Watt-32 for convenience.

* `.\src\build.bat' renamed to `configur.bat' (to immitate Unix).

* Various updates to `makefile.all' to improve Watcom support.
  Rudimentary support for Watcom386 + WDOSX extender.

* language.l: fixed `lang_init()' to support beeing called multiple
  times to extend language entries from more than 1 file.
  E.g. application may also add language entries.

* sock_ini.c: removed macro `rand_seed()' and use `peekw(0,0x46C)'
  instead.

* socket.[ch]: New member `bcast_pool' in `struct Socket';
  for queueing UDP-packets for `INADDR_ANY' sockets (SS_PRIV state
  set). Used by `_recvdaemon()' when beeing called by `udp_handler()'.

* fsext.c: replaced `_sock_get_last()' with `fd+1'.
  socket.c: removed `_sock_get_last()'.

* sockopt.c changes: fixed handling of SO_RCVTIMEO/SO_SNDTIMEO:
  User cannot specify timeouts using `setsockopt()'. Only to get,
  e.g:
    struct timeval tv;
    getsockopt (sock,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv));

* socket.c: In `socklist_add()' don't set `sock->timeout' for UDP
  and raw sockets. This causes `UDP_DGRAM' sockets to never timeout
  on inactivity.

* Added `uninit_warn()' to gethost.c to help application developer to
  remember calling `sock_init()' before using critical functions.
  Especially `gethostbyname()' etc. are often called during init and
  hence these assert the `_watt_is_init' flag and call `uninit_warn()'.
  Maybe `sock_init()' should be called also?

* Changes to keep Watcom C happy: in pcdbug.c and sock_prn.c use `va_list'
  and `va_start' instead of the `(&format)+1' trick as last argument to
  _vbprintf/vsprintf.

* Changes to keep Watcom C happy: in transmit.c and misc.c, rewrite to
  not use cast on `lvalue'.

* Define `rand_seed()' macro for DOS4GW: `(*(WORD*)0x46C)'

* transmit.c, ip_transmit() change: added `tx_len += o_len' if socket
  has IP-options.

* receive.c change: In `udp_receive()' for `socket->so_state == SS_PRIV';
  condition for reception of broadcast packets is changed to:

    if (ret != 0 && peer.s_addr)
    {
      ..
      if (ret < 0)   /* 0-byte probe */
         return (0);
      return (ret);
    }

* bind.c/receive.c changes: Return -1 when `_UDP_listen()' fails.
  `errno = ENOMEM' already set.


******************* Changes version 2.0 dev.rel.4 *******************

* New utility tools in .\util: ERRNOS.C must be compiled with compiler
  of each vendor to produce a list of errno's and sys_errlist[] which
  also includes network related errno's. These lists are produced by
  .\src\build.bat and included in .\src\neterr.c and .\inc\sys\werrno.h

* .\util\mkdep tool now only searches for ".h" files.

* djgpp's FS-extensions for sockets moved to new module fsext.c

* Added call to kbhit() in select_s().

* gethost.c changes: Return `struct hostent' with `my_ip_addr' when
  gethostbyname ("my-host-name") is requested.

* ioctl.c changes: Added SIOCGIFMTU/SIOCGIFFLAGS support.
  Fixed SIOCGIFADDR/SIOCGIFCONF handling.

* Handle special situation when UDP sockets (SOCK_DGRAM) is bound
  to an INADDR_ANY address. Wattcp's `udp_handler()' doesn't store
  address information for broadcast.

  Fix _UDP_listen() to call `sock_recv_init()' which makes sure
  SOCK_DGRAM messages received as broadcast are queued.

  In `receive()', we poll this queue using `sock_recv_from()' or in
  `select_s()' using `sock_recv_used()'.  Thus the `*from' address in
  `receive()' will be correctly set to peer's address ip/port.

* Cleaned out all tabs from .c/.h files. Tabs are evil :-)

* select_s() now terminates the poll-loop if timeout expires
  before we had time to poll all requested sockets. This makes
  the logic for `cnt > 0' AND timed-out much easier.

* Allow bogus IP-packets in `_ip_raw_peek()'.

* Allow SOCK_RAW sockets to call `send()', `sendto()' and `write_s()'
  withhout a `socket->local_addr' filled in.

* gethost.c changes: Added expiry of cached values stored in
  `gethostbyaddr()' and `gethostbyname()'. Configurable timeout
  (default is 15min).

* Moved all build options defined in W_OPT to new file config.h.
  config.h is included in wattcp.h.

* New module nettime.c. Implements net_times() to return "user"
  and "system" time. System time is time-ticks used in BSD-sockets
  calls.

* Added check for "addrlen < sizeof(struct sockaddr_in)" in some
  places. Set `errno = EADDRNOTAVAIL' if fails.

* Added timer for SOCK_STREAM sockets before they are deleted from
  linked list. Times out after `sock_delay' (30) seconds.

* pcconfig.c changes: Added `is_ip_brdcast()' function.

* New module ip_out.c. Routine `_ip_output()' builds the IP-header
  and transmits it.
  Notes:
    Contrary to most Wattcp function, arguments `srp_ip' and
    `dst_ip' are on network-order (big-endian). Arguments `sock',
    `file' and `line' are only used for packet-debugger (in pcdbug.c).

* receive.c changes: store AF_INET in `from->sin_family'.
  Added routine `udp_raw_fill_from()'.


******************* Changes version 2.0 dev.rel.3 *******************
  
* transmit.c change: Sets ENOMEM if alloca() fails in writev_s().

* bind.c change: Don't change `sin_addr' to our IP-address when
  binding locally.

* connect() sets errno = EHOSTUNREACH when ARP fails.
  Not ENETUNREACH as previously.

* recv(), recvfrom() and read_s() returns -1 and errno = ENOTCONN when
  socket-state SS_CANTRCVMORE is set.

* select_s() now returns when all sockets (s < num_fd) are checked.
  Not when first count gets set.

* select_s() didn't do FD_SET on output. Set correct bit for socket
  when read, write or exception event fullfilled.  Under djgpp,
  call _dpmi_yield() in select loop.

* tcp_receive() refinement: return 0 when FIN received.
  Don't set errno.

* pkt_send() and _eth_send() returns length of data sent.
  sock_write(), sock_enqueue() returns 0 immediately if
  transmission fails (pkt_send() returns 0).

* TCP-debugger changes: ACK/SEQ-numbers written as decimal.
  This makes it easier to look for retransmissions.

* Didn't stop RTT-timer in tcp_Retransmitter(). This caused aggressive
  retransmissions (which caused congestion).
  Uses `sock_delay' for `tcp_LONGTIMEOUT' when opening a connection.

* gethostbyaddr() returns my_ip_adr and hostname for INADDR_ANY (0.0.0.0)
  gethostbyaddr() returns "broadcast" for INADDR_BROADCAST or limited
  broadcasts adresses.

* Fixed __ffs() function (in ffs.asm).
  Added __ffs() (in misc.c) for djgpp 2.01 or older.

* Added handling of SO_KEEPALIVE in tcp_sock_daemon().


******************* Changes version 2.0 dev.rel.2 *******************

* socket() returns -1 with errno = ENETDOWN when no network-driver
  (pktdrvr) is found. Previous action was to exit the program.  -GV

* Changed sock_init(), tcp_init(), _eth_init() and pkt_init() to return
  non-zero if they fails. (to support above change). Error codes (WERR_x)
  are in sock_ini.h.  -GV

* 'sock_setdebug(FILE*)' removed. Instead controlled by WATTCP.CFG keyword
  SK_DEBUG.DEVICE and 'sockopt(s,SO_DEBUG,..)';


*******************  version 2.0 dev.rel.1 *******************

- - -
General Changes                    (12/12/1998)

    Version 2.0 dev release 1.

    Changes for Watt-32 are too numerous to list in detail here.

    Watt-32 supports these compiler environments:

      GNU C/C++ 2.7 (or later) with djgpp2 DOS-extender.
      Metaware HighC 3.x with PharLap DOS-extenders.
      Borland C/C++ 4.x (or later), small/large model, real-mode.

    Provision for Watcom-386, MS Visual C 1.52 and MS Quick-C is included,
    but mostly untested.

    These are some of the new functions of Watt-32:

    DHCP-client: An RFC-1541/2131 compliant DHCP-client allocates
      an IP for you, sets the netmask and gateways etc. User doesn't need to
      configure wattcp.cfg.

    RARP-client: Dan Kegel contributed a RARP-client which tranlates your
      EtherNet address into a usable IP-address.

    ICMP-redirect: Watt-32 automatically switches gateway if an ICMP-redirect
      is received.

    PPP-support: Watt-32 supports both types of PPP-drivers;
      i.e. types that emulate EtherNet frames and those who don't.
      Antonio Lopez Molero has written the excellent DOS-PPP driver that
      works very well with Watt-32. Get
      ftp://ftp.gui.uva.es/.1/pc/freedos/files/internet/dosppp/dosppp06.zip

    Protocol debugger: A much improved protocol debugger/tracer
      analyses IP (ICMP, UDP and TCP) and ARP/RARP packets to/from your host
      (or broadcast). Various headers can be filtered. DNS-records and IP/TCP
      options are also shown.

    BIND Resolver: A port of the Unix resolver library. This was
      added mainly to implement the getmxbyname() function.

    File based lookup: User may specify fixed IP/names in a hosts
      file.  All the getXbyY() functions from <netdb.h> are
      supported.
 
    BSD-Sockets: Watt-32 tries to mimic the BSD-socket API with
      support for SOCK_DGRAM, SOCK_STREAM, SOCK_RAW, blocking and non-
      blocking I/O. Most header files required to port Unix network programs
      to WatTCP/DOS is provided. This API needs some work to improve transfer
      rate, compliance to the man-pages etc. But it is currently used to
      built the Lynx Web-browser (see http://sol.slcc.edu/lynx/current/)


    1. I've tried to keep the original names on most appliciation-specific
       function, but a few presented too much trouble when porting BSD-Unix
       applications to DOS:

         Old name:          New name:
         getsockname()      _getsockname()
         getpeername()      _getpeername()
         inet_ntoa()        _inet_ntoa()
         inet_addr()        _inet_addr()

       The BSD versions getsockname() and getpeername() are implemented in
       netaddr.c

       Remember: Most (all?) BSD-style network functions use network order
         (i.e. big-endian) quantities as opposed to WatTCP which use
         host order (little-endian) as parameters to all functions.
         Take great care when mixing generic WatTCP functions and
         BSD-style functions.

    2. chk_timeout() returns 0 if argument (timeout) is 0. This is to
       update the 'date' variable more often. Since 'set_timer()' and
       'set_ttimer()' can never return 0 for active timeouts, I regard
       this as safe.

    See readme.too for additional changes.

    -GV, Gisle Vanem <giva@gnett.no>

- - -
General Changes                     (7/16/93)
    I did a lot of cleaning up to make this compile more nicely and
    more than a year's worth of bugs have been fixed.

    Several areas underwent protocol optimization to significantly
    improve performance under certain circumstances.  Noticable
    enhancements include SLIP support and fragments reassembly, but
    the latter is currently disabled as I introduced a bug.

- - -
General Changes                     (3/31/92)
    This update has a lot of little bug fixes, optimizations and
    general improvements thanks to a lot of people's input.  In
    particular, Jason Dent and Graham Robinson (author of PKTMUX10).

1. Push bit handling is improved.  This is mostly necessary for 3270
   protocols, most others treat tcp as a simple binary stream.

2. Zero window probing has been fixed.  This will keep things rolling
   even when the remote machine is swamped and the network becomes lossy
   around the same time.

3. A bug in the ASCII tcp stuff was introduced on my site this month
   and has been fixed.  I don't know if the bug was on my old distribution.

4. Significant changes were made to the internal handling of acknowledgements
   and handling data within the receive window.

5. A bug used to annoy SCO and possibly other system consoles - fixed.
   When WATTCP wished to refuse unwanted sessions from remote systems, it
   would be missing a small flag.  Most tcp's didn't notice this flaw.

6. Type of Service flag now RFC compliant - currently unused in non-military
   installations, this flag could be used to set priorities for TELNET
   sessions versus bulk data transfers like FTP, particularly over slow
   lines.  Phil Karn (Mr. KA9Q) is currently researching this area and
   so this upgrade should make WATTCP code react properly (unlike SunOS, BSD,
   etc.) in sites which use his TCPs.

Erick

- - -
Speed/Performance               (1/04/1992)

    The tcp code has undergone some mods to make it much faster, with
    reads up to 120 kilobytes/s and writes up to 42 kilobytes/s on the
    same subnet as my Sun.

    These speed were great, but my pc is usually on a subnet.  There, the
    speeds were about 26 kB/s in writes and 70 kB/s in reads.

    For read's I was able to use good old sock_fastread.  For writes,
    sock_fastwrite / sock_write just don't cut it because they are limited
    to the small buffer size located in the tcp_Socket structure.

    I've added a new call which let's you get around that limitation,
    sock_enqueue().  This new routine let's you specify a buffer of data
    you wish to enqueue for transmission.  WATTCP records the address of
    that buffer and its length, and starts to transmit it according to
    the TCP rules.  You are not allowed to touch that buffer until all
    the data is fully transmitted, something you can tell by using the
    sock_tbused( s ) until it returns zero.  You must also keep calling
    tcp_tick() or sock_tick() as those routines schedule transmissions.


    Here is some sample code which writes out a disk file:

    tcp_open...
    f->dhanle = open( ....
    ...
    while ( 1 ) {
        /* check connection and do background stuff */
        if (tcp_tick( s ) == 0) break;

        /* see if we can schedule more data */
        if ( sock_tbused( s ) == 0 ){
            printf("disk reading %u bytes\n", ftpdbufferlen );
            if ((diff = read( f->dhandle, ftpdbuffer, ftpdbufferlen )) <= 0 ) {
                /* eof or possibly error condition */
                break;
            } else {
                /* data ready to send */
                sock_enqueue( s, ftpdbuffer, diff );
            }
        }
    }

    close( f->dhandle );
    sock_close( s );
- - -
SMTPSERV  (in separate file: SMTPSERV.ZIP)

    This program accepts inbound mail and places it into mail spool files
    almost identically to the way Phil Karn's NOS does.  You can download the
    executable in pub/wattcp/smtpserv.zip.  If you find it useful or wish
    to have it changed, let me know.

-----------------------------------------------------------------------------

Large Model                     (9/13/1991)
    You can compile large or small model applications.  Check out the
    MAKEFILE in the .\APPS subdirectory to see how easy it is to switch.

    The fullsrc.zip collection automatically produces large and small
    model libraries.

    There is a potential problem when you compile applications because
    you make the same mistake I did and place tcp_Socket on the stack
    by declaring it an automatic variable.  The 'C' stack is normally
    only four K, slightly less than the tcp_Socket structure.

    I didn't figure this one out very quickly, so tcp_open, udp_open,
    and tcp_listen have code to warn you immediately and exit in case
    you forget.

-----------------------------------------------------------------------------

TCP Fixes                       (9/13/1991)
     The TCP portion of WATTCP has had numerous improvements.  I've managed
     to significantly reduce the packet count while improving performance
     and reliability.

-----------------------------------------------------------------------------

New Wattcp Programs
     The latest release of MS-Kermit includes the WATTCP kernel, letting you
     use it as a TELNET program.  I do not know where the ftp site is,
     but it will probably be announced soon on Comp.protocols.tcp-ip.ibmpc
     in the near future.

     LPD is a line printer server which will let a PC accept jobs from UNIX.
     It offers some simple device restriction capabilities.  You can spool
     jobs out any DOS file or device.  It requires a little few lines
     of work to be used at any site other than mine.  It is available

     COMD.EXE is a simple program can be used to allow network access to
     RS232 devices.  With a little work it could be converted into a modem
     pool.  It is available from [129.97.128.196] pub/wattcp/comd.zip.

     If you have any improvements or new applications, please let me know.
     I will gladly distribute them for you.

-----------------------------------------------------------------------------

Nested Config Files             (7/16/91)
    Wattcp config files may be easily nested to allow for centralized
    control of most parameters with local overrides, or user specific
    extensions.

    To include a nested config file, use the following line in the
    main config file:

        include = filename
    eg. include = c:\local.cfg

    If the local file could not be found, a warning message is displayed.
    You may wish to use a local file if it exists, but not display a message
    if it does not.  To do that, simply prepend the filename with a question
    mark.

    eg. include = ?c:\local.cfg

    When the nested file is complete it will return to the main file.

    The nesting limit is dependant upon the number of unused file handles
    and the stack size.

-----------------------------------------------------------------------------

TCP/UDP Packet Dumps            (7/10/1991)
    TCP/UDP packet dumping features have been added and may prove useful
    for testing and debugging your applications.

    The debugger dumps packets, which gives you a feel for what the
    kernal and the other end are trying to do.

    It's my job to try to make things go as fast as possible with as
    few packets as possible (least load).  Actually, when you use the
    dumping feature you usually INCREASE the packet count because the
    dumper takes time which times out the scheduler and causes
    retransmits.

    To include the debugging features in your program, add the line
        dbuginit();
    to your program *before* you call sock_init();

    To enable/disable the debugger, include the following lines in your
    WATTCP.CFG file:
        DEBUG.FILE=somename     # otherwise it will open a file called
                                # WATTCP.DBG in the current subdirectory
                                # somename could be con which will dump
                                # to the screen
        DEBUG.MODE=DUMP         # to dump TCP/UDP data, looks a bit like
                                # DEBUG.COM
   or   DEBUG.MODE=HEADERS      # to dump TCP/UDP headers
   or   DEBUG.MODE=ALL          # to dump everything, headers and data

   You may write some textual data directly to the file.  Remember, you
   must send a 'C' string ending with a 0, and you must include your
   own CRLFs.

        db_write( char *msg );

   NOTE: If you use this feature and you also use usr_init, you
         must chain usr_init as described in the programmers manual,
         and as show in TCPINFO.C.

-----------------------------------------------------------------------------
Good UDP Support                (6/5/1991)
   Initially, only standard socket calls could be used for UDP.  That was kind
   of shabby because UDP tends to be higher traffic, has no flow control, and
   you wish to know record boundaries.

   The new code allows you to declare a big buffer into which the incomming
   UDP packets will be bufferred.  Once initialized with sock_recv_init, the
   buffer is used until the socket is closed.  NOTE: sock_recv... and the
   regular socket input routines are MUTUALLY EXCLUSIVE, you can not use
   one and the other at the same time.  

        byte bigbuf[ 8192 ];
        byte smallbuf[ 512 ];
        int templen;

        if ( !udp_open( &data, localport, remote, remoteport, NULL) ) {
            printf("Error opening UDP channel");
            exit( 3 );
        }
        /* set the big buffer */
        if ( sock_recv_init( &data, bigbuf, sizeof( bigbuf )) == -1 ) {
            printf("Error setting the receive buffers");
            exit( 3 );
        }
        while ( 1 ) {
            tcp_tick( NULL );           /* got to do this or sock_tick */

            /* check for incomming udp data */
            if ( templen = sock_recv( &data, smallbuf, sizeof( smallbuf ))) {
                /* something received and it was templen bytes long */
            }
        }
        sock_Close( &data );

   sock_recv... adds extra code, so it need not be used for simple UDP sockets
   such as BOOTP which expects only a single packet.

   See sock_mode checksums below for more interesting notes.

-----------------------------------------------------------------------------
UDP Checksums                   (6/5/1991)
   sock_mode can be used to enable or disable checksums for udp sessions
   using the following calls:

        sock_mode( &socket, UDP_MODE_CHK );
        sock_mode( &socket, UDP_MODE_NOCHK );

   Unlike *some* systems, Waterloo TCP correctly assumes checksums are active
   and allows an application to disable them on the fly as they consider
   appropriate.

   Either or both sides may disable or re-enable checksums.

-----------------------------------------------------------------------------
TCP Nagle Algorithm             (6/5/1991)
   The Nagle algorithm is now used to collect data.  Nagle is ideally suited
   to programs like TELNET (TCPPORT), etc. which send a lot of small chunks
   of data.  Some programs, like X-Windows, real-time data collection, etc.,
   should turn of the Nagle feature.  Nagle is on by default and should not
   be disabled unless a true problem is experienced.

        sock_mode( &socket, TCP_MODE_NONAGLE ); /* turns it off */
        sock_mode( &socket, TCP_MODE_NAGLE );   /* re-enables it */

-----------------------------------------------------------------------------
getdomainname Changes           (6/5/1991)
   getdomainname always took a string and length parameter, just like UNIX.
   Now, if the length is zero, getdomainname just returns the pointer to
   a system copy of the domainstring.

-----------------------------------------------------------------------------
gethostname sethostname Changes (6/5/1991)
   gethostname and sethostname are now available.  They work identically to
   get/setdomainname() (as enhanced above).  The host name can either be set
   via the WATTCP.CFG file or via bootp.
-----------------------------------------------------------------------------

sock_PreRead addition           (4/26/1991)

   int sock_PreRead( void *s, byte *dp, int len );

   Some situations arise where it would be nice to read data without causing
   it to disappear from the socket's buffer.  Usually that means double
   buffering.  sock_PreRead works exactly like sock_FastRead, except it does
   not remove the read data from the data buffers.  The returned value is the
   number of bytes transferred, 0 for no data waiting, or -1 on a socket
   error.

   This function is intended for special cases which are not easily performed
   using other methods.

-----------------------------------------------------------------------------

sethostid addition              (4/26/1991)

   longword sethostid( longword ip );

   This function sets the system's default ip address.  Changing the ip address
   will destroy existing TCP and UDP sessions.  You should close all sockets
   before calling this function.  The passed ip address is always returned.

   This function is low level and rarely useful to an application programmer.

   main()
   {
       longword ip = 0x80010101;   /* 128.1.1.1 */
       char buffer[ 512 ];

       sock_init();
       sethostid( ip );
       printf("IP address has been set to %s\n\r",
           inet_ntoa( buffer, getipaddr() );
   }

-----------------------------------------------------------------------------

setdomainname addition          (4/26/1991)

   char *setdomainname( char *string);

   The domain name returned by getdomainname and used for resolve() is set to
   the value in the string passed to setdomainname().  Note that changing the
   contents of the string after a setdomainname() call may or may not change
   the value of the system domain string and is not recommended.  You are
   recommended to dedicate a static location which will permanently hold that
   name.

   setdomainname( NULL ) is an acceptable way to totally remove any domain name
   and subsequently resolves will not attempt to append a domain name.

   The passed string is always returned, as demonstrated below.

   This function is low level and rarely useful to an application programmer.

   #include <stdio.h>
   #include <tcp.h>
   char buffer[ 512 ];  /* use a static or a calloc, do not place the name
                           in a local variable on the stack, it may get lost! */
   main()
   {
       sock_init();
       puts("Enter a new domain");
       gets( buffer );
       printf("Was using %s\n\r", getdomainname());
       printf("Now using %s\n\r", setdomainname( buffer ));

       setdomainname( NULL );
       puts("Now using no domain name");
   }

-----------------------------------------------------------------------------

_arp_resolve addition           (4/26/1991)

   _arp_resolve( longword ina, void *ethap)

   Given an ip address (ina), find the hardware address.  If ethap is non-NULL,
   place the hardware address in the buffer pointed to by ethap.

   Each call to _arp_resolve checks a local cache to see if we already know
   the hardware address.  If no entry exists for that IP address, steps
   are taken to find a hardware address.  If the ip node is on our subnet,
   an ARP request is broadcast, otherwise _arp_resolve is called recursively
   to find the address to the gateway.

   Socket opens intrinsically call _arp_resolve and place the hardware address
   in the socket structure so they are no longer dependant upon existance in
   the cache.  This means existing tcp and udp sessions do not automatically
   reconfigure if a new route is found to the remote host, but this is typical
   of pc implementations and is quite reasonable.

   Programs which wish to force the hardware address to be in the arp cache
   need only specify the ip address and NULL for the ethap buffer.

   Returns 1 on success or 0 if the ip address could not be resolved.

   This is a special use function and is rarely necessary for user
   applications.

-----------------------------------------------------------------------------

