AmiNetXDuo 0.25.0 (NetX Duo 6.5.1, ThreadX 6.5.1)
AmiNetXDuo 0.25.0 (NetX Duo 6.5.1, ThreadX 6.5.1)
Drop AmiNetXDuo-0.25.0.lha on a Workbench
window and run Install-AmiNetXDuo.
-
A DHCPv6 lease is renewed once, when it is due, rather than rebound twenty-five times a second forever. A server that answers with T1 and T2 of zero is telling the client to pick its own renewal times; the client read zero as "renew now" and re-entered the rebind state on every pass, which also meant a renewal never actually reached the wire and the address's lifetime shrank each time. On the lab's network that was 2544 rebinds in five minutes, and is now none
-
The remote desktop shows the screen and not the memory beside it. A graphics card rounds a screen's bitmap up to the board's own pitch, and the console took its width from the bitmap, so a 1368-pixel-wide screen was served as 1600: two hundred and thirty-two columns of whatever the card had off the right-hand edge, on every frame, and seventeen per cent more data to send than the screen contains. A planar screen had the same, rounded up to sixteen
-
An encrypted connection is three to five times faster and no longer takes the machine off the network while it runs. A 4096-bit certificate -- which is what every Let's Encrypt chain ends at -- was handed to the reference arithmetic instead of the 68k routines, one silent block of about ninety seconds per handshake, and the routines that did run gave the rest of the machine a turn only seventeen times in an operation.
fetch https://www.gnu.org/goes from 100 seconds to twenty or thirty, and a machine that used to stop answering for its own address for a minute at a time now answers throughout -
NetSetupno longer writes uninitialised memory into the interface file. A call that did not passIPV6=emitted aCONFIGURE6line holding whatever was on the stack, into a file the stack reads on the next boot -
A DHCP server's domain is accepted in the forms servers actually send it: an underscore, which a great many consumer routers use, and the fully qualified form ending in a dot, which is stored without it. Refusing either left the machine with no default domain and no search suffix at all, because both come from that one option
-
A malformed DHCPv6 option no longer costs the client the configuration it already had. The DNS servers and the search list are now replaced only after the whole message has parsed, so one bad option in a Reply cannot leave the machine with neither
-
A DHCPv6 exchange that fails on a new network no longer republishes the previous network's DNS servers, and a setup that fails once no longer disables DHCPv6 for the life of the machine
-
A DHCP option that could not be read asks to be read again on the next pass, for the host name, the domain and the search list as well as the servers. One that can never succeed keeps what it has and says so once, rather than retrying forever
-
A router's advertised DNS servers and search domains expire when their lifetime runs out, and belong to the interface and the source that advertised them, so one card's advertisement no longer withdraws another's
-
Multicast name service clears its cache when asked, keeps a browse alive while more than one program is using it, retries a publication that failed, and gets its goodbye onto the wire at shutdown. A lookup across two cards no longer spends the whole timeout on the first
-
A second network card that cannot attach is dropped rather than taking the whole stack down, and
AddNetInterfacekeeps a card that could not get a link-local address instead of removing it -
telnetto a name whose first address does not answer no longer takes three minutes. The retry now draws from the timeout the caller asked for rather than starting a fresh one -
nslookupreports a record it cannot read and carries on, rather than abandoning the answer -
httpdserves a drawer containing a name too long to list, minus that entry, instead of dropping the connection for every client that asks -
The WebSocket console refuses malformed control frames, oversized control words and invalid UTF-8, and keeps pipelined input under backpressure
-
getnameinfo()no longer fails when the port has no name inDEVS:Internet/services. The flag that requires a name is about the host, and the peer's port on an accepted connection never has one -
The release archive contains
C:sshagain. The packer only copied a client somebody else had built, so an archive made any other way was simply missing it -
A connected UDP socket becomes readable again. The readability test and
FIONREADread the source port from a packet still on the receive queue, where the UDP header has not yet been stripped, so the port never matched the peer and the socket looked permanently empty;sntptimed out on every attempt andiperfin UDP mode burned each slice -
FIONREADon a datagram socket reports the payload without its UDP header, and agrees with what a peeking read returns -
A UDP socket reports an ICMP error as readable and clears it through
SO_ERROR, instead of leaving a program waiting for a datagram that will never arrive -
A datagram socket honours
shutdown(): a socket shut down for reading reports no bytes, and the disconnected state is consistent between two tasks looking at it -
A UDP or raw socket only accepts what its bind and its connect name. Datagrams from other peers, and to other local addresses, were delivered to a socket that had asked for one endpoint
-
An IPv6 link-local address keeps its zone through bind, connect, accept and receive, and a local zone is no longer confused with the peer's. An address on a machine with two cards named whichever interface the stack looked at first
-
IPv6 multicast honours the scope zone of the address, and a UDP disconnect clears the zone it was using
-
The path MTU is measured on the interface actually selected for the destination, not the first one
-
getnameinfo()withNI_NAMEREQDreturns the numeric port when the service has no name. The flag is about the host half -- the peer port on an accepted connection is ephemeral and is never inDEVS:Internet/services, so the whole call failed and the caller lost the host name that had in fact resolved -
Undefined flags to
getnameinfo()are refused rather than ignored -
A TCP socket reports its queue depths correctly. The receive walk followed a field that holds a sentinel on a ready packet -- an odd address, so a
NetStatusquery on a socket with two or more queued segments took an address error -- and Send-Q counted headers as application data -
Encrypted connections work above descriptor 255, no longer race two tasks creating a session at once, and honour
nfdswhen waiting on buffered data -
A resumed encrypted session is bound to the parameters that were cached with it, so it cannot come back with different ones
-
The router-advertised DNS servers and search domains expire when their lifetime runs out, and are owned per interface and per source, so one card's advertisement no longer withdraws another's
-
A DHCP lease's DNS servers, host name, default domain and search suffix are reconciled against what the lease actually offers, and a server withdrawn from a renewed lease is withdrawn from the resolver
-
A statically configured DNS server survives a lease withdrawal
-
Multicast service discovery retries a publication that failed, reports every publication failure rather than the first, keeps a shared browse alive while more than one program is using it, and gets its goodbye onto the wire at shutdown
-
A multicast name lookup across two cards no longer spends the whole timeout on the first one
-
httpdconditional requests compare entity tags exactly, distinguish weak from strong, and keep a complete tag list rather than the last entry -
httpdparses byte ranges without guessing, and refuses a malformed request version, a malformed header field name, an unsupported expectation, an undelimited transfer coding and an invalid WebDAVOverwritedirective -
httpdkeeps the old file until its replacement is complete, never truncates an existing file to hold a temporary, and reports a failure on the final write instead of returning success -
httpdrefuses aMOVEorCOPYwhose destination is inside its source, never deletes the source after a partial copy, and refuses a name it would have to truncate anywhere in the tree -
httpdaborts a directory listing when the scan fails, rather than serving the part it managed to read as though it were complete -
httpdmatches a WebSocket negotiation token exactly and requires an exact takeover query -
The WebSocket console rejects a non-minimal frame length, a prohibited or malformed close code, invalid UTF-8 in a text message or close reason, and enforces the message ceiling across a fragmented message
-
The WebSocket console keeps pipelined input under backpressure, evicts only at a frame boundary, preserves a queued close over a ping, and stops polling an input socket that is blocked
-
telnet,whoisandnettracefinish a write that the stack accepted only in part, instead of sending a truncated request -
telnetrenders a bare carriage return as the NVT defines it -
nslookupconfines a name to its own RDATA field, so a malformed record cannot read past it -
tftpremoves a partial download when the local write fails, and accepts the transfer port only from the server it asked -
ncandiperfhonour IPv6 for a wildcard listener and in server mode;iperfignores a truncated UDP datagram and pins a UDP run to its first peer -
nctimes out a UDP listener that never receives a first datagram -
Every command-line tool refuses a negative or overflowing numeric argument -- timeouts, units, ports, scope indices, port ranges, capture geometry and workloads -- rather than narrowing it into something else
-
A service entry without a protocol, an oversized protocol number and an oversized service port are refused by the name database
-
SIOCGIFCONFreports the bytes written when given a buffer, so a caller cannot walk past the end of a short one -
Socket option buffers that are not aligned are tolerated rather than read as though they were
-
A socket timeout of a full day no longer wraps, and a finite wait is charged the time it has already spent
-
A raw or packet-filter channel is safe to use from two tasks at once: interface replacement is transactional, and property, readiness, sizing and signal-mask queries are taken under the lock
-
The SANA-II layer bounds a receive to the data actually copied, and reaps writes after the final drain
-
The
AddNetInterfaceandConfigureNetInterfacetools honour a hardware address and an initialisation delay supplied at run time -
make-dist.shbuilds what is missing instead of describing the commands and stopping -
A certificate that is not allowed to be used the way the connection needs is refused. A leaf's keyUsage was never checked, so a certificate marked for encryption only, or for signing only, was accepted for either; a program is now told which of those it hit rather than being told the handshake failed
-
DHCP runs on the interfaces that asked for it. The client enrolled interface 0 whichever way it was configured, so a machine with a fixed address on its first card and DHCP on its second leased for the wrong one
-
An interface that goes down and comes back gets its address again. Neither the DHCPv6 client nor the router solicitation was restarted, so the machine kept whatever it had before the cable moved, or nothing
-
Multicast name service survives being switched off and on. Disabling an interface tested whether it was enabled outside the lock that protects the answer, enabling one that then failed left records published for a service that was not running, and deleting the responder left it in its multicast groups and left callbacks pointing into freed memory
-
A network service that fails to start no longer leaves its worker running. Telnet, TFTP, MQTT, the cloud client, both DHCP servers and the mDNS responder each created threads and timers and then returned an error without stopping them, so a failed start left the machine slower and the second attempt fighting the first
-
Browsing for services stops reading at the end of the caller's array. It kept comparing against entries past the end when there were more services than room for them
-
A DHCPv6 packet whose first option is one we do not know is handled the same way every time. The unknown option left the result of the previous option's parse standing, which was whatever the compiler had put there
-
PCMCIA network interrupts now run through
card.resource's status-change callback, including the V39 post-status phase and the Kickstart 2.x Gayle acknowledgement, instead of registering a raw PORTS server that bypassed the socket owner -
Removing a PCMCIA card takes the unit offline without touching the empty socket, releases ownership from task context, and keeps the handle ready for a validated reinsertion. Reinsertion reruns CIS, COR and chip attachment and restores an online unit unless the caller explicitly put it offline
-
A PCMCIA card configured for use is reset before its handle is released, and an empty or initially busy socket can be claimed on a later
OpenDevice()instead of requiring the device resident to be reloaded -
cnet16detection repeats the complete reset-port pulse after switching odd-register reads to the 16-bit path. The old retry changed the ISR read width only, after the reset read that needed the same workaround had already failed -
Creating or resetting a ThreadX thread fails cleanly when Exec cannot allocate its native Task. The failed Task creation was invisible to ThreadX, which published and could start a thread that had nothing underneath it
-
Thread teardown still detaches the native Task and recovers the scheduler baton when the reaper has no spare signal bit. That fallback returned before recording the live zombie, so the caller could free its stack and the scheduler could remain owned by a thread that no longer existed
-
Thread stacks are rejected whenever their ranges overlap, including when the new range wholly contains an existing one. That containment passed the endpoint-only check and let two Tasks use the same memory as a stack
-
A TLS host name too long for both certificate verification and SNI is refused instead of silently shortened. Truncating the identity could verify or contact a different host from the one the program requested
-
A transmit request that finds the hardware ring full after copying is now marked asynchronous before it is requeued. It still carried
IOF_QUICK, so its eventual completion was not replied and the caller could wait forever -
The mbuf cluster limit remains a limit when two tasks grow the pool together. Both could observe the last slot free while allocation ran outside the lock and each add a cluster
-
httpdrefuses a document root longer than it can hold instead of serving a shortened one, which named a different directory -
The 68020 modular-squaring primitive is a no-op on an empty modulus rather than running its loop backwards through memory. Nothing in the stack calls it that way; a program using the routine directly had no way to know that was required
-
Asking to share the library base no longer loses the rest of the request. The answer is still no -- signals and timer state belong to the task that opened the library -- but refusing the tag discarded every tag after it in the same call, so a program that asked to share and linked its errno in one go ran without an errno for its whole life
-
Leaving a range of multicast addresses removes the ones that are there. A program that joined them one at a time, or that had already left one, was told the whole request failed and stayed in every group in the range
-
getaddrinfo()with no hints resolves a service that exists only over UDP again --tftp,ntp,syslogand the rest. Tightening the protocol checks moved the lookup to after the socket type was defaulted, and the "try both protocols" step could then never run -
A program killed while it was inside the stack no longer stops the network for everything else. Its claim on the stack could not be given back by a task that no longer exists, and nothing else was allowed to give it back either
-
Two programs closing encrypted connections at the same time no longer corrupt the list the encryption library keeps of its open sessions
-
Shutting the stack down no longer frees memory a stuck driver request can still reach. When a device refuses to return a request, the interface is deliberately left behind, and the packet pool it points into was deleted anyway
-
Asking for another task's credentials returns a copy. The pointer named that task's own context, which could close the moment the search released the scheduler, so the caller read it after it was gone
-
A TCP: session no longer looks at its socket after closing it. If another holder closed at the same moment, that close was the last one and the memory was already free
-
An unbound interface only releases a packet for commands that carry one. A control command's packet field is whatever was there before, and it was being freed as though it were a packet
-
A LANCE card keeps sending across a multicast filter change. Changing the filter reinitialises the chip, which threw away frames it had already accepted and reported as sent
-
Two interfaces can no longer be bound to the same slot. The search stopped at the first free entry and rebound it even when the interface already held one further along
-
An interface that survives a failed device open keeps its configuration. The map from device to configuration kept naming the pre-compaction entry, so a later lookup lost a working interface
-
S2_ONEVENTwith an empty mask is refused instead of waiting forever, since no event can share a bit with it -
A failed name-server query replies as the request it was made with. The reply went out through the SANA helper, which writes a byte count into the field an IOStdReq uses for something else
-
A write that raced going offline is refused rather than queued onto a stopped unit, where nothing was left to send it
-
Waiting for online or offline no longer misses a transition that lands between the state test and the queue
-
Capture channels survive being closed and reopened while another call is in flight. A read, a close, an ioctl or an arriving packet could all act on the replacement channel that took the same number
-
The random pool credits entropy without wrapping. A large credit through the public interface could carry a partly seeded pool back toward empty
-
A multicast range no longer wraps its reference count
-
The library refuses an unsolicited TLS renegotiation. There is no renegotiation API here and one connection is one handshake, but the vendored stack would accept a server's request to start a second one without asking
-
A reader that outlives its removal no longer has its stack freed underneath it. The teardown read a gauge of how many such tasks were alive, and that number can be unchanged across the window if an older one exits as this one is created, so the check passed and the memory went back while the task was still standing on it
-
A LANCE card that reports a buffer error or an underrun starts sending again. Both clear the chip's transmit enable, so retiring the frame left a card that says it is running and never transmits another packet until the machine is rebooted
-
The transmit watchdog resets a card that is stuck, not one that is busy. It fired whenever the ring stayed full for the interval, which under a sustained transfer is a card that is keeping up, and the reset dropped what was queued
-
Adding or removing a multicast address is one transaction. The exact list and the hardware filter built from it were updated separately, so a program doing this from one task while another received could leave the card filtering on a list that no longer matched
-
Configuring an interface by name keeps hold of it for the whole call. The name was turned into a slot number once, and the slot could be freed and reused underneath, so the rest of the call could configure a different interface. Removing an interface now waits for such a call rather than pulling the slot out from under it
-
An address allocation started with
BeginInterfaceConfig()survives the program that asked for it closing the library. The worker outlives the caller by design, and could be left polling a slot on a stack that had been taken down and rebuilt behind it -
Removing an interface by name removes the one that was named. The name was resolved to a slot, the lock was dropped, and the slot was reused, so a program could take down a different interface than it asked for
-
The resolver's configuration is read and written one whole change at a time. A program reading the name server list or the domain name while another set them could see a half-written table or a torn string
-
A socket option passed by reference with a null pointer is refused. The pointer was written through, and on a machine with no memory protection that write lands on the interrupt vectors at address zero
-
recvfrom()refuses a source-address buffer that arrives without its length, before it takes a datagram off the queue rather than after -
recvmsg()reports the size of the source address when the buffer given for it is too small, instead of leaving the caller with nothing -
getaddrinfo()refuses hints whose output fields are not clear, which is how a reused or partly initialised structure shows itself -
getnameinfo()appends the zone to a link-local address only when asked for it withNI_WITHSCOPEID -
An event or an error that arrives while a program is reading them is no longer lost. Reading the pending error, the urgent-data mark and the event set each took two steps, and the network task posts between them, so a new event could be erased by the write that cleared the old one
-
Dup2Socket()reserves a descriptor. Asking for one without a socket did nothing, so the descriptor a program was holding for later could be handed to the next socket it opened -
getaddrinfo()fails cleanly when it runs out of memory. A failed allocation was added to the list anyway, so the call could report success with a list shorter than the answer, or empty -
getaddrinfo()checks the protocol it is given.ai_protocolwas never looked at, so a request for UDP with no socket type was answered with the TCP service, and a contradictory pair such as stream over UDP was accepted -
The source address in a message's own control data decides where a multicast datagram leaves from, ahead of the standing interface option
-
WaitSelect()reports a stack that went away while it was waiting, instead of returning as though the wait had simply timed out -
SBTC_CAN_SHARE_LIBRARY_BASESanswers FALSE and refuses a request to share, because signal masks and timer state belong to the task that opened the library. Asking is refused; passing FALSE is not, so a program setting several tags at once does not lose the ones after it -
The library is not unloaded while a ThreadX Task can still be running code inside it. Stopping the kernel can refuse, or time out once stopping has begun, and the refusal was logged and then ignored: the segment went back to the operating system anyway, with tasks still standing on it
-
connect()stops trying when it gives up. On a timeout or a break it returned the failure and left the SYN retransmission running, so a reply arriving afterwards could connect a socket whose caller had already been told the connection failed -
accept()no longer answers a handshake twice. A wait that expired inside it wound the connection back to listening, and the next call sent a second SYN and acknowledgment for a connection already half open, with different sequence numbers -
MSG_DONTWAITworks. It was accepted and discarded, so a program asking for one operation not to wait waited anyway -
A large
SO_RCVTIMEOorSO_SNDTIMEOis the timeout that was asked for. The conversion to ticks overflowed, so a long timeout became a short one, and one value landed exactly on "wait forever". Out-of-range microseconds are refused rather than rounded -
recvmsg()reports ancillary data it had to discard. With no room for it, or no buffer at all, the data was dropped andMSG_CTRUNCwas not set, so the caller was told nothing was missing -
A read with a zero-length buffer on a datagram socket discards the datagram, which is what that read is for. It returned zero and left the datagram queued
-
DeleteRouteTagList()reports a route that was not there. NetX Duo answers success without looking when its table is empty, so deleting a route that never existed failed on a machine with routes and succeeded on one without -
ObtainSocket()does not lose the socket when it runs out of descriptors. The registry entry was removed and freed before the descriptor was allocated, and the failure path put back a different entry -
A link-local address is chosen for the interface that needs it, on every attempt. The interface was picked when the address object was first built and never again, though stopping it only suspends it, so after an interface came or went it probed on the wrong one
-
The wait after a DHCP timeout is skipped when there is nothing to wait for. A failed link-local fallback was followed by fifteen seconds of waiting for an address that could not arrive
-
The release test installs on every card the archive supports, and boots each one. It had only ever booted the A2065, which is how an installer that could not detect five of the nine cards reached eight releases
-
A PCMCIA card is found on a machine with 8 MB of Fast RAM in the test rig. Zorro II Fast RAM covers 0x200000 to 0x9fffff and the A1200's PCMCIA windows are at 0x600000 and 0xa00000, so they collided and the driver reported no card while the slot reported one