Please wait until the page is fully downloaded and then press the "Expand" button or the blue line numbers.

0055001 /*
0055002 tcp_lib.c
0055003 
0055004 Copyright 1995 Philip Homburg
0055005 */
0055006 
0055007 #include "inet.h"
0055008 #include "buf.h"
0055009 #include "clock.h"
0055010 #include "event.h"
0055011 #include "io.h"
0055012 #include "type.h"
0055013 
0055014 #include "assert.h"
0055015 #include "tcp_int.h"
0055016 
0055017 THIS_FILE
0055018 
0055019 #if you_want_to_be_complete
0055020 
tcp_LEmod4G() / tcp_GEmod4G() / tcp_Lmod4G() / tcp_Gmod4G()




0055021 #undef tcp_LEmod4G
0055022 PUBLIC int tcp_LEmod4G(n1, n2)
0055023 u32_t n1;
0055024 u32_t n2;
0055025 {
0055026          return !((u32_t)(n2-n1) & 0x80000000L);
0055027 }
0055028 
0055029 #undef tcp_GEmod4G
0055030 PUBLIC int tcp_GEmod4G(n1, n2)
0055031 u32_t n1;
0055032 u32_t n2;
0055033 {
0055034          return !((u32_t)(n1-n2) & 0x80000000L);
0055035 }
0055036 
0055037 #undef tcp_Lmod4G
0055038 PUBLIC int tcp_Lmod4G(n1, n2)
0055039 u32_t n1;
0055040 u32_t n2;
0055041 {
0055042          return !!((u32_t)(n1-n2) & 0x80000000L);
0055043 }
0055044 
0055045 #undef tcp_Gmod4G
0055046 PUBLIC int tcp_Gmod4G(n1, n2)
0055047 u32_t n1;
0055048 u32_t n2;
0055049 {
0055050          return !!((u32_t)(n2-n1) & 0x80000000L);
0055051 }
0055052 #endif
0055053 
0055054 PUBLIC void tcp_extract_ipopt(tcp_conn, ip_hdr)
0055055 tcp_conn_t *tcp_conn;
0055056 ip_hdr_t *ip_hdr;
tcp_extract_ipopt()




0055057 {
0055058          int ip_hdr_len;
0055059 
0055060          ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
0055061          if (ip_hdr_len == IP_MIN_HDR_SIZE)
0055062                   return;
0055063 
0055064          DBLOCK(1, printf("ip_hdr options NOT supported (yet?)\n"));
0055065 }
0055066 
0055067 PUBLIC void tcp_extract_tcpopt(tcp_conn, tcp_hdr)
0055068 tcp_conn_t *tcp_conn;
0055069 tcp_hdr_t *tcp_hdr;
tcp_extract_tcpopt()




0055070 {
0055071          int tcp_hdr_len;
0055072 
0055073          tcp_hdr_len= (tcp_hdr->th_data_off & TH_DO_MASK) >> 2;
0055074          if (tcp_hdr_len == TCP_MIN_HDR_SIZE)
0055075                   return;
0055076 
0055077          DBLOCK(2, printf("tcp_hdr options NOT supported (yet?)\n"));
0055078 }
0055079 
0055080 PUBLIC u16_t tcp_pack_oneCsum(ip_hdr, tcp_pack)
0055081 ip_hdr_t *ip_hdr;
0055082 acc_t *tcp_pack;
tcp_pack_oneCsum()

tcp_pack_oneCsum() computes the checksum of a tcp packet (including several fields of its ip header). It accomplishes this by computing the checksum (by calling oneC_sum()) of each of the tcp packet's buffers.

Note that a checksum is used to determine if errors occurred during the transmission of data.


0055083 {
0055084          size_t ip_hdr_len;
0055085          acc_t *pack;
0055086          u16_t sum;
0055087          u16_t word_buf[6];
0055088          int odd_length;
0055089          char *data_ptr;
0055090          int length;
0055091 
0055092          ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
0055093          word_buf[0]= ip_hdr->ih_src & 0xffff;
0055094          word_buf[1]= (ip_hdr->ih_src >> 16) & 0xffff;
0055095          word_buf[2]= ip_hdr->ih_dst & 0xffff;
0055096          word_buf[3]= (ip_hdr->ih_dst >> 16) & 0xffff;
0055097          word_buf[4]= HTONS(IPPROTO_TCP);
0055098          word_buf[5]= htons(ntohs(ip_hdr->ih_length)-ip_hdr_len);
0055099          sum= oneC_sum(0, word_buf, sizeof(word_buf));
0055100 
0055101          pack= tcp_pack;
0055102          odd_length= 0;
0055103          for (; pack; pack= pack->acc_next)
Add the checksums of the buffers.

The trickiest part of this loop is handling the (possible) odd byte at the end of a buffer. If there is an odd number of bytes in a buffer, the odd byte at the end is checksummed with the first byte of the next buffer and then the remaining bytes of the buffer are checksummed together.


0055104          {
0055105                   
0055106                   data_ptr= ptr2acc_data(pack);
ptr2acc_data()

The macro ptr2acc_data is #define'd in inet/generic/buf.h as:

#define ptr2acc_data(/* acc_t * */ a) (bf_temporary_acc=(a), \
(&bf_temporary_acc->acc_buffer->buf_data_p[bf_temporary_acc-> \
acc_offset]))

ptr2acc_data() simply returns a pointer to the actual data within an accessor.

ptr2acc_data() is usually called so that the fields of a header (e.g., ip header) can be analyzed.


0055107                   length= pack->acc_length;
0055108 
0055109                   if (!length)
0055110                            continue;
0055111                   sum= oneC_sum (sum, (u16_t *)data_ptr, length);
oneC_sum()

A checksum is used to determine if errors occurred during the transmission of data. The checksum algorithm used by oneC_sum() (which is also the Internet standard) is described by RFC 1071.

Essentially, the algorithm goes through data and adds all the bytes together (using one's complement addition). The high 16 bits of the resulting 32 bit value is then added to the low 16 bits (again, using one's complement addition). The checksum field is then set to the one's complement of this 16 bit sum. (Recall that the one's complement of 0xF0F0 is 0x0F0F.) Since AND'ing any 16 bit number and its 16 bit one's complement will equal 0xFFFF, the checksum of the packet (without the checksum field) AND'ed with the checksum field will equal 0xFFFF (provided the packet was not corrupted after the checksum field was calculated). For example, the checksum of a udp header (including the checksum field) will equal 0xFFFF if the packet was not corrupted in delivery.


From RFC 1071:

In outline, the Internet checksum algorithm is fairly simple:

(1) Adjacent octets to be checksummed are paired to form 16-bit
integers, and the 1's complement sum of these 16-bit integers is
formed.

(2) To generate a checksum, the checksum field itself is cleared,
the 16-bit 1's complement sum is computed over the octets
concerned, and the 1's complement of this sum is placed in the
checksum field.

(3) To check a checksum, the 1's complement sum is computed over the
same set of octets, including the checksum field. If the result
is all 1 bits (-0 in 1's complement arithmetic), the check
succeeds.

Below is a "C" code algorithm that describes the process above. This algorithm is also from RFC 1071. Note that count is the running count of all the bytes in the data and checksum is the return value.



{
/* Compute Internet Checksum for "count" bytes
* beginning at location "addr".
*/
register long sum = 0;

while( count > 1 ) {
/* This is the inner loop */
sum += * (unsigned short) addr++;
count -= 2;
}

/* Add left-over byte, if any */
if( count > 0 )
sum += * (unsigned char *) addr;

/* Fold 32-bit sum to 16 bits */
while (sum>>16)
sum = (sum & 0xffff) + (sum >> 16);

checksum = ~sum;
}



0055112                   if (length & 1)
0055113                   {
0055114                            odd_length= !odd_length;
0055115                            sum= ((sum >> 8) & 0xff) | ((sum & 0xff) << 8);
0055116                   }
0055117          }
0055118          if (odd_length)
0055119          {
0055120                   /* Undo the last swap */
0055121                   sum= ((sum >> 8) & 0xff) | ((sum & 0xff) << 8);
0055122          }
0055123          return sum;
0055124 }
0055125 
0055126 PUBLIC void tcp_get_ipopt(tcp_conn, ip_hdropt)
0055127 tcp_conn_t *tcp_conn;
0055128 ip_hdropt_t *ip_hdropt;
tcp_get_ipopt()




0055129 {
0055130          if (!tcp_conn->tc_remipopt)
0055131          {
0055132                   ip_hdropt->iho_opt_siz= 0;
0055133                   return;
0055134          }
0055135          DBLOCK(1, printf("ip_hdr options NOT supported (yet?)\n"));
0055136          ip_hdropt->iho_opt_siz= 0;
0055137          return;
0055138 }
0055139 
0055140 PUBLIC void tcp_get_tcpopt(tcp_conn, tcp_hdropt)
0055141 tcp_conn_t *tcp_conn;
0055142 tcp_hdropt_t *tcp_hdropt;
tcp_get_tcpopt()




0055143 {
0055144          int optsiz;
0055145 
0055146          if (!tcp_conn->tc_tcpopt)
0055147          {
0055148                   tcp_hdropt->tho_opt_siz= 0;
0055149                   return;
0055150          }
0055151          tcp_conn->tc_tcpopt= bf_pack(tcp_conn->tc_tcpopt);
bf_pack()

bf_pack(old_acc) creates a new linked list of accessors of old_acc's equivalent length and copies the data from old_acc to it. In this way, the data is compressed (or packed).

For example, bf_pack(old_acc) will return new_acc:



(Note that 300+200+300=800=512+288.)


0055152          optsiz= bf_bufsize(tcp_conn->tc_tcpopt);
bf_bufsize()

bf_bufsize() returns the total buffer size of a linked list of accessors (i.e., the sum of acc_length for the accessors in a linked list).

For a detailed description of the network service's buffer management, click here.


0055153          memcpy(tcp_hdropt->tho_data, ptr2acc_data(tcp_conn->tc_tcpopt),
0055154                   optsiz);
0055155          if ((optsiz & 3) != 0)
0055156          {
0055157                   tcp_hdropt->tho_data[optsiz]= TCP_OPT_EOL;
0055158                   optsiz= (optsiz+3) & ~3;
0055159          }
0055160          tcp_hdropt->tho_opt_siz= optsiz;
0055161 
0055162          return;
0055163 }
0055164 
0055165 PUBLIC acc_t *tcp_make_header(tcp_conn, ref_ip_hdr, ref_tcp_hdr, data)
tcp_make_header()




0055166 tcp_conn_t *tcp_conn;
0055167 ip_hdr_t **ref_ip_hdr;
0055168 tcp_hdr_t **ref_tcp_hdr;
0055169 acc_t *data;
0055170 {
0055171          ip_hdropt_t ip_hdropt;
0055172          tcp_hdropt_t tcp_hdropt;
0055173          ip_hdr_t *ip_hdr;
0055174          tcp_hdr_t *tcp_hdr;
0055175          acc_t *hdr_acc;
0055176          char *ptr2hdr;
0055177          int closed_connection;
0055178 
0055179          closed_connection= (tcp_conn->tc_state == TCS_CLOSED);
0055180 
0055181          if (tcp_conn->tc_remipopt || tcp_conn->tc_tcpopt)
0055182          {
0055183                   tcp_get_ipopt (tcp_conn, &ip_hdropt);
tcp_get_ipopt()




0055184                   tcp_get_tcpopt (tcp_conn, &tcp_hdropt);
0055185                   assert (!(ip_hdropt.iho_opt_siz & 3));
0055186                   assert (!(tcp_hdropt.tho_opt_siz & 3));
0055187 
0055188                   hdr_acc= bf_memreq(IP_MIN_HDR_SIZE+
0055189                            ip_hdropt.iho_opt_siz+TCP_MIN_HDR_SIZE+
0055190                            tcp_hdropt.tho_opt_siz);
bf_memreq()

After the buffers have been initialized, accessors[] looks like the following:



bf_memreq() allocates accessors to the caller. For example, if 1514 bytes of buffer space are requested immediately after the network process starts and each buffer is 512 bytes (the default), then accessors[] will look like the following:



Note that three elements of accessors[] have been removed from buf512_freelist and that the head of the chain of the 3 accessors is returned by bf_memreq(). Also note that the acc_linkC and buf_linkC fields have been set to one and acc_length and acc_offset have been set to their appropriate values.

So what happens if there are not enough buffers on the buf512_freelist to satisfy a request? On lines 2280-2290 of buf.c, functions that free buffers for the specific clients (e.g., eth_buffree()) are called until there are enough buffers on buf512_freelist.

For a complete description of the network service's buffer management, click here.


0055191                   ptr2hdr= ptr2acc_data(hdr_acc);
ptr2acc_data()

The macro ptr2acc_data is #define'd in inet/generic/buf.h as:

#define ptr2acc_data(/* acc_t * */ a) (bf_temporary_acc=(a), \
(&bf_temporary_acc->acc_buffer->buf_data_p[bf_temporary_acc-> \
acc_offset]))

ptr2acc_data() simply returns a pointer to the actual data within an accessor.

ptr2acc_data() is usually called so that the fields of a header (e.g., ip header) can be analyzed.


0055192 
0055193                   ip_hdr= (ip_hdr_t *)ptr2hdr;
0055194                   ptr2hdr += IP_MIN_HDR_SIZE;
0055195 
0055196                   if (ip_hdropt.iho_opt_siz)
0055197                   {
0055198                            memcpy(ptr2hdr, (char *)ip_hdropt.iho_data,
0055199                                     ip_hdropt.iho_opt_siz);
0055200                   }
0055201                   ptr2hdr += ip_hdropt.iho_opt_siz;
0055202 
0055203                   tcp_hdr= (tcp_hdr_t *)ptr2hdr;
0055204                   ptr2hdr += TCP_MIN_HDR_SIZE;
0055205 
0055206                   if (tcp_hdropt.tho_opt_siz)
0055207                   {
0055208                            memcpy (ptr2hdr, (char *)tcp_hdropt.tho_data,
0055209                                     tcp_hdropt.tho_opt_siz);
0055210                   }
0055211                   hdr_acc->acc_next= data;
0055212 
0055213                   ip_hdr->ih_vers_ihl= (IP_MIN_HDR_SIZE+
0055214                            ip_hdropt.iho_opt_siz) >> 2;
0055215                   tcp_hdr->th_data_off= (TCP_MIN_HDR_SIZE+
0055216                            tcp_hdropt.tho_opt_siz) << 2;
0055217          }
0055218          else
0055219          {
0055220                   hdr_acc= bf_memreq(IP_MIN_HDR_SIZE+TCP_MIN_HDR_SIZE);
bf_memreq()

After the buffers have been initialized, accessors[] looks like the following:



bf_memreq() allocates accessors to the caller. For example, if 1514 bytes of buffer space are requested immediately after the network process starts and each buffer is 512 bytes (the default), then accessors[] will look like the following:



Note that three elements of accessors[] have been removed from buf512_freelist and that the head of the chain of the 3 accessors is returned by bf_memreq(). Also note that the acc_linkC and buf_linkC fields have been set to one and acc_length and acc_offset have been set to their appropriate values.

So what happens if there are not enough buffers on the buf512_freelist to satisfy a request? On lines 2280-2290 of buf.c, functions that free buffers for the specific clients (e.g., eth_buffree()) are called until there are enough buffers on buf512_freelist.

For a complete description of the network service's buffer management, click here.


0055221                   ip_hdr= (ip_hdr_t *)ptr2acc_data(hdr_acc);
ptr2acc_data()

The macro ptr2acc_data is #define'd in inet/generic/buf.h as:

#define ptr2acc_data(/* acc_t * */ a) (bf_temporary_acc=(a), \
(&bf_temporary_acc->acc_buffer->buf_data_p[bf_temporary_acc-> \
acc_offset]))

ptr2acc_data() simply returns a pointer to the actual data within an accessor.

ptr2acc_data() is usually called so that the fields of a header (e.g., ip header) can be analyzed.


0055222                   tcp_hdr= (tcp_hdr_t *)&ip_hdr[1];
0055223                   hdr_acc->acc_next= data;
0055224 
0055225                   ip_hdr->ih_vers_ihl= IP_MIN_HDR_SIZE >> 2;
0055226                   tcp_hdr->th_data_off= TCP_MIN_HDR_SIZE << 2;
0055227          }
0055228 
0055229          if (!closed_connection && (tcp_conn->tc_state == TCS_CLOSED))
0055230          {
0055231                   DBLOCK(1, printf("connection closed while inuse\n"));
0055232                   bf_afree(hdr_acc);
bf_afree()

After a chain of accessors is no longer needed, the chain (and not simply the single accessor passed as the parameter) can be freed by calling bf_free(). However, if either acc_linkC or buf_linkC of one of the accessors in the linked list is not equal to one (1), the entire chain will not be freed. For example, if buf_afree(acc1) is called for the following chain:



Then the resulting chain will be:



bf_afree() returns acc1 (accessors[63]) to acc_freelist (recall that acc_freelist is the linked list of acc_t's without an associated buffer). However, buffers512[127] cannot be freed because acc2 (accessors[64]) still references it.

bf_afree() is called after an accessor's associated data is no longer needed (for example, after a packet has been sent off by the ethernet driver).


0055233                   return 0;
0055234          }
0055235 
0055236          ip_hdr->ih_tos= tcp_conn->tc_tos;
0055237          ip_hdr->ih_ttl= tcp_conn->tc_ttl;
0055238          ip_hdr->ih_proto= IPPROTO_TCP;
0055239          ip_hdr->ih_src= tcp_conn->tc_locaddr;
0055240          ip_hdr->ih_dst= tcp_conn->tc_remaddr;
0055241          ip_hdr->ih_flags_fragoff= 0;
0055242 
0055243          tcp_hdr->th_srcport= tcp_conn->tc_locport;
0055244          tcp_hdr->th_dstport= tcp_conn->tc_remport;
0055245          tcp_hdr->th_seq_nr= tcp_conn->tc_RCV_NXT;
0055246          tcp_hdr->th_flags= 0;
0055247          tcp_hdr->th_window= htons(tcp_conn->tc_RCV_HI-tcp_conn->tc_RCV_LO);
htons() / ntohs() / htonl() / ntohl()

From htons(3):

"htons() converts a 16-bit quantity from host byte order to network byte order."

Different CPU architectures group multiple bytes differently. For example, on a "little-endian" machine (an example of which is the Intel CPU), the value 0x1234 is stored in memory as 0x3412. However, on a "big-endian" machine, the value 0x1234 is stored in memory as 0x1234.

It is important that values in a header are sent across a network in a consistent manner independent of the architecture of the sending or receiving system. For this reason, a standard was chosen. The standard chosen was big-endian although it could have just as well been little-endian.

htons() is defined in /include/net/hton.h, as:
#define htons(x) (_tmp=(x), ((_tmp>>8) & 0xff) | ((_tmp<<8) & 0xff00))

ntohs() converts a 16-bit quantity from network byte order to host byte order, the reverse of htons().

htonl() and ntohl() are identical to htons() and ntohs() except that they convert 32-bit quantities instead of 16-bit quantities.

Processes generally supply header information when sending packets. The data in these fields is converted to the network format (i.e., big-endian) by the process before the process copies the data to the network service.


0055248          tcp_hdr->th_chksum= 0;
0055249          *ref_ip_hdr= ip_hdr;
0055250          *ref_tcp_hdr= tcp_hdr;
0055251          return hdr_acc;
0055252 }
0055253 
0055254 #if !CRAMPED
0055255 PUBLIC void tcp_print_state (tcp_conn)
0055256 tcp_conn_t *tcp_conn;
tcp_print_state()




0055257 {
0055258          printf("tcp_conn_table[%d]->tc_state= ", tcp_conn-
0055259                   tcp_conn_table);
0055260          if (!(tcp_conn->tc_flags & TCF_INUSE))
0055261          {
0055262                   printf("not inuse\n");
0055263                   return;
0055264          }
0055265          switch (tcp_conn->tc_state)
0055266          {
0055267          case TCS_CLOSED: printf("CLOSED"); break;
0055268          case TCS_LISTEN: printf("LISTEN"); break;
0055269          case TCS_SYN_RECEIVED: printf("SYN_RECEIVED"); break;
0055270          case TCS_SYN_SENT: printf("SYN_SENT"); break;
0055271          case TCS_ESTABLISHED: printf("ESTABLISHED"); break;
0055272          case TCS_CLOSING: printf("CLOSING"); break;
0055273          default: printf("unknown (=%d)", tcp_conn->tc_state); break;
0055274          }
0055275 }
0055276 #endif
0055277 
0055278 PUBLIC int tcp_check_conn(tcp_conn)
0055279 tcp_conn_t *tcp_conn;
tcp_check_conn()




0055280 {
0055281          int allright;
0055282          u32_t lo_queue, hi_queue;
0055283          int size;
0055284 
0055285          allright= TRUE;
0055286          if (tcp_conn->tc_inconsistent)
0055287          {
0055288                   assert(tcp_conn->tc_inconsistent == 1);
0055289 #if !CRAMPED
0055290                   printf("tcp_check_conn: connection is inconsistent\n");
0055291 #endif
0055292                   return allright;
0055293          }
0055294 
0055295          /* checking receive queue */
0055296          lo_queue= tcp_conn->tc_RCV_LO;
0055297          if (lo_queue == tcp_conn->tc_IRS)
0055298                   lo_queue++;
0055299          if (lo_queue == tcp_conn->tc_RCV_NXT && (tcp_conn->tc_flags &
0055300                   TCF_FIN_RECV))
0055301                   lo_queue--;
0055302          hi_queue= tcp_conn->tc_RCV_NXT;
0055303          if (hi_queue == tcp_conn->tc_IRS)
0055304                   hi_queue++;
0055305          if (tcp_conn->tc_flags & TCF_FIN_RECV)
0055306                   hi_queue--;
0055307 
0055308          size= hi_queue-lo_queue;
0055309          if (size<0)
0055310          {
0055311 #if !CRAMPED
0055312                   printf("rcv hi_queue-lo_queue < 0\n");
0055313                   printf("SND_NXT= 0x%x, SND_UNA= 0x%x\n",
0055314                            tcp_conn->tc_SND_NXT, tcp_conn->tc_SND_UNA);
0055315                   printf("lo_queue= 0x%x, hi_queue= 0x%x\n",
0055316                            lo_queue, hi_queue);
0055317                   printf("size= %d\n", size);
0055318 #endif
0055319                   allright= FALSE;
0055320          }
0055321          else if (!tcp_conn->tc_rcvd_data)
0055322          {
0055323                   if (size)
0055324                   {
0055325 #if !CRAMPED
0055326                            printf("RCV_NXT-RCV_LO != 0\n");
0055327                            tcp_print_conn(tcp_conn);
tcp_print_conn()




0055328                            printf("lo_queue= %lu, hi_queue= %lu\n",
0055329                                     lo_queue, hi_queue);
0055330 #endif
0055331                            allright= FALSE;
0055332                   }
0055333          }
0055334          else if (size != bf_bufsize(tcp_conn->tc_rcvd_data))
bf_bufsize()

bf_bufsize() returns the total buffer size of a linked list of accessors (i.e., the sum of acc_length for the accessors in a linked list).

For a detailed description of the network service's buffer management, click here.


0055335          {
0055336 #if !CRAMPED
0055337                   printf("RCV_NXT-RCV_LO != sizeof tc_rcvd_data\n");
0055338                   tcp_print_conn(tcp_conn);
tcp_print_conn()




0055339                   printf(
0055340                   "lo_queue= %lu, hi_queue= %lu, sizeof tc_rcvd_data= %d\n",
0055341                            lo_queue, hi_queue, bf_bufsize(tcp_conn->tc_rcvd_data));
0055342 #endif
0055343                   allright= FALSE;
0055344          }
0055345          else if (size != 0 && (tcp_conn->tc_state == TCS_CLOSED ||
0055346                   tcp_conn->tc_state == TCS_LISTEN ||
0055347                   tcp_conn->tc_state == TCS_SYN_RECEIVED ||
0055348                   tcp_conn->tc_state == TCS_SYN_SENT))
0055349          {
0055350 #if !CRAMPED
0055351                   printf("received data but not connected\n");
0055352                   tcp_print_conn(tcp_conn);
tcp_print_conn()




0055353 #endif
0055354                   allright= FALSE;
0055355          }
0055356          if (tcp_Lmod4G(tcp_conn->tc_RCV_HI, tcp_conn->tc_RCV_NXT))
tcp_LEmod4G() / tcp_GEmod4G() / tcp_Lmod4G() / tcp_Gmod4G()




0055357          {
0055358 #if !CRAMPED
0055359                   printf("tc_RCV_HI (%d) < tc_RCV_NXT (%d)\n",
0055360                            tcp_conn->tc_RCV_HI, tcp_conn->tc_RCV_NXT);
0055361 #endif
0055362                   allright= FALSE;
0055363          }
0055364 
0055365          /* checking send data */
0055366          lo_queue= tcp_conn->tc_SND_UNA;
0055367          if (lo_queue == tcp_conn->tc_ISS)
0055368                   lo_queue++;
0055369          if (lo_queue == tcp_conn->tc_SND_NXT &&
0055370                   (tcp_conn->tc_flags & TCF_FIN_SENT))
0055371          {
0055372                   lo_queue--;
0055373          }
0055374          hi_queue= tcp_conn->tc_SND_NXT;
0055375          if (hi_queue == tcp_conn->tc_ISS)
0055376                   hi_queue++;
0055377          if (tcp_conn->tc_flags & TCF_FIN_SENT)
0055378                   hi_queue--;
0055379 
0055380          size= hi_queue-lo_queue;
0055381          if (size<0)
0055382          {
0055383 #if !CRAMPED
0055384                   printf("snd hi_queue-lo_queue < 0\n");
0055385                   printf("SND_ISS= 0x%x, SND_UNA= 0x%x, SND_NXT= 0x%x\n",
0055386                            tcp_conn->tc_ISS, tcp_conn->tc_SND_UNA,
0055387                            tcp_conn->tc_SND_NXT);
0055388                   printf("hi_queue= 0x%x, lo_queue= 0x%x, size= %d\n",
0055389                            hi_queue, lo_queue, size);
0055390 #endif
0055391                   allright= FALSE;
0055392          }
0055393          else if (!tcp_conn->tc_send_data)
0055394          {
0055395                   if (size)
0055396                   {
0055397 #if !CRAMPED
0055398                            printf("SND_NXT-SND_UNA != 0\n");
0055399                            printf("SND_NXT= %d, SND_UNA= %d\n",
0055400                                     tcp_conn->tc_SND_NXT, tcp_conn->tc_SND_UNA);
0055401                            printf("lo_queue= %d, hi_queue= %d\n",
0055402                                     lo_queue, hi_queue);
0055403 #endif
0055404                            allright= FALSE;
0055405                   }
0055406          }
0055407          else if (size != bf_bufsize(tcp_conn->tc_send_data))
bf_bufsize()

bf_bufsize() returns the total buffer size of a linked list of accessors (i.e., the sum of acc_length for the accessors in a linked list).

For a detailed description of the network service's buffer management, click here.


0055408          {
0055409 #if !CRAMPED
0055410                   printf("SND_NXT-SND_UNA != sizeof tc_send_data\n");
0055411                   printf("SND_NXT= %d, SND_UNA= %d\n",
0055412                            tcp_conn->tc_SND_NXT, tcp_conn->tc_SND_UNA);
0055413                   printf("lo_queue= %d, lo_queue= %d\n",
0055414                            lo_queue, hi_queue);
0055415                   printf("bf_bufsize(data)= %d\n",
0055416                            bf_bufsize(tcp_conn->tc_send_data));
0055417 #endif
0055418                   allright= FALSE;
0055419          }
0055420 
0055421          /* checking counters */
0055422          if (!tcp_GEmod4G(tcp_conn->tc_SND_UNA, tcp_conn->tc_ISS))
tcp_LEmod4G() / tcp_GEmod4G() / tcp_Lmod4G() / tcp_Gmod4G()




0055423          {
0055424 #if !CRAMPED
0055425                   printf("SND_UNA < ISS\n");
0055426 #endif
0055427                   allright= FALSE;
0055428          }
0055429          if (!tcp_GEmod4G(tcp_conn->tc_SND_NXT, tcp_conn->tc_SND_UNA))
tcp_LEmod4G() / tcp_GEmod4G() / tcp_Lmod4G() / tcp_Gmod4G()




0055430          {
0055431 #if !CRAMPED
0055432                   printf("SND_NXT<SND_UNA\n");
0055433 #endif
0055434                   allright= FALSE;
0055435          }
0055436          if (!tcp_GEmod4G(tcp_conn->tc_SND_TRM, tcp_conn->tc_SND_UNA))
tcp_LEmod4G() / tcp_GEmod4G() / tcp_Lmod4G() / tcp_Gmod4G()




0055437          {
0055438 #if !CRAMPED
0055439                   printf("SND_TRM<SND_UNA\n");
0055440 #endif
0055441                   allright= FALSE;
0055442          }
0055443          if (!tcp_GEmod4G(tcp_conn->tc_SND_NXT, tcp_conn->tc_SND_TRM))
tcp_LEmod4G() / tcp_GEmod4G() / tcp_Lmod4G() / tcp_Gmod4G()




0055444          {
0055445 #if !CRAMPED
0055446                   printf("SND_NXT<SND_TRM\n");
0055447 #endif
0055448                   allright= FALSE;
0055449          }
0055450 
0055451          DIFBLOCK(1, (!allright), printf("tcp_check_conn: not allright\n"));
0055452          return allright;
0055453 }
0055454 
0055455 #if !CRAMPED
0055456 PUBLIC void tcp_print_pack(ip_hdr, tcp_hdr)
0055457 ip_hdr_t *ip_hdr;
0055458 tcp_hdr_t *tcp_hdr;
tcp_print_pack()




0055459 {
0055460          int tcp_hdr_len;
0055461 
0055462          assert(tcp_hdr);
0055463          if (ip_hdr)
0055464                   writeIpAddr(ip_hdr->ih_src);
0055465          else
0055466                   printf("???");
0055467          printf(",%u ", ntohs(tcp_hdr->th_srcport));
0055468          if (ip_hdr)
0055469                   writeIpAddr(ip_hdr->ih_dst);
0055470          else
0055471                   printf("???");
0055472          printf(",%u ", ntohs(tcp_hdr->th_dstport));
htons() / ntohs() / htonl() / ntohl()

From htons(3):

"htons() converts a 16-bit quantity from host byte order to network byte order."

Different CPU architectures group multiple bytes differently. For example, on a "little-endian" machine (an example of which is the Intel CPU), the value 0x1234 is stored in memory as 0x3412. However, on a "big-endian" machine, the value 0x1234 is stored in memory as 0x1234.

It is important that values in a header are sent across a network in a consistent manner independent of the architecture of the sending or receiving system. For this reason, a standard was chosen. The standard chosen was big-endian although it could have just as well been little-endian.

htons() is defined in /include/net/hton.h, as:
#define htons(x) (_tmp=(x), ((_tmp>>8) & 0xff) | ((_tmp<<8) & 0xff00))

ntohs() converts a 16-bit quantity from network byte order to host byte order, the reverse of htons().

htonl() and ntohl() are identical to htons() and ntohs() except that they convert 32-bit quantities instead of 16-bit quantities.

Processes generally supply header information when sending packets. The data in these fields is converted to the network format (i.e., big-endian) by the process before the process copies the data to the network service.


0055473          printf(" 0x%lx", ntohl(tcp_hdr->th_seq_nr));
htons() / ntohs() / htonl() / ntohl()

From htons(3):

"htons() converts a 16-bit quantity from host byte order to network byte order."

Different CPU architectures group multiple bytes differently. For example, on a "little-endian" machine (an example of which is the Intel CPU), the value 0x1234 is stored in memory as 0x3412. However, on a "big-endian" machine, the value 0x1234 is stored in memory as 0x1234.

It is important that values in a header are sent across a network in a consistent manner independent of the architecture of the sending or receiving system. For this reason, a standard was chosen. The standard chosen was big-endian although it could have just as well been little-endian.

htons() is defined in /include/net/hton.h, as:
#define htons(x) (_tmp=(x), ((_tmp>>8) & 0xff) | ((_tmp<<8) & 0xff00))

ntohs() converts a 16-bit quantity from network byte order to host byte order, the reverse of htons().

htonl() and ntohl() are identical to htons() and ntohs() except that they convert 32-bit quantities instead of 16-bit quantities.

Processes generally supply header information when sending packets. The data in these fields is converted to the network format (i.e., big-endian) by the process before the process copies the data to the network service.


0055474          if (tcp_hdr->th_flags & THF_FIN)
0055475                   printf(" <FIN>");
0055476          if (tcp_hdr->th_flags & THF_SYN)
0055477                   printf(" <SYN>");
0055478          if (tcp_hdr->th_flags & THF_RST)
0055479                   printf(" <RST>");
0055480          if (tcp_hdr->th_flags & THF_PSH)
0055481                   printf(" <PSH>");
0055482          if (tcp_hdr->th_flags & THF_ACK)
0055483                   printf(" <ACK 0x%x %u>", ntohl(tcp_hdr->th_ack_nr),
0055484                            ntohs(tcp_hdr->th_window));
htons() / ntohs() / htonl() / ntohl()

From htons(3):

"htons() converts a 16-bit quantity from host byte order to network byte order."

Different CPU architectures group multiple bytes differently. For example, on a "little-endian" machine (an example of which is the Intel CPU), the value 0x1234 is stored in memory as 0x3412. However, on a "big-endian" machine, the value 0x1234 is stored in memory as 0x1234.

It is important that values in a header are sent across a network in a consistent manner independent of the architecture of the sending or receiving system. For this reason, a standard was chosen. The standard chosen was big-endian although it could have just as well been little-endian.

htons() is defined in /include/net/hton.h, as:
#define htons(x) (_tmp=(x), ((_tmp>>8) & 0xff) | ((_tmp<<8) & 0xff00))

ntohs() converts a 16-bit quantity from network byte order to host byte order, the reverse of htons().

htonl() and ntohl() are identical to htons() and ntohs() except that they convert 32-bit quantities instead of 16-bit quantities.

Processes generally supply header information when sending packets. The data in these fields is converted to the network format (i.e., big-endian) by the process before the process copies the data to the network service.


0055485          if (tcp_hdr->th_flags & THF_URG)
0055486                   printf(" <URG %u>", tcp_hdr->th_urgptr);
0055487          tcp_hdr_len= (tcp_hdr->th_data_off & TH_DO_MASK) >> 2;
0055488          if (tcp_hdr_len != TCP_MIN_HDR_SIZE)
0055489                   printf(" <options %d>", tcp_hdr_len-TCP_MIN_HDR_SIZE);
0055490 }
0055491 #endif
0055492 
0055493 #if !CRAMPED
0055494 PUBLIC void tcp_print_conn(tcp_conn)
0055495 tcp_conn_t *tcp_conn;
tcp_print_conn()




0055496 {
0055497          int iss, irs;
0055498 
0055499          iss= tcp_conn->tc_ISS;
0055500          irs= tcp_conn->tc_IRS;
0055501 
0055502          tcp_print_state (tcp_conn);
tcp_print_state()




0055503          printf(
0055504          " ISS 0x%lx UNA +0x%lx(0x%lx) TRM +0x%lx(0x%lx) NXT +0x%lx(0x%lx)",
0055505                   iss, tcp_conn->tc_SND_UNA-iss, tcp_conn->tc_SND_UNA,
0055506                   tcp_conn->tc_SND_TRM-iss, tcp_conn->tc_SND_TRM,
0055507                   tcp_conn->tc_SND_NXT-iss, tcp_conn->tc_SND_NXT);
0055508          printf(" snd_cwnd +0x%lx(0x%lx)",
0055509                   tcp_conn->tc_snd_cwnd-tcp_conn->tc_SND_UNA,
0055510                   tcp_conn->tc_snd_cwnd);
0055511          printf(" transmit_seq ");
0055512          if (tcp_conn->tc_transmit_seq == 0)
0055513                   printf("0");
0055514          else
0055515          {
0055516                   printf("+0x%lx(0x%lx)", tcp_conn->tc_transmit_seq-iss,
0055517                            tcp_conn->tc_transmit_seq);
0055518          }
0055519          printf(" IRS 0x%lx LO +0x%x(0x%lx) NXT +0x%x(0x%lx) HI +0x%x(0x%lx)",
0055520                   irs, tcp_conn->tc_RCV_LO-irs, tcp_conn->tc_RCV_LO,
0055521                   tcp_conn->tc_RCV_NXT-irs, tcp_conn->tc_RCV_NXT,
0055522                   tcp_conn->tc_RCV_HI-irs, tcp_conn->tc_RCV_HI);
0055523          if (tcp_conn->tc_flags & TCF_INUSE)
0055524                   printf(" TCF_INUSE");
0055525          if (tcp_conn->tc_flags & TCF_FIN_RECV)
0055526                   printf(" TCF_FIN_RECV");
0055527          if (tcp_conn->tc_flags & TCF_RCV_PUSH)
0055528                   printf(" TCF_RCV_PUSH");
0055529          if (tcp_conn->tc_flags & TCF_MORE2WRITE)
0055530                   printf(" TCF_MORE2WRITE");
0055531          if (tcp_conn->tc_flags & TCF_SEND_ACK)
0055532                   printf(" TCF_SEND_ACK");
0055533          if (tcp_conn->tc_flags & TCF_FIN_SENT)
0055534                   printf(" TCF_FIN_SENT");
0055535 }
0055536 #endif
0055537 
0055538 /*
0055539  * $PchId: tcp_lib.c,v 1.7 1995/11/21 06:45:27 philip Exp $
0055540  */