📄 pctcp.c
字号:
word len;
byte *dp;
longword temp;
udp_Socket *s;
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 ) {
#ifdef DEBUG
if ( s->safetysig != SAFETYUDP ) {
if (debug_on) outs("\n\rUDP: Chain Error\n\r"); // R. Whitby
}
#endif
if ( (s->hisport != 0) &&
(intel16( up->dstPort ) == s->myport) &&
(intel16( up->srcPort ) == s->hisport) &&
((intel( ip->destination ) & sin_mask) == (s->myaddr & sin_mask)) &&
(intel( ip->source ) == s->hisaddr )) break;
}
// R. Whitby 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 );
// S. Lawson - combined from these observations (alot of
// explanation to remove one line)
// Dashui Zhou <dszhou@cs.sdu.edu.cn>
// ARP answer packet overwrites the first datagram
// that arrives at a newly opened passive UDP
// socket. (DZ fix moved _arp_resolve)
// CpV <crudesoft@yahoo.com>
// _arp_resolve() calls tcp_tick() which calls
// calls this udp_handler() again (recurses)
// Anyway, we don't need to resolve now, we can
// resolve when we want to send something.
// _arp_resolve(intel(ip->source), &s->hisethaddr, 0);
// take on value of expected destination unless it
// is broadcast
if ( (intel(~ip->destination) & ~sin_mask) != 0 )
s->myaddr = intel( ip->destination );
}
break;
}
}
#ifdef NOTUSED // S. Lawson - "passive sockets" scan above does this!
if ( !s ) {
/* demux to broadcast sockets */
// S. Lawson - CpV <crudesoft@yahoo.com> has a change here that
// causes broadcasts to go to a socket even if it is bound to a
// remote IP address - I'm not including this because binding to
// a specific machine should imply you're not interested in getting
// packets from other machines on that socket. You can always keep
// a socket bound to the broadcast address for receiving broadcasts.
for ( s = udp_allsocs; s; s = s->next )
if ( (s->hisaddr == 0xffffffffuL) &&
(intel16( up->dstPort ) == s->myport )) break;
}
#endif
if (_dbugrecv) (*_dbugrecv)( (sock_type*)s, ip, up, 0); // R. Whitby
if ( !s ) {
// S. Lawson - return ICMP port unreachable on non-broadcast
if (my_ip_addr && temp!=0xffffffffuL && (~temp & ~sin_mask)) {
#ifdef DEBUG
if (debug_on) outs("\n\rUDP: Discarding Packet\n\r");
#endif
icmp_Unreach(ip);
}
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 */
/* 2000.11.15 save first received packet rather than latest */
if (( (len -= UDP_LENGTH ) > 0) && ( s->rdatalen == 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;
}
}
}
static void tcp_handler( in_Header *ip )
{
tcp_Header *tp;
tcp_PseudoHeader ph;
int len;
/* byte *dp; */
int diff;
tcp_Socket *s;
word flags;
long diffticks, ldiff; /* must be signed */
long scheduleto;
if ( (longword)(intel( ip->destination ) - my_ip_addr) > multihomes )
return;
#ifdef UNUSED // S. Lawson - len wiped by 3rd line down anyway!
len = in_GetHdrlenBytes(ip);
len = intel16( ip->length ) - len; /* len of tcp data */
#endif
len = in_GetHdrlenBytes(ip);
tp = (tcp_Header *)((byte *)ip + len); /* tcp frame pointer */
len = intel16( ip->length ) - len; /* len of tcp data */
flags = intel16( tp->flags );
#ifdef DEBUG
if (debug_on > 1) {
mono[160]++;
colour[160]++;
mono[162] = colour[162] = (flags & tcp_FlagSYN) ? 'S' : ' ';
mono[164] = colour[164] = (flags & tcp_FlagACK) ? 'A' : ' ';
mono[166] = colour[166] = (flags & tcp_FlagFIN) ? 'F' : ' ';
mono[168] = colour[168] = (flags & tcp_FlagRST) ? 'R' : ' ';
}
#endif
/* demux to active sockets */
for ( s = tcp_allsocs; s; s = s->next )
{
#ifdef DEBUG
if ( s->safetysig != SAFETYTCP )
{
if (debug_on) outs("\n\rTCP: Chain Error\n\r"); // R. Whitby
}
#endif
if ( s->hisport != 0 &&
intel16( tp->dstPort ) == s->myport &&
intel16( tp->srcPort ) == s->hisport &&
intel( ip->destination ) == s->myaddr &&
intel( ip->source ) == s->hisaddr ) break;
}
if ( !s && (flags & tcp_FlagSYN))
{
/* demux to passive sockets, must be a new session */
for ( s = tcp_allsocs; s; s = s->next )
if ((s->hisport == 0) && (intel16( tp->dstPort ) == s->myport ))
{
s->myaddr = intel( ip->destination );
break;
}
}
if (_dbugrecv) (*_dbugrecv)( (sock_type*)s, ip, tp, 0 );
if ( !s )
{
if (!(flags & tcp_FlagRST)) tcp_rst( ip, tp );
//printf("tcp was reset\n");
return;
}
ph.src = ip->source; /* already INTELled */
ph.dst = ip->destination;
ph.mbz = 0;
ph.protocol = TCP_PROTO;
ph.length = intel16( len );
ph.checksum = checksum(tp, len);
if ( checksum(&ph, sizeof(ph)) != 0xffff )
{
#ifdef DEBUG
if (debug_on) outs("\n\rTCP: Bad Checksum\n\r"); // R. Whitby
#endif
tcp_sendsoon( s );
return;
}
/* reset code */
if ( flags & tcp_FlagRST ) {
#ifdef DEBUG
if (debug_on) outs("\n\rTCP: Connection Reset\n\r"); // R. Whitby
#endif
s->datalen = 0;
if (s->state != tcp_StateCLOSED && s->state != tcp_StateLASTACK)
s->rdatalen = 0;
s->err_msg = "Remote reset connection";
s->state = tcp_StateCLOSED;
/* if (s->dataHandler) s->dataHandler(s, 0, -1); */
tcp_unthread(s);
/* 2001.1.18 - make it fail tcp_tick() */
s->ip_type = 0;
return;
}
if ( sock_inactive )
s->inactive_to = set_timeout( sock_inactive );
/* update our retransmission stuff */
/* new algorithms */
if (s->karn_count == 2) {
s->karn_count = 0;
#ifdef DEBUG
if (debug_on > 1 ) printf("finally got it safely zapped from %u to ????\n\r",s->unacked);
#endif /* DEBUG */
} else {
if ( s->vj_last ) {
/* unnecessary to use unhappy || s->datalen ) */
if ((diffticks = set_ttimeout( 0 ) - s->vj_last) >= 0 ) {
/* we ignore the overnight case */
diffticks -= (longword)( s->vj_sa >> 3 );
s->vj_sa += (int)diffticks;
if (diffticks < 0)
diffticks = - diffticks;
diffticks -= (s->vj_sd >> 2);
s->vj_sd += (int)diffticks;
if (s->vj_sa > MAXVJSA) s->vj_sa = MAXVJSA;
if (s->vj_sd > MAXVJSD) s->vj_sd = MAXVJSD;
}
/* only recompute rtt hence rto after success */
s->rto = (1 + ((s->vj_sa >> 2) + (s->vj_sd))) >> 1 ;
#ifdef DEBUG
if (debug_on > 1 ) printf("rto %u sa %u sd %u cwindow %u wwindow %u unacked %u\n",
s->rto, s->vj_sa, s->vj_sd, s->cwindow, s->wwindow, s->unacked );
#endif /* DEBUG */
}
s->karn_count = 0;
if ( s->wwindow != 255 ) {
if ( s->wwindow++ >= s->cwindow ) {
if ( s->cwindow != 255 )
s->cwindow ++;
/* tcpwinfix
* Movement of the next line *seems* to fix the failure of the TCP
* send window to open up (which makes TCP writes very slow, as
* seen with some previous releases of WatFTP), though it's been
* a long time since I made this change (today is 96.09.24) and
* I'm not sure how confident I was even then that it was correct.
* Also I don't have any description of the VJ algorithm and don't
* really understand this code all that well, but some time ago
* this seemed to be the right thing to do and seems to work.
* That said, if I'm wrong, I hope I haven't broken things worse :-)
* There is one other place, also marked 'tcpwinfix' above in this
* file, and those are the only two changes I made for this bug
* which may need undoing if I'm wrong. -- mdurkin
*/
s->wwindow = 0; /* mdurkin -- added 95.05.02 */
}
/* s->wwindow = 0; /* mdurkin -- removed 95.05.02 */
}
}
/* all new */
scheduleto = set_ttimeout( s->rto + 2 );
if ( s->rtt_time < scheduleto ) s->rtt_time = scheduleto;
s->datatimer = 0; /* EE 99.08.23 */
switch ( s->state ) {
case tcp_StateLISTEN: /* accepting SYNs */
/* save his ethernet address */
if ( _pktipofs )
movmem(&((((eth_Header *)ip) - 1)->source), &s->hisethaddr, sizeof(eth_address));
if ( flags & tcp_FlagSYN ) {
if ( ip->tos > s->tos )
s->tos = ip->tos;
else if ( ip->tos < s->tos ) {
/* RFC 793 says we should close connection */
/* we best not do that while SunOS ignores TOS */
}
s->acknum = intel( tp->seqnum ) + 1;
s->hisport = intel16( tp->srcPort );
s->hisaddr = intel( ip->source );
s->flags = tcp_FlagSYN | tcp_FlagACK;
s->state = tcp_StateSYNREC;
s->unhappy = true;
tcp_send(s, __LINE__); /* we must respond immediately */
s->timeout = set_timeout( tcp_TIMEOUT );
} else
tcp_rst( ip , tp ); /* send a reset */
return;
case tcp_StateSYNSENT: /* added ACK Section */
if ( flags & tcp_FlagSYN ) {
if ( ip->tos > s->tos )
s->tos = ip->tos;
else if ( ip->tos < s->tos ) {
/* RFC 793 says we should close connection */
/* we best not do that while SunOS ignores TOS */
}
s->flags = tcp_FlagACK;
s->timeout = set_timeout( tcp_TIMEOUT );
/* FlagACK means connection established, else SYNREC */
if ( flags & tcp_FlagACK) {
/* but is it for the correct session ? */
if (tp->acknum == intel(s->seqnum + 1)) {
s->state = tcp_StateESTAB;
s->seqnum++; /* good increment */
s->acknum = intel( tp->seqnum ) + 1; /* 32 bits */
tcp_ProcessData(s, tp, len, &ph, &flags); /* someone may try it */ /* S. Lawson */
s->unhappy = true; /* rely on their attempts */
tcp_send( s, __LINE__ );
} else {
/* wrong ack, force a RST and resend SYN soon*/
s->flags = tcp_FlagRST;
s->unhappy = true;
tcp_send( s, __LINE__ );
s->flags = tcp_FlagSYN;
tcp_send( s, __LINE__ );
}
} else {
s->acknum++;
s->state = tcp_StateSYNREC;
return;
}
} else
tcp_rst( ip, tp );
break;
case tcp_StateSYNREC: /* recSYNSENT, sentACK, waiting EST */
if ( flags & tcp_FlagSYN ) {
s->flags = tcp_FlagSYN | tcp_FlagACK;
s->unhappy = true;
tcp_send(s, __LINE__);
s->timeout = set_timeout( tcp_TIMEOUT );
return;
}
if ( (flags & tcp_FlagACK) && (intel( tp->acknum ) == (s->seqnum + 1))) {
if ( (s->window = intel16( tp->window )) > 0x7fff )
s->window = 0x7fff;
s->flags = tcp_FlagACK;
s->state = tcp_StateESTAB;
s->seqnum++;
s->timeout = 0; /* never timeout */
s->unhappy = false;
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -