tcp.c
来自「mcf5307实验源代码」· C语言 代码 · 共 1,562 行 · 第 1/5 页
C
1,562 行
/*************************************************************************/
/* */
/* FUNCTION */
/* */
/* tcpresetfin */
/* */
/* DESCRIPTION */
/* */
/* Send a reset packet back to sender */
/* Use the packet which just came in as a template to return to */
/* sender. Fill in all of the fields necessary and dlayersend it back. */
/* */
/* CALLED BY */
/* TCP_Interpret */
/* */
/* CALLS */
/* */
/* intswap */
/* longswap */
/* ipcheck */
/* tcpcheck */
/* NET_Send */
/* */
/*************************************************************************/
static int16 tcpresetfin(TCPKT *t, uint16 dlen)
{
uint16 tport;
struct pseudotcp xxx;
struct pqueue HUGE *buf_ptr;
TCPKT *out_tcp;
if(t->t.flags&TRESET) /* don't reset a reset */
return(1);
/* We need to build a new packet to transmit this reset back to the
sender. Therefore, we must get the packet itself and we must acquire
a header packet for the transmit operation (see below). */
/* Allocate a buffer to place the arp packet in. */
buf_ptr = (struct pqueue HUGE *)dll_dequeue((tqe_t *)&buffer_freelist);
if(buf_ptr == NU_NULL)
{
return (NU_NULL);
}
/* Initialize each field in the allocated buffer. */
buf_ptr->data_len = 0;
buf_ptr->next = (struct pqueue *)NU_NULL;
buf_ptr->previous = (struct pqueue *)NU_NULL;
buf_ptr->seqnum = 0;
/* Set up a pointer to the packet. */
out_tcp = (TCPKT *)(buf_ptr->packet - 2);
/* Now we start building the packet itself. We move the data from
the TCP packet that we received into our newly allocated packet. */
/* Swap TCP layer portions for sending back. */
if(t->t.flags&TACK)
{
out_tcp->t.seq=t->t.ack; /* ack becomes next seq # */
out_tcp->t.ack=0L; /* ack # is 0 */
out_tcp->t.flags=TRESET|TFIN;
} /* end if */
else
{
out_tcp->t.seq=0L;
if(t->t.flags&TSYN)
out_tcp->t.ack=longswap(longswap(t->t.seq)+ dlen + 1);
else
out_tcp->t.ack=longswap(longswap(t->t.seq)+ dlen);
out_tcp->t.flags=TRESET|TACK|TFIN;
} /* end else */
tport=t->t.source; /* swap port #'s */
out_tcp->t.source=t->t.dest;
out_tcp->t.dest=tport;
out_tcp->t.hlen=20<<2; /* header len */
out_tcp->t.window=0;
out_tcp->t.urgent = t->t.urgent;
/* Create pseudo header for checksum. */
xxx.z=0;
xxx.proto=t->i.protocol;
xxx.tcplen=intswap(20);
memcpy ((void *)xxx.source, (const void *)t->i.ipsource, 4);
memcpy ((void *)xxx.dest, (const void *)t->i.ipdest, 4);
out_tcp->t.check=0;
out_tcp->t.check=tcpcheck( (uint16 *) &xxx, (uint16 *) &out_tcp->t,
(uint16)sizeof(struct tcph));
/* IP and data link layers. */
/* machine it came from */
memcpy ((void *)out_tcp->i.ipdest, (const void *)t->i.ipsource, 4);
memcpy ((void *)out_tcp->i.ipsource, (const void *)nnipnum, 4);
out_tcp->i.versionandhdrlen = t->i.versionandhdrlen;
out_tcp->i.service = t->i.service;
out_tcp->i.protocol = t->i.protocol;
out_tcp->i.frags = t->i.frags;
out_tcp->i.tlen=intswap(sizeof(IPLAYER)+sizeof(TCPLAYER));
out_tcp->i.ident = (uint16)nnipident++;
out_tcp->i.ttl=30;
out_tcp->i.check=0;
out_tcp->i.check=ipcheck((uint16 *)&out_tcp->i,10);
out_tcp->d.type = t->d.type;
/* data link address */
memcpy ((void *)out_tcp->d.dest, (const void *)t->d.me, DADDLEN);
/* my address */
memcpy ((void *)out_tcp->d.me, (const void *)blankd.me, DADDLEN);
/* Increment the number of IP packets transmitted. */
SNMP_ipOutRequests_Inc;
/* Increment the number of TCP segments transmitted. */
SNMP_tcpOutSegs_Inc;
/* Increment the number of TCP resets sent. */
SNMP_tcpOutRsts_Inc;
/* Send the packet. */
NET_Send(buf_ptr, (sizeof(DLAYER) + sizeof(IPLAYER) + sizeof(TCPLAYER)),
OTHER_PKT);
return (0);
} /* end tcpresetfin() */
/*************************************************************************/
/* */
/* FUNCTION */
/* */
/* tcp_update_headers */
/* */
/* DESCRIPTION */
/* */
/* Update the fields in the IP and TCP headers that change from */
/* packet to packet. Depending on the type parameter, call */
/* either tcpsend or tcp_sendack. */
/* */
/* CALLED BY */
/* transq */
/* netread */
/* netest */
/* doconnect */
/* netopen */
/* netclose */
/* tcpdo */
/* */
/* CALLS */
/* */
/* intswap */
/* longswap */
/* ipcheck */
/* tcpcheck */
/* */
/*************************************************************************/
int16 tcp_update_headers (struct port *pport, uint16 dlen, uint32 seq_num,
int16 tcp_hlen)
{
struct port *prt;
prt = pport;
if (prt == NU_NULL)
{
NU_Tcp_Log_Error (TCP_INV_PORT, TCP_RECOVERABLE,
__FILE__, __LINE__);
return (-1);
} /* end if */
/* do IP header first */
prt->tcpout.i.ident = intswap ((uint16)nnipident++);
prt->tcpout.i.tlen = intswap ( (uint16)(sizeof(struct iph) +
sizeof(struct tcph) + dlen));
prt->tcpout.i.check = 0;
prt->tcpout.i.check = ipcheck ((uint16 *)&prt->tcpout.i, 10);
/* do TCP header */
prt->tcpout.t.seq = seq_num; /* byte swapped */
/* Update the ack value that will be sent. */
prt->tcpout.t.ack = longswap (pport->in.nxt);
/* Update the tcp header len */
prt->tcpout.t.hlen = (tcp_hlen << 4);
/*
* if the port has some credit limit, use it instead of large
* window buffer. Generally demanded by hardware limitations.
*/
if ((uint)(prt->credit) < (prt->in.size))
{
prt->tcpout.t.window = intswap (prt->credit);
}
else
{
prt->tcpout.t.window = intswap (prt->in.size); /* window size */
}
/* prepare pseudo-header for checksum */
prt->tcps.tcplen = intswap ((uint16)(dlen + sizeof(TCPLAYER)));
/* get the checksum */
prt->tcpout.t.check = 0;
return NU_SUCCESS;
} /* end tcp_update_headers. */
/*************************************************************************/
/* */
/* FUNCTION */
/* */
/* tcp_sendack */
/* */
/* DESCRIPTION */
/* */
/* Transmit an ack packet or a packet that contains options. */
/* Acks work this way so that we don't have to allocate a buffer */
/* for a packet that will contain no data. */
/* */
/* CALLED BY */
/* transq */
/* netread */
/* netest */
/* doconnect */
/* netopen */
/* netclose */
/* tcpdo */
/* */
/* CALLS */
/* */
/* intswap */
/* longswap */
/* ipcheck */
/* tcpcheck */
/* NET_Send */
/* */
/*************************************************************************/
int16 tcp_sendack(struct port *pport, uint16 dlen)
{
TCPKT *tcp_ptr;
struct pqueue HUGE *buf_ptr;
uint16 *temp_tcp;
uint16 hlen;
/* Clear the PUSH flag if no data to be sent. */
if (!pport->out.contain)
pport->tcpout.t.flags &= ~TPUSH;
/* Update the IP and TCP headers with the latest info. The TCP header is
always 5 words in size for an ACK packet. */
tcp_update_headers(pport, dlen, longswap(pport->out.nxt), 5);
/* Allocate a buffer to place the ack packet in. */
buf_ptr = (struct pqueue HUGE *)dll_dequeue((tqe_t *)&buffer_freelist);
if(buf_ptr == NU_NULL)
{
return (NU_NULL);
}
/* Initialize each field in the allocated buffer. */
buf_ptr->data_len = dlen;
buf_ptr->next = (struct pqueue *)NU_NULL;
buf_ptr->previous = (struct pqueue *)NU_NULL;
buf_ptr->seqnum = 0;
/* NFH - To take care of padding that is used for machines that
* require word alignment, there is a padding field at the beginning
* of the TCPKT. This next code moves the pointer to the TCPPKT ahead
* 2 bytes to make up for the padding. */
temp_tcp = (uint16 *) &pport->tcpout;
temp_tcp++;
/* Compute the length of the packet. */
hlen = sizeof(DLAYER) + sizeof(IPLAYER) + sizeof(TCPLAYER);
/* Move the header information into the packet. */
memcpy ((void *)buf_ptr->packet, (const void *)temp_tcp,
hlen + dlen);
tcp_ptr = (TCPKT *)(buf_ptr->packet - 2);
/* Compute and fill in the checksum. */
tcp_ptr->t.check = tcpcheck((uint16 *)&pport->tcps,
(uint16 *) &tcp_ptr->t,
(uint16) (dlen + sizeof(TCPLAYER)) );
/* Increment the number of IP packets transmitted. */
SNMP_ipOutRequests_Inc;
/* Increment the number of TCP segments transmitted. */
SNMP_tcpOutSegs_Inc;
NET_Send(buf_ptr, (int16)(dlen + sizeof(DLAYER) + sizeof(IPLAYER) +
sizeof(TCPLAYER)), OTHER_PKT);
return(NU_SUCCESS);
} /* end tcp_sendack */
/*************************************************************************/
/* */
/* FUNCTION */
/* */
/* tcpsend */
/* */
/* DESCRIPTION */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?