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;
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;
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;
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;
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)
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);
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;
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;
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);
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);
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);
0055353 #endif
0055354 allright= FALSE;
0055355 }
0055356 if (tcp_Lmod4G(tcp_conn->tc_RCV_HI, tcp_conn->tc_RCV_NXT))
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))
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))
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))
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))
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;
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;
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);
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 */