📄 pctcp.c
字号:
icmp_handler(ip);
break;
}
} else {
#ifdef DEBUG
if (debug_on) outs("\n\rIP: Bad Checksum\n\r"); // R. Whitby
#endif
}
break;
case /*0x806*/ 0x608 :
/* do arp */
_arp_handler( (arp_Header *)ip );
break;
}
if (ip) _eth_free(ip);
continue;
}
/* check for our outstanding packets */
tcp_Retransmitter();
// S. Lawson return( s->udp.ip_type );
return( s ? s->udp.ip_type : 1 ); /* S. Lawson - change CJ01 */
}
void tcp_set_debug_state( int x )
{
debug_on = x;
}
/* returns 1 if connection is established */
int tcp_established( tcp_Socket *s )
{
return( s->state >= tcp_StateESTAB );
}
/*
* udp_write() handles fragmented UDP by assuming it'll be called
* once for all fragments with no intervening calls. This is
* the case in sock_write().
* Handles upto a hair-under 32K datagrams. Could be made to handle
* upto a hair-under 64K easily... wanna Erick?
* Might be possible to test 'offset' for non/zero fewer times to be
* more efficient. Might also be more efficient to use the old
* UDP checksum() call when more_frags is false in the first frag
* (i.e., not a fragmented dgram).
* Uses _mss to decide splits which defaults to 1400. Could pack
* more into an Ethernet packet.
*/
#define IP_MF 0x0020 // more fragments, net byte order
static udp_write( udp_Socket *s, byte *datap, int len, word offset )
{
struct { // special pseudo header because need to
tcp_PseudoHeader ph; // compute checksum in two parts (may not
word checksum2; // have all of datagram built at once).
} ph;
struct _pkt {
in_Header in;
udp_Header udp;
int data;
/* longword maxsegopt; */
} *pkt;
byte *dp;
in_Header *inp;
udp_Header *udpp;
word maxlen;
int more_frags;
word origlen = len;
// S. Lawson - set Ethernet address if not set (possible if we were
// a passive/broadcast socket
if (memcmp(&s->hisethaddr, "\0\0\0\0\0\0", 6)==0) {
/* check for broadcast */
/* 2001.1.18 changed from -1 */
if ( s->hisaddr == 0xffffffff || !s->hisaddr )
memset( &s->hisethaddr, 0xff, sizeof( eth_address ));
else if ( ! _arp_resolve(s->hisaddr, &s->hisethaddr, 0) )
return( 0 );
}
pkt = (struct _pkt *)_eth_formatpacket(&s->hisethaddr, /*0x800*/ 8);
if( offset ) { // this is not the first fragment
dp = (byte *) &pkt->udp; // data goes right after IP header
} else {
dp = (byte *) &pkt->data;
udpp = &pkt->udp;
/* udp header */
udpp->srcPort = intel16( s->myport );
udpp->dstPort = intel16( s->hisport );
udpp->checksum = 0;
udpp->length = intel16( UDP_LENGTH + len );
}
inp = &pkt->in;
memset( inp, 0, sizeof( in_Header ));
// S. Lawson - this needs changed to handle DHCP when using 576 MSS
#ifdef NOTUSED
maxlen = _mss & 0xFFF8; // make a multiple of 8
if( !offset ) maxlen -= UDP_LENGTH; // note UDP_LENGTH is 8, so ok
#else
maxlen = _mss - sizeof( in_Header ) - sizeof ( udp_Header );
if (offset) {
maxlen += sizeof (udp_Header);
maxlen &= 0xFFF8; // make a multiple of 8
}
#endif
if( len > maxlen ) {
maxlen &= 0xFFF8; // S. Lawson - multiple of 8
len = maxlen;
more_frags = 1;
} else more_frags = 0;
inp->length = intel16( sizeof(in_Header) +
(offset ? 0 : UDP_LENGTH) + len );
movmem(datap, dp, len );
/* internet header */
inp->ver = 4;
inp->hdrlen = 5;
inp->tos = 0;
/* inp->vht = 0x4500;*/ /* version 4, hdrlen 5, tos 0 */
/* if offset non-zero, then is part of a prev datagram so don't incr ID */
inp->identification = intel16( offset ? ip_id : ++ip_id ); /* was post inc */
// inp->frag = 0;
inp->frags = (offset ? intel16((offset + UDP_LENGTH) >> 3) : 0);
if(more_frags) inp->frags |= IP_MF;
inp->ttl = 254;
inp->proto = UDP_PROTO; /* udp */
/* inp->ttlProtocol = (250<<8) + 6; */
inp->checksum = 0;
inp->source = intel( s->myaddr );
inp->destination = intel( s->hisaddr );
inp->checksum = ~checksum( inp, sizeof(in_Header));
/* compute udp checksum if desired */
if(!offset) { // only first of frags has UDP header for entire UDP dgram
if ( s->sock_mode & UDP_MODE_NOCHK )
udpp->checksum = 0;
else {
ph.ph.src = inp->source; /* already INTELled */
ph.ph.dst = inp->destination;
ph.ph.mbz = 0;
ph.ph.protocol = UDP_PROTO; /* udp */
ph.ph.length = udpp->length; /* already INTELled */
/* can't use since may not have the whole dgram built at once */
// ph.checksum = checksum(&pkt->udp, intel16(ph.length));
/* this way handles it */
ph.ph.checksum = checksum(&pkt->udp, UDP_LENGTH);
ph.checksum2 = checksum(datap, origlen);
udpp->checksum = ~checksum(&ph, sizeof(ph));
}
}
if (_dbugxmit) (*_dbugxmit)( (sock_type*)s, inp, udpp, 0 );
_eth_send( intel16( inp->length ));
return ( len );
}
/*
* udp_read - read data from buffer, does large buffering
*/
static int udp_read( udp_Socket *s, byte *datap, int maxlen )
{
int x;
if (maxlen < 0) maxlen = MAXINT;
if (( x = s->rdatalen ) > 0) {
if ( x > maxlen ) x = maxlen;
if ( x > 0 ) {
if (datap) movmem( s->rdata, datap, x );
if ( s->rdatalen -= x )
movmem( s->rdata + x, s->rdata, s->rdatalen);
}
}
return( x );
}
void _udp_cancel( in_Header *ip )
{
int len;
udp_Header *up;
udp_Socket *s;
/* match to a udp socket */
len = in_GetHdrlenBytes(ip);
up = (udp_Header *)((byte *)ip + len); /* udp frame pointer */
/* demux to active sockets */
for ( s = udp_allsocs; s; s = s->next )
if ( s->hisport != 0 &&
intel16( up->dstPort ) == s->hisport &&
intel16( up->srcPort ) == s->myport &&
intel( ip->destination ) == s->hisaddr ) break;
if ( !s ) {
/* demux to passive sockets */
for ( s = udp_allsocs; s; s = s->next )
if ( s->hisport == 0 && intel16( up->dstPort ) == s->myport ) break;
}
if (s) {
s->rdatalen = 0;
s->ip_type = 0;
}
}
void *_tcp_lookup( longword hisip, word hisport, word myport )
{
tcp_Socket *s;
for ( s = tcp_allsocs; s; s = s->next ) {
if ( ( myport == s->myport ) && /* always unique under WATTCP */
( hisport == s->hisport ) &&
( hisip == s->hisaddr ))
return( s );
}
return( NULL );
}
void _tcp_cancel( in_Header *ip, int code, char *msg, longword dummyip )
{
static int in_icmp_redirect = 0; // smart@actrix.gen.nz
int len;
tcp_Socket *s;
tcp_Header *tp;
len = in_GetHdrlenBytes(ip); /* check work */
tp = (tcp_Header *)((byte *)ip + len); /* tcp frame pointer */
/* demux to active sockets */
for ( s = tcp_allsocs; s; s = s->next ) {
if ( intel16( tp->srcPort) == s->myport &&
intel16( tp->dstPort ) == s->hisport &&
intel( ip->destination ) == s->hisaddr ) {
switch (code) {
/* halt it */
case 1 : if (( s->stress ++ > s->rigid ) &&
( s->rigid < 100 )) {
s->err_msg = (msg) ?
msg : "ICMP closed connection";
s->rdatalen = s->datalen = 0;
s->unhappy = false;
tcp_abort( s );
/* if (s->dataHandler) s->dataHandler(s, 0, -1); */
break;
}
// follow through to next case
/* slow it down */
case 2 : s->cwindow = 1;
s->wwindow = 1;
s->rto <<= 2;
s->vj_sa <<= 2;
s->vj_sd <<= 2;
break;
/* icmp redirect for host */
case 5 : /* save his NEW network address */
/* Dummy is passed in NW form need to intel! */
/* This was a bug fixed QVS - smart@actrix.gen.nz */
if (!in_icmp_redirect)
{
in_icmp_redirect = 1;
_arp_resolve(intel(dummyip), &s->hisethaddr, 0);
in_icmp_redirect = 0;
}
break;
}
}
}
}
static int tcp_read( tcp_Socket *s, byte *datap, int maxlen )
{
int x;
long ldiff; // S. Lawson
int diff; // S. Lawson
if (maxlen < 0 ) maxlen = MAXINT;
if (( x = s->rdatalen) > 0) {
if ( x > maxlen ) x = maxlen;
if ( x > 0 ) {
if (datap) movmem( s->rdata, datap, x );
#ifdef NOTUSED // S. Lawson - possible data fragment above
if (( s->rdatalen -= x ) > 0 ) {
movmem( s->rdata + x, s->rdata, s->rdatalen );
#else // S. Lawson
if (( s->rdatalen -= x ) > 0 || s->frag[0] != 0L) {
diff=0;
if (s->frag[0] != 0L) {
ldiff=s->frag[1] - s->acknum;
diff=abs((int) ldiff);
}
movmem( s->rdata + x, s->rdata, s->rdatalen + diff);
#endif
tcp_sendsoon( s ); /* update the window */
} else
tcp_send( s, __LINE__ ); /* update window el-pronto */
}
} else if ( s->state == tcp_StateCLOSWT )
tcp_close( s );
return( x );
}
/*
* Write data to a connection.
* Returns number of bytes written, == 0 when connection is not in
* established state.
*/
static int tcp_write( tcp_Socket *s, byte *dp, int len )
{
int x;
if (len < 0 ) len = MAXINT;
/* no longer uses tcp_MaxData */
if ( s->state != tcp_StateESTAB ) len = 0;
// S. Lawson - fixed per GV (behaves badly with user defined buffers)
// if ( len > (x = s->maxrdatalen - s->datalen) ) len = x;
if ( len > (x = tcp_MaxBufSize - s->datalen) ) len = x;
if ( len > 0 ) {
movmem( dp, s->data + s->datalen, len );
s->datalen += len;
s->unhappy = true; /* redundant because we have outstanding data */
s->datatimer = set_timeout( sock_data_timeout ); /* EE 99.08.23 */
if ( s->sock_mode & TCP_LOCAL )
s->sock_mode &= ~TCP_LOCAL;
else {
if ( s->sock_mode & TCP_MODE_NONAGLE ) {
tcp_send( s, __LINE__ );
} else {
/* transmit if first data or reached MTU */
/* not true MTU, but better than nothing */
if (( s->datalen == len ) || ( s->datalen > (s->mss)/2 ))
tcp_send( s, __LINE__ );
else
tcp_sendsoon( s );
}
}
}
return ( len );
}
/*
* Send pending data
*/
static void tcp_Flush( tcp_Socket *s )
{
if ( s->datalen > 0 ) {
s->flags |= tcp_FlagPUSH;
if (s->unacked == 0) // S. Lawson - only if data not moving
tcp_send(s, __LINE__);
}
}
/*
* Handler for incoming packets.
*/
static void udp_handler( in_Header *ip )
{
udp_Header *up;
tcp_PseudoHeader ph;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -