📄 tcp_input.pc
字号:
/* * GloMoSim is COPYRIGHTED software. Release 2.02 of GloMoSim is available * at no cost to educational users only. * * Commercial use of this software requires a separate license. No cost, * evaluation licenses are available for such purposes; please contact * info@scalable-networks.com * * By obtaining copies of this and any other files that comprise GloMoSim2.02, * you, the Licensee, agree to abide by the following conditions and * understandings with respect to the copyrighted software: * * 1.Permission to use, copy, and modify this software and its documentation * for education and non-commercial research purposes only is hereby granted * to Licensee, provided that the copyright notice, the original author's * names and unit identification, and this permission notice appear on all * such copies, and that no charge be made for such copies. Any entity * desiring permission to use this software for any commercial or * non-educational research purposes should contact: * * Professor Rajive Bagrodia * University of California, Los Angeles * Department of Computer Science * Box 951596 * 3532 Boelter Hall * Los Angeles, CA 90095-1596 * rajive@cs.ucla.edu * * 2.NO REPRESENTATIONS ARE MADE ABOUT THE SUITABILITY OF THE SOFTWARE FOR ANY * PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. * * 3.Neither the software developers, the Parallel Computing Lab, UCLA, or any * affiliate of the UC system shall be liable for any damages suffered by * Licensee from the use of this software. */// Use the latest version of Parsec if this line causes a compiler error./* * $Id: tcp_input.pc,v 1.12 2001/02/16 04:17:42 jmartin Exp $ * * Ported from FreeBSD 2.2.2. * This file contains TCP input routine, follows pages 65-76 of RFC 793. *//* * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1994, 1995 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)tcp_input.c 8.12 (Berkeley) 5/24/95 * $Id: tcp_input.pc,v 1.12 2001/02/16 04:17:42 jmartin Exp $ */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <assert.h>#include "api.h"#include "main.h"#include "structmsg.h"#include "tcp.h"#include "transport.h"#include "in_pcb.h"#include "ip.h"#include "tcpip.h"#include "tcp_config.h"#include "tcp_hdr.h"#include "tcp_fsm.h"#include "tcp_proto.h"#include "tcp_seq.h"#include "tcp_timer.h"#include "tcp_var.h"static void data_adj(struct tcpiphdr *, int);static void submit_data(GlomoNode *, APP_TYPE, int, unsigned char *, int, struct tcpcb *);static void tcp_dooptions(struct tcpcb *, unsigned char *, int, struct tcpiphdr *, struct tcpopt *, unsigned long, struct tcpstat *); static void tcp_mss( struct tcpcb *, int, struct tcpstat * );static int tcp_reass(GlomoNode *, struct tcpcb *, struct tcpiphdr *, struct tcpstat *); static void tcp_xmit_timer(struct tcpcb *, int, struct tcpstat * ); staticvoid TransportTcpSetTimerForOutput(GlomoNode *node){ char clockStr[GLOMO_MAX_STRING_LENGTH]; Message *newMsg; newMsg = GLOMO_MsgAlloc(node, GLOMO_TRANSPORT_LAYER, TRANSPORT_PROTOCOL_TCP, MSG_TRANSPORT_Tcp_CheckTcpOutputTimer); GLOMO_MsgSend(node, newMsg, 0);}/* * Remove len bytes of data from a tcp segment. */static void data_adj(ti, len) struct tcpiphdr *ti; int len;{ unsigned char *old_start, *new_start; if (len < ti->ti_len){ old_start = (unsigned char *) (ti + 1) ; new_start = old_start + len; memcpy(old_start, new_start, ti->ti_len - len); }}/* * Reassemble received packets. * Deliver data to application if in sequence. */static inttcp_reass(node, tp, ti, tcp_stat) GlomoNode *node; struct tcpcb *tp; struct tcpiphdr *ti; struct tcpstat *tcp_stat;{ struct tcpiphdr *q, *ti1, *q1; int flags; struct inpcb *inp = tp->t_inpcb; /* * Call with ti==0 after become established to * force pre-ESTABLISHED data up to user */ if (ti == 0) goto present; /* * Find a segment which begins after this one does. */ for (q = tp->seg_next; q != (struct tcpiphdr *)tp; q = (struct tcpiphdr *)q->ti_next) if (SEQ_GT(q->ti_seq, ti->ti_seq)) break; /* * If there is a preceding segment, it may provide some of * our data already. If so, drop the data from the incoming * segment. If it provides all of our data, drop us. */ if ((struct tcpiphdr *)q->ti_prev != (struct tcpiphdr *)tp) { int i; q = (struct tcpiphdr *)q->ti_prev; /* conversion to int (in i) handles seq wraparound */ i = q->ti_seq + q->ti_len - ti->ti_seq; if (i > 0) { if (i >= ti->ti_len) { if (tcp_stat) { tcp_stat->tcps_rcvduppack++; tcp_stat->tcps_rcvdupbyte += ti->ti_len; } /* * Try to present any queued data * at the left window edge to the user. * This is needed after the 3-WHS * completes. */ pc_free(ti); goto present; } data_adj(ti, i); ti->ti_len -= i; ti->ti_seq += i; } q = (struct tcpiphdr *)(q->ti_next); } if (tcp_stat) { tcp_stat->tcps_rcvoopack++; tcp_stat->tcps_rcvoobyte += ti->ti_len; } /* * While we overlap succeeding segments trim them or, * if they are completely covered, dequeue them. */ while (q != (struct tcpiphdr *)tp) { int i = (ti->ti_seq + ti->ti_len) - q->ti_seq; if (i <= 0) break; if (i < q->ti_len) { data_adj(q, i); q->ti_len -= i; q->ti_seq += i; break; } q1 = q; q = (struct tcpiphdr *)q->ti_next; remque_ti((struct tcpiphdr *)q->ti_prev); pc_free(q1); } /* * Stick new segment in its place. */ insque_ti(ti, (struct tcpiphdr *)q->ti_prev);present: /* * Present data to user, advancing rcv_nxt through * completed sequence space. */ if (!TCPS_HAVEESTABLISHED(tp->t_state)) return (0); ti = tp->seg_next; if (ti == (struct tcpiphdr *)tp || ti->ti_seq != tp->rcv_nxt) return (0); do { tp->rcv_nxt += ti->ti_len; flags = ti->ti_flags & TH_FIN; remque_ti(ti); submit_data(node, inp->app_proto_type, inp->con_id, (unsigned char *)(ti + 1), ti->ti_len, tp); ti1 = ti; ti = (struct tcpiphdr *)ti->ti_next; pc_free(ti1); } while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt); return (flags);}/* * TCP input routine, follows pages 65-76 of the * protocol specification dated September, 1981 very closely. */voidtcp_input(node, payload, total_len, priority, p_head, tcp_iss, tcp_now, tcp_stat) GlomoNode *node; unsigned char *payload; int total_len; int priority; struct inpcb *p_head; tcp_seq *tcp_iss; unsigned long tcp_now; struct tcpstat *tcp_stat;{ struct tcpiphdr *ti; struct inpcb *inp; struct tcpcb *tp = NULL; unsigned char *tcp_seg; const int tcprexmtthresh = 3; unsigned char *optp = NULL; unsigned char *datap = NULL; int optlen = 0; int len, tlen, off; int tiflags; int todrop, acked, ourfinisacked, needoutput = 0; int iss = 0; struct tcpopt topt; unsigned long tiwin; int to_accept = 0; int flag; tcp_seg = (unsigned char *)pc_malloc(total_len); assert(tcp_seg != NULL); memcpy (tcp_seg, payload, total_len); memset((char *)&topt, 0, sizeof(topt)); if (tcp_stat) tcp_stat->tcps_rcvtotal++; /* * Get IP and TCP header together. Assume ip options has been striped. * Note: IP leaves IP header in tcp_seg. * */ ti = (struct tcpiphdr *)tcp_seg; if (total_len < sizeof (struct tcpiphdr)) { if (tcp_stat) tcp_stat->tcps_rcvshort++; pc_free(tcp_seg); return; } /* * Checksum extended TCP header and data. * Note here assumes ip hasn't subtracted ip header * length from ip_len (different from original code). * Assuming here that the source and destination IP address * fields and the packet length field have been correctly * set. */ len = ti->ti_len; tlen = len - sizeof(struct ipovly); ti->ti_len = tlen; /* * Zero and set this stuff in the "Extended pseudoheader" * for the checksum */ ti->ti_prev = 0; ti->ti_next = 0; ti->ti_x1 = 0; ti->ti_pr = IPPROTO_TCP; ti->ti_sum = in_cksum( (unsigned short *) tcp_seg, len); if (ti->ti_sum) { if (tcp_stat) tcp_stat->tcps_rcvbadsum++; goto drop; } /* * Check that TCP offset makes sense, * pull out TCP options and adjust length. XXX */ off = ti->ti_off << 2; if (off < sizeof (struct tcphdr) || off > tlen) { if (tcp_stat) tcp_stat->tcps_rcvbadoff++; goto drop; } tlen -= off; /* data length */ ti->ti_len = tlen; optlen = off - sizeof (struct tcphdr); optp = tcp_seg + sizeof(struct tcpiphdr); datap = optp + optlen; tiflags = ti->ti_flags; if (tcp_stat) { if (tlen > 0){ tcp_stat->tcps_rcvpack ++; tcp_stat->tcps_rcvbyte += ti->ti_len; } else if (tiflags & (TH_SYN|TH_FIN|TH_RST)) tcp_stat->tcps_rcvctrl ++; } /* * Locate pcb for segment. */findpcb: inp = in_pcblookup(p_head, ti->ti_dst, ti->ti_dport, ti->ti_src, ti->ti_sport, INPCB_NO_WILDCARD); /* * PCB doesn't exist, check if it's a connection request. * If so, prepare to accept the connection. Otherwise, drop * the packet. */ if (inp == p_head){ inp = in_pcblookup(p_head, ti->ti_dst, ti->ti_dport, ti->ti_src, ti->ti_sport, INPCB_WILDCARD); if (inp != p_head) to_accept = 1; else goto dropwithreset; } tp = intotcpcb(inp); if (tp->t_state == TCPS_CLOSED) goto drop; /* Unscale the window into a 32-bit value. */ if ((tiflags & TH_SYN) == 0) tiwin = ti->ti_win << tp->snd_scale; else tiwin = ti->ti_win; if (to_accept) { to_accept = 0; if ((tiflags & (TH_RST|TH_ACK|TH_SYN)) != TH_SYN) { /* * Note: dropwithreset makes sure we don't * send a RST in response to a RST. */ if (tiflags & TH_ACK) { if (tcp_stat) tcp_stat->tcps_badsyn++; goto dropwithreset; } goto drop; } inp = (struct inpcb *)tcp_attach(p_head, inp->app_proto_type, ti->ti_dst, ti->ti_dport, ti->ti_src, ti->ti_sport, -1, priority); if (inp == 0) { goto drop; } tp = intotcpcb(inp); tp->t_state = TCPS_LISTEN; /* Compute proper scaling value from buffer space */ while (tp->request_r_scale < TCP_MAX_WINSHIFT && TCP_MAXWIN << tp->request_r_scale < inp->inp_rcv_hiwat) tp->request_r_scale++; } /* * Segment received on connection. * Reset idle time and keep-alive timer. */ tp->t_idle = 0; if (TCPS_HAVEESTABLISHED(tp->t_state))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -