The official home page for DOS Trumpet ABI is http://www.trumpet.com.au/dosapps/. Version 3.01 (aka ntcpdrv) is referred to as "using less memory" on the official home page, but it is the first version to properly implement several features, for example, the ability to find the address of sender of a UDP packet.
Mike Durkin has written a great C wrapper for the trumpet ABI;
you can download it from Tsoft's site.
I have ported his C wrapper to 32 bit Watcom C. (It still compiles
under 16 bit Borland, too.) You can download my port from
here until Mike picks it up. (Note: I only ported the DNS and UDP parts-- the TCP part
still needs porting, but it should be very easy.)
A few Usenet posts with bugfixes are archived below.
The wrapper comes with working DNS routines and an example finger client, but no UDP examples. To remedy that, I have written ports of a perl UDP example:
The trick to receiving UDP packets is revealed in the DNS code: you can use the same handle to get DNS responses as you used to send them! That means that the 'srcport' and 'destport' parameters to udp_open are really 'localport' and 'remoteport'.
Subject: TCPDRV C ABI bug fixed --- tcpabi_udp_status
Date: Fri, 03 Apr 1998 20:19:25 -0600
From: dszhou@cs.sdu.edu.cn
Newsgroups: comp.protocols.tcp-ip.ibmpc, comp.protocols.tcp-ip
I found a bug in Trumpet TCP ABI in C interface TABI9605, and
fixed it. The bug is caused by an omitted line in specification
file TCP201.SPE. To fix this bug, add the following line in
udp_status segment just after line "ah = 24H" in file TCP201.SPE
first.
bx = handle
Then rewrite C function tcpabi_udp_status as following:
int tcpabi_udp_status(unsigned handle, unsigned char flags,
unsigned *size_next, tcpabi_session_info_t far **info )
{
union REGS r;
struct SREGS s;
segread(&s);
r.h.ah = 0x24;
r.h.al = flags;
r.x.bx = handle; /* Added by dszhou@cs.sdu.edu.cn, 98.03.24 */
int86x( _tcpabi_vector, &r, &r, &s );
_tcpabi_errno = r.h.dl;
if( size_next ) *size_next = r.x.cx;
if( info ) *info = MK_FP( s.es, r.x.di );
return ( _tcpabi_errno ? -1 : r.x.ax );
/* return number of packets avail */
/* or -1 if error */
}
Subject: WATTCP UDP passive socket bug fixed
Date: Fri, 03 Apr 1998 20:22:17 -0600
From: dszhou@cs.sdu.edu.cn
Newsgroups: comp.protocols.tcp-ip.ibmpc, comp.protocols.tcp-ip
I found a bug in WATTCP9609 UDP part, and fixed it. The bug is, if
you open a passive UDP socket for a UDP server(such as TFTP server),
the server can gets first datagram from a client, and then discards
all successive datagrams from the same client. If you set debug on
(using tcp_set_debug_state), you can see "discarding..." when a
datagram arrives.
The bug is due to the cross effect of function udp_handler in file
PCTCP.C and function _arp_resolve in file PCARP.C, and some more.
When first datagram reaches the server, the server records client's
IP address and port, then sends an ARP request to find client's MAC
address(really need here?). Unfortunately, the ARP answer packet
overwrites the head of the first datagram buffer, myaddr CHANGES.
So successive datagrams are discarded.
There are several ways to remedy this error. I simply move the
_arp_resolve function call to the end of function udp_handler,
the datagram buffer is useless there.
By the way, it's fortune that we can get first datagram's content,
because ARP packet length is just the same as normal IP head length
plus UDP head length.
For your convenience, I list the corrected function here.
Dashui Zhou, Dept. of CS, Shandong Univ., China.
/*
* Handler for incoming packets.
*/
static void udp_handler( in_Header *ip )
{
udp_Header *up;
tcp_PseudoHeader ph;
word len;
byte *dp;
longword temp;
udp_Socket *s;
int need_arp = 0; /* must be auto, 98.04.03 */
temp = intel( ip->destination );
// temp = ip number
// or 255.255.255.255
// or sin_mask.255.255
if ( ((~temp & ~sin_mask) != 0) && /* not a broadcast packet*/
((( temp - my_ip_addr) > multihomes ) /* not my address */
&& my_ip_addr)) /* and I know my address */
return;
len = in_GetHdrlenBytes(ip);
up = (udp_Header *)((byte *)ip + len); /* udp segment pointer */
len = intel16( up->length );
/* demux to active sockets */
for ( s = udp_allsocs; s; s = s->next ) {
if ( s->safetysig != SAFETYUDP ) {
if (debug_on) outs("chain error in udp\r\n");
}
if ( (s->hisport != 0) &&
(intel16( up->dstPort ) == s->myport) &&
(intel16( up->srcPort ) == s->hisport) &&
((temp & sin_mask) == (s->myaddr & sin_mask)) &&
(intel( ip->source ) == s->hisaddr )) break;
}
if (_dbugrecv) (*_dbugrecv)( (sock_type*)s, ip, up, 0);
if ( !s ) {
/* demux to passive sockets */
for ( s = udp_allsocs; s; s = s->next )
if ( ((s->hisaddr == 0) || (s->hisaddr == 0xffffffffuL))
&& intel16( up->dstPort ) == s->myport ) {
// do we record this information ???
if ( s->hisaddr == 0 ) {
s->hisaddr = intel( ip->source );
s->hisport = intel16( up->srcPort );
/* dszhou@cs.sdu.edu.cn found a bug and fixed here, Apr. 3, 1998 */
need_arp = 1; /* remember we need arp */
/* and postpone arp action */
// take on value of expected destination unless
// it is broadcast
if ( (~temp & ~sin_mask) != 0 )
s->myaddr = temp;
}
break;
}
}
if ( !s ) {
/* demux to broadcast sockets */
for ( s = udp_allsocs; s; s = s->next )
if ( (s->hisaddr == 0xffffffffuL) &&
(intel16( up->dstPort ) == s->myport )) break;
}
if ( !s ) {
if (debug_on) outs("discarding...");
return;
}
// these parameters are used for things other than just checksums
ph.src = ip->source; /* already INTELled */
ph.dst = ip->destination;
ph.mbz = 0;
ph.protocol = UDP_PROTO;
ph.length = up->length;
if ( up->checksum ) {
ph.checksum = checksum(up, len);
if (checksum(&ph, sizeof( tcp_PseudoHeader)) != 0xffff)
return;
}
/* process user data */
if ( (len -= UDP_LENGTH ) > 0) {
dp = (byte *)( up );
if (s->dataHandler)
s->dataHandler( s, &dp[ UDP_LENGTH ], len , &ph, up);
else {
if (len > s->maxrdatalen ) len = s->maxrdatalen;
movmem( &dp[ UDP_LENGTH ], s->rdata, len );
s->rdatalen = len;
}
}
if( need_arp ) /* get his MAC address before return,
98.04.03 */
_arp_resolve(intel(ip->source), &s->hisethaddr, 0);
} // End of udp_handler
Subject: WATTCP UDP Client/Server Example
Date: 8 Apr 1998 20:01:37 GMT
From: "Michael Temari" temari@ix.netcom.com
Newsgroups: comp.protocols.tcp-ip.ibmpc
I've been seeing some questions regarding WATTCP UDP programming lately and
thought I would share my UDP client/server test program.
Basically run the program with no arguments and it is a server that listens
on UDP port 812 and echoes back whatever it receives. Pass the argument of
the IP address of the server and the program becomes the client allowing
you the enter data that will be sent to the server and get bounced back.
Hope this helps those who are trying to do UDP programming with WATTCP.
Michael Temari
temari@ix.netcom.com
attached file: Wtest.c