#include "tnn.h" #ifdef TCP_STACK LHEAD rxSegment; /* RX TCP-Segment. */ LHEAD txSegment; /* TX TCP-Segment. */ LHEAD rxDaten; /* RX-Buffer. */ static void StackRX(void); /* Eingehende RX Segmente. */ static void StackState(void); /* Statusanderungen. */ static void StackTX(void); /* Ausgehende TX Segmente. */ /* Initialisiere, */ void StackInitTCP(void) { inithd(&rxSegment); /* Frame fuer Empfangs-Liste. */ inithd(&txSegment); /* Frame fuer Sende-Liste. */ inithd(&rxDaten); /* RX-Bufferung. */ } /* TCP-Service */ void StackSRV(void) { StackRX(); /* Eingehende RX-Segmente. */ StackState(); /* Statusaenderungen. */ StackTX(); /* Ausgehende TX-Segmente. */ } /* Neues TX-Segment in die Sende-Liste anlegen/anhaengen. */ void PutTXStack(register int i , /* SOCKET */ MBHEAD *Data, /* Daten ohne TCP-Header. */ int DataLen, /* Datenlaenge. */ unsigned short Flags, /* TCP-Flag. */ unsigned char TState) /* Sendestatus. */ { STACKTX *TSeq; if ((TSeq = (STACKTX *)allocb(ALLOC_TCPSTACK)) == NULL) /* Buffer besorgen. */ { sockets[i].TState = TCP_RSTSENT; /* Kein Speicher,Verbindung zuruecksetzen*/ return; } TSeq->Sock = i; /* Socket setzen. */ TSeq->Data = Data; /* Daten setzen. */ TSeq->Flags = Flags; /* TCP-Flag setzen. */ TSeq->TState = TState; /* Sende-Status setzen. */ TSeq->TimeLast = time(NULL); TSeq->Timer = 0; /* Timer zuruecksetzen. */ TSeq->Retry = 0; /* Retry zuruecksetzen. */ ++sockets[i].PacNum; /* Ein Frame mehr in der Sende-Liste. */ relink((LEHEAD *)TSeq, (LEHEAD *)txSegment.tail); /* In die Sende-Liste */ } /* haengen. */ /* Entsorge alle RX-Daten. */ static void DelDatenRX(int Sock) { DATENRX *Drx; DATENRX *DrxPrev; for (Drx = (DATENRX *)rxDaten.head; /* Durchsuche RX-Datenliste. */ Drx != (DATENRX *)&rxDaten; Drx = DrxPrev) { DrxPrev = Drx->next; if (Drx->Sock != Sock) /* Socketvergleich. */ continue; /* Zum naechsten Eintrag. */ if (Drx->Data != NULL) /* Wenn es Daten gibt, */ dealmb(Drx->Data); /* entsorgen. */ dealoc((MBHEAD *)ulink((LEHEAD *)Drx)); /* RX-Segment entsorgen. */ } } /* Entsorge alle TX-Segment. */ static void DelTXSegment(int Sock) { STACKTX *TSeq; for (TSeq = (STACKTX *)txSegment.head; /* Durchsuche die TX-Segmentliste. */ TSeq != (STACKTX *)&txSegment; TSeq = TSeq->next) { if (TSeq->Sock != Sock) /* Socketvegleich. */ continue; /* Zum naechsten Eintrag. */ if (TSeq->Data != NULL) /* Wenn es daten gibt, */ dealmb(TSeq->Data); /* entsorgen. */ dealoc((MBHEAD *)ulink((LEHEAD *)TSeq)); /* TX-Segment entsorgen. */ return; } } /* Entsorge alle Buffer vom Socket. */ void DelSock(int Sock) { DelDatenRX(Sock); /* RX-Daten entsorgen. */ DelTXSegment(Sock); /* TX-Segmente entsorgen. */ DelSocket(Sock); /* Socket entsorgen. */ } /* Einen Eintrag aus der RX-Liste holen. */ DATENRX *GetBuffer(TSOCKET *Sock) { DATENRX *Drx; for (Drx = (DATENRX *)rxDaten.head; /* Durchsuche die RX-Liste. */ Drx != (DATENRX *)&rxDaten; Drx = Drx->next) { if (Sock->Socket != Drx->Sock) /* Socketvergleich. */ continue; /* Zum naechsten Socket. */ return(Drx); /* Aktueller Eintrag. */ } return(NULL); /* Kein Eintrag gefunden. */ } /* Eingehende TCP-Daten weiterleiten in die RX-Segmentliste. */ void TCPIPProcess(register IP *ip, register MBHEAD *bp) { MBHEAD *Data; STACKRX *RSeq; if ((Data = (MBHEAD *)allocb(ALLOC_MBHEAD)) == NULL) /* Buffer besorgen. */ return; /* Kein Speicher, Empfangsbuffer entsorgt der IP-Router. */ while (bp->mbgc != bp->mbpc) /* Alle Zeichen in den Buffer schreiben. */ putchr(getchr(bp), Data); rwndmb(Data); /* Buffer zurueckspulen. */ if ((RSeq = (STACKRX *)allocb(ALLOC_TCPSTACK)) == NULL)/* RX-Segment besorgen.*/ { dealmb(Data); /* Kein Speicher, Buffer entsorgen. */ return; } RSeq->Data = Data; /* Empfang-Daten setzen. */ RSeq->IpHdr = ip; /* IP-Header setzen. */ relink((LEHEAD *)RSeq, (LEHEAD *)rxSegment.tail); /* Umhaengen in die */ return; /* Empfangs-Liste. */ } /* TCP-Header lesen. */ void ReadTcpHeader(TCP *tcp, IP *ip, MBHEAD *bp) { int temp_flag; tcp->srcPort = get16(bp); /* Port-Nummer der Quelle. */ tcp->dstPort = get16(bp); /* Port-Nummer des Ziel. */ tcp->seqnum = get32(bp); /* Sequenznummer des 1. Datenbytes */ /* in diesem Segment. */ tcp->acknum = get32(bp); /* Bestaetigungsnummer. */ temp_flag = get16(bp); /* Flags einlesen. */ tcp->data_offset = (temp_flag >> 12) & 0x0f; /* Datenworte im header. */ tcp->res = (temp_flag >> 6) & 0x3f; /* nicht benutzt -> 0.*/ tcp->flags = temp_flag & 0x3f; /* URG,ACK,PSH,RST,SYN & FIN. */ tcp->window = get16(bp); /* Groesse des Buffers fuer diese Verb. */ tcp->checksum = get16(bp); /* CRC-Checksum. */ tcp->urgentPointer = get16(bp); /* Fuer wichtige Daten. */ if (tcp->flags == TSYN) /* Verbindungsaufbau. */ { int DataLen = 0, options = 0, i = 0; /* Gesamtlaenge ermitteln */ DataLen = ((tcp->data_offset * 4) + (ip->ihl * 4));/* (TCP-Header + Daten).*/ options = (DataLen - TCP_HEADER); /* Optionslaenge ermitteln */ /* (Data - TCP-Header abziehen). */ options = options / 2; for (i = 0; i < options; i++) tcp->options[i] = (char)get16(bp); /* Optionen setzen. */ } } /* Entsorge alte TX-Segmente. */ void DelSegment(register int i, TCP *tcp) { STACKTX *TSeq; for (TSeq = (STACKTX *)txSegment.head; /* Durchsuche alle TX-Segmente. */ TSeq != (STACKTX *)&txSegment; TSeq = TSeq->next) { if (TSeq->Sock != sockets[i].Socket) /* Socketvergleich. */ continue; /* Zum naechsten Segment. */ if (sockets[i].SendNext == tcp->acknum) /* Frame uebertragen. */ { --sockets[i].PacNum; /* Ein Frame weniger. */ sockets[i].SendEvent = TRUE; /* Select signalisieren - weiter senden. */ if (TSeq->Data != NULL) /* Nur wenn es Daten gibt. */ dealmb(TSeq->Data); /* Buffer leeren/entsorgen. */ dealoc((MBHEAD *)ulink((LEHEAD *)TSeq)); /* TX Segment entsorgen. */ return; } else /* Frame konnte nicht uebertragen werden. */ { if (sockets[i].TState != TCP_RSTSENT) sockets[i].SendEvent = FALSE; /* Select signalisieren - keine */ } /* weiteren Frame senden. */ } } /* Daten auslesen und fuer Funktion Recv bereitstellen. */ BOOLEAN ReadBuffer(register IP *ip, register TCP *tcp, register int i, MBHEAD *bp) { DATENRX *Drx; unsigned int DataLen = 0; /* Gesamtlaenge ermitteln (TCP-Header + Daten). */ DataLen = (ip->length) - ((tcp->data_offset * 4) + (ip->ihl * 4)); if (DataLen >= TCP_HEADER) DataLen -= TCP_HEADER; /* TCP-Header abziehen. */ else DataLen = 0; if (DataLen) /* Es gibt Daten. */ { if ((Drx = (DATENRX *)allocb(ALLOC_TCPSTACK)) == NULL) /* Besorge Buffer. */ return(TRUE); /* Speicher ist voll. */ /* Besorge Buffer. */ if ((Drx->Data = (MBHEAD *)allocb(ALLOC_TCPSTACK)) == NULL) { dealoc((MBHEAD *)ulink((LEHEAD *)Drx)); /* Buffer entsorgen. */ return(TRUE); /* Speicher ist voll. */ } Drx->Sock = sockets[i].Socket; /* Socket setzen. */ sockets[i].RecvEvent = TRUE; /* Select Siginalisieren, */ /* wir haben was empfangen. */ sockets[i].RecvNext += DataLen; /* Daten an den Seq-Wert anhaengen. */ while (DataLen--) /* Daten in Buffer schreiben. */ putchr(getchr(bp), Drx->Data); rwndmb(Drx->Data); /* Buffer zurueckspulen. */ relink((LEHEAD *) Drx, (LEHEAD *)rxDaten.tail); /* RX-Liste umhaengen. */ } return(FALSE); /* Frame angenommen. */ } /* Eingehende RX-Segment analysieren. */ int ReadRXStack(TCP *tcp, IP *ip, MBHEAD *bp) { register int i; for (i = 1; i < NUM_SOCKETS; ++i) /* Durchsuche die Socketliste. */ { switch(sockets[i].State) /* Socket status. */ { case TCP_LISTEN: /* LISTEN-Modus. */ if (tcp->flags != TSYN) /* Nur annehmen, wenn neue Verbindung. */ continue; /* Ansonsten zum naechsten Eintrag. */ if (sockets[i].LocalPort != tcp->dstPort) /* Portvergleich. */ continue; /* Zum naechsten Eintrag. */ if (tcp->flags == TSYN) { if (sockets[i].Listen++ >= sockets[i].MaxListen)/* in die Warteschlange. */ continue; /* Warteschlange ist voll, zum naechsten eintrag. */ } /* Verbindungsaufbau starten. */ sockets[i].IpDest = ip->source;/* Empfaenger, IP-Adresse setzen. */ sockets[i].tos = ip->tos; /* Type of Service setzen. */ sockets[i].RecvEvent = TRUE; /* Select signalisieren - */ /* wir haben was empfangen. */ sockets[i].DestPort = tcp->srcPort; /* Port-Nummer vom Ziel. */ sockets[i].UrgPointer = tcp->urgentPointer; /* Flags einlesen. */ sockets[i].RecvNext = tcp->seqnum + 1; sockets[i].SendUnacked = 1; sockets[i].SendNext = sockets[i].SendUnacked + 1; return(i); /* Socket uebergeben. */ case TCP_CONNECTED: /* CONNECTED-Modus. */ if (sockets[i].DestPort != tcp->srcPort) /* Destportvergleich! */ continue; return(i); /* Unser gesuchter Socket. */ } } return(EOF); /* Nix gefunden. */ } /* Verbindung nicht annehmen/zuruecksetzen. */ void SendRST(IP *ip, TCP *tcp) { register int NewSock; /* Neuen Socket anlegen. */ if ((NewSock = Socket(AF_INET, SOCK_STREAM, 0)) == EOF) return; /* Neuer Socket kann nicht erstellt werden. */ sockets[NewSock].IpDest = ip->source; sockets[NewSock].LocalPort = tcp->dstPort; sockets[NewSock].DestPort = tcp->srcPort; sockets[NewSock].SendUnacked= tcp->acknum; sockets[NewSock].RecvNext = tcp->seqnum + 1; SendTcpFlag(NewSock, /* Frame an den Nachbarn senden. */ NULL, 0, (TACK + TRST), 0, 0); DelSock(NewSock); /* Socket entsorgen. */ } /* ACK-Statusaendernungen. */ void StateACK(register int i, TCP *tcp) { if ( (sockets[i].SendUnacked != tcp->acknum) /* Noch nicht aktualisiert, */ &&(tcp->window != 0)) /* wenn noch was ins Fenster passt!. */ sockets[i].SendUnacked = tcp->acknum; /* ACK-Aktualisieren. */ switch(sockets[i].TState) /* Aktueller Status. */ { /* Status schliessen: */ case TCP_PSHWAITFIN : /* Sende alle offenstehende Packete. */ if (tcp->window == 0) /* Nachbar kann keine Daten mehr annehmen. */ sockets[i].SendEvent = FALSE; /* Select signalisieren, keine weiteren Frame senden */ else /* Nachbar kann daten annehmen. */ { if (sockets[i].PacNum) /* Es gibt noch Frame. */ { /* Neuer Status: */ sockets[i].TState = TCP_PSHSENTFIN; /* Naechstes Packet senden. */ sockets[i].SendEvent = TRUE;/* Select signalisieren, weiter senden.*/ } else /* Neuer Status: */ sockets[i].TState = TCP_FINSENT; /* Socket sofort schliessen. */ } break; case TCP_ACKWAIT : /* Status Stabil: Warte auf ACK-Bestaetigung. */ if (tcp->window == 0) /* Nachbar kann keine Daten mehr annehmen . */ sockets[i].SendEvent = FALSE;/* Select signalisieren, keine weiteren Frame senden. */ else /* Nachbar kann daten annehmen. */ { /* Neuer Status: */ sockets[i].TState = TCP_ESTABLISHED; /* Verbindung stabil. */ sockets[i].SendEvent = TRUE; /* Select Signalisieren, */ } /* weitere Frames senden. */ break; /* Status schliessen: */ case TCP_ACKWAITFIN : /* Warte auf ACK, danach FIN senden. */ sockets[i].TState = TCP_FINSENT; /* Neuer Status: */ /* Socket sofort schliessen. */ sockets[i].SendEvent = TRUE;/* Select Signalisieren, weitere Frames senden. */ break; case TCP_FINACKWAIT : /* Status schliessen: Warte auf ACK-Bestaetigung. */ sockets[i].TState = TCP_FINWAIT; /* Neuer Status: */ /* Warte auf FIN & ACK-Bestaetigung. */ sockets[i].SendEvent = TRUE;/* Select Signalisieren, weitere Frames senden. */ break; /* Status schliessen: */ case TCP_ACKWAITCLOSED : /* Warte auf ACK-Bestaetigung, Socket entfernen. */ sockets[i].TState = TCP_CLOSED; /* Entsorge Socket. */ break; } } /* RX-Segmente analysieren. */ static void StackRX(void) { STACKRX *RSeq; register int i; static TCP tcp; while ((RSeq = (STACKRX *)rxSegment.head) != (STACKRX *)&rxSegment) { ReadTcpHeader(&tcp, RSeq->IpHdr, RSeq->Data); /* TCP-Header lesen. */ /* Eingehende RX-Segment analysieren. */ if ((i = ReadRXStack(&tcp, RSeq->IpHdr, RSeq->Data)) != EOF) { ReadBuffer(RSeq->IpHdr, &tcp, i, RSeq->Data); switch (tcp.flags) { case (TACK + TFIN) : /* Nachbar will sofort getrennt werden. */ sockets[i].RecvEvent = TRUE; /* Select signalisieren, wir haben was empfangen. */ sockets[i].SendEvent = TRUE; /* Select signalisieren, weitere Frames senden. */ if ( (sockets[i].TState == TCP_ESTABLISHED) /* Verbindung stabil. */ ||(sockets[i].TState == TCP_ACKWAIT) ||(sockets[i].TState == TCP_PSHSENTFIN)) { sockets[i].RecvNext += 1; /* Bei Bestaetigung um ein erhoehen. */ SendTcpFlag(i, /* ACK & FIN mit ACK-bestaetigen. */ NULL, 0, TACK, WINSIZE, 0); /* Neuer Status: ACK & FIN */ sockets[i].TState = TCP_FINSENTCLOSED;/* an den Nachbarn schicken.*/ } if (sockets[i].TState == TCP_FINWAIT) /* FIN & ACK-Bestaetigung erhalten. */ { sockets[i].RecvNext += 1; /* Seq-Wert um eins erhoehen. */ SendTcpFlag(i, /* ACK-Bestaetigung senden. */ NULL, 0, TACK, WINSIZE, 0); sockets[i].TState = TCP_CLOSED;/* Socket kann geschlossen werden. */ } break; case (TACK + TPSH + TFIN) : /* Nachbar will sofort getrennt werden. */ sockets[i].RecvEvent = TRUE;/* Select signalisieren, wir haben was empfangen. */ sockets[i].SendEvent = TRUE;/* Select signalisieren, weitere Frames senden. */ SendTcpFlag(i, /* Verbindung zuruecksetzen. */ NULL, 0, TRST, WINSIZE, 0); sockets[i].TState = TCP_CLOSED; /* Neuer Status: Socket entsorgen. */ break; case (TACK) : /* ACK-Bestaetigung. */ StateACK(i, &tcp); break; case (TACK + TPSH) : /* Es sind Daten im Header. */ if (sockets[i].SendUnacked != tcp.acknum) sockets[i].SendUnacked = tcp.acknum; sockets[i].SendEvent = TRUE; SendTcpFlag(i, /* ACK-Bestaetigung senden. */ NULL, 0, TACK, WINSIZE, 0); /* Neuer Status: */ sockets[i].TState = TCP_ESTABLISHED; /* Verbindung stabil. */ break; case (TRST) : /* Verbindung zuruecksetzen. */ sockets[i].TState = TCP_RSTSENT; /* Socket entsorgen. */ sockets[i].SendEvent = TRUE; DelSock(i); break; } DelSegment(i, &tcp); } else SendRST(RSeq->IpHdr, &tcp); /* Verbindung nicht annehmen/zuruecksetzen. */ dealmb(RSeq->Data); /* Buffer entsorgen. */ dealoc((MBHEAD *)ulink((LEHEAD *)RSeq)); /* RX-Segment entsorgen. */ } } /* Je nach Status reagieren. */ static void StackState(void) { register int i; for (i = 1; i < NUM_SOCKETS; ++i) /* durchsuche alle Socket. */ { /* Socket mit Status */ if ( (sockets[i].State == TCP_CLOSED) /* Socket unbenutzt */ ||(sockets[i].State == TCP_LISTEN) /* Listen */ ||(sockets[i].TState == TCP_ESTABLISHED) /* Stabile Verbindung und */ ||(sockets[i].TState == TCP_PSHSENT)) /* Frame senden nicht beachten. */ continue; /* Zum naechsten Socket. */ switch(sockets[i].TState) /* Socket-Status. */ { case TCP_SYNCON: /* Verbindungsaufbau bestaetigen. */ PutTXStack(i, /* SYN & ACK senden.*/ NULL, 0, (TSYN + TACK), TCP_SYNCON); sockets[i].TState = TCP_PSHSENT; continue; /* Zum naechsten Socket. */ case TCP_FINSENT: /* Status schliessen: Socket sofort schliessen. */ PutTXStack(i, /* FIN & ACK senden. */ NULL, 0, (TACK + TFIN), TCP_FINSENT); sockets[i].TState = TCP_PSHSENT; /* Neuer Status: Frames senden. */ continue; /* Zum naechsten Socket. */ /* Status schliessen: */ case TCP_FINSENTCLOSED : /* Nach ACK-Bestaetigung, FIN & ACK-Senden.*/ PutTXStack(i, /* FIN & ACK senden. */ NULL, 0, (TACK + TFIN), TCP_FINSENTCLOSED); sockets[i].TState = TCP_PSHSENT; /* Neuer Status: Frames senden. */ continue; /* Zum naechsten Socket. */ /* Status schliessen: */ case TCP_PSHSENTFIN : /* Naechstes Frame senden. */ if (!sockets[i].PacNum) /* Alle Frame gesendet. */ sockets[i].TState = TCP_FINSENT; /* Neuer Status: FIN & ACK senden. */ continue; /* Zum naechsten Socket. */ case TCP_RSTSENT : /* Status schliessen: Verbindung zuruecksetzen. */ PutTXStack(i, /* Frame mit Flag RST senden. */ NULL, 0, TRST, TCP_RSTSENT); sockets[i].TState = TCP_PSHSENT; /* Neuer Status: Frames senden. */ continue; /* Zum naechsten Socket. */ case TCP_CLOSED : /* Socket leeren/entsorgen. */ DelSock(i); return; } } } /* Frame senden. */ static void StackTX(void) { STACKTX *TSeq; register int i; time_t now; for (TSeq = (STACKTX *)txSegment.head; /* Durchsuche alle Socket. */ TSeq != (STACKTX *)&txSegment; TSeq = TSeq->next) { if ((i = SearchSock(TSeq->Sock)) == EOF) /* Socket ermitteln. */ { /* Socket wurde mittlerweile geschlossen. */ if (TSeq->Data != NULL) /* Gibt es Daten. */ dealmb((MBHEAD *)TSeq->Data); /* Buffer leeren/entsorgen. */ dealoc((MBHEAD *)ulink((LEHEAD *)TSeq)); /* TX Segment entsorgen. */ return; } if (TSeq->Timer) /* Timer laeuft. */ { now = time(NULL); if (TSeq->TimeLast < now) { TSeq->TimeLast = time(NULL); if (TSeq->Timer < 20) { ++TSeq->Timer; continue; } /* Max. versuche ueberschritten. */ if (TSeq->Retry >= TCP_MAX_RETRY) { /* Socket soll geschlossen werden. */ if (sockets[i].TState == TCP_CLOSE) { /* Socket schliessen. */ sockets[i].TState = TCP_CLOSED; /* zum naechsten Frame. */ continue; } /* Socket soll geschlossen werden. */ sockets[i].TState = TCP_CLOSE; /* Select signalisieren. */ sockets[i].RecvEvent = TRUE; sockets[i].SendEvent = TRUE; continue; } ++TSeq->Retry; TSeq->Timer = 0; if (TSeq->Data != NULL) rwndmb(TSeq->Data); sockets[i].TState = TCP_PSHSENT; } } if ( (sockets[i].TState == TCP_PSHSENT) /* Frame an den Nachbarn senden */ ||(sockets[i].TState == TCP_ESTABLISHED) /* wenn Verbindung stabil. */ ||(sockets[i].TState == TCP_PSHSENTFIN)) /* Socket soll geschloessen */ { /* werden, vorher alle Frames senden. */ SendTcpFlag(i, /* Frame senden. */ TSeq->Data, (TSeq->Data == NULL ? 0 : TSeq->Data->mbpc - TSeq->Data->mbgc), TSeq->Flags, WINSIZE, (unsigned short)(TSeq->Flags == (TSYN + TACK) ? TCP_OPTION : FALSE)); if ((unsigned short)(TSeq->Flags == (TSYN + TACK))) { sockets[i].TState = TCP_ACKWAIT; /* Warte auf ACK-Bestaetigung. */ ++TSeq->Timer; /* Timer starten. */ continue; /* Zum naechsten Frame. */ } switch(TSeq->TState) /* Statusaendung. */ { case TCP_ESTABLISHED : /* Status: Stabile Verbindung. */ case TCP_PSHSENT : /* Status: Frame senden. */ if (sockets[i].TState == TCP_PSHSENTFIN) { sockets[i].TState = TCP_PSHWAITFIN;/* offenstehende Frames senden */ ++TSeq->Timer; /* Timer starten. */ continue; /* Zum naechsten Frame. */ } /* Neuer Status: */ sockets[i].TState = TCP_ACKWAIT; /* Warte auf ACK-Bestaetigung. */ ++TSeq->Timer; /* Timer starten. */ continue; /* Zum naechsten Frame. */ case TCP_PSHSENTFIN : /* Status schliessen: Naechstes Packet senden. */ sockets[i].TState = TCP_PSHWAITFIN;/* Status: Warte auf ACK-Meldung.*/ ++TSeq->Timer; /* Timer starten. */ continue; /* Zum naechsten Frame. */ case TCP_FINSENT :/* Status schliessen: Socket soll geschlossen werden*/ sockets[i].TState = TCP_FINACKWAIT; /* Neuer Status: Warte auf ACK. */ ++TSeq->Timer; /* Timer starten. */ continue; /* Zum naechsten Frame. */ /* Status schliessen: */ case TCP_FINSENTCLOSED : /* Nach ACK-Bestaetigung, FIN & ACK-Senden.*/ sockets[i].TState = TCP_ACKWAITCLOSED;/* Neuer Status: Warte auf ACK*/ ++TSeq->Timer; /* Timer starten. */ continue; /* Zum naechsten Frame. */ case TCP_RSTSENT : /* Verbindung zuruecksetzen. */ sockets[i].TState = TCP_CLOSED; /* Neuer Status: .Socket schliessen.*/ ++TSeq->Timer; /* Timer starten. */ continue; /* Zum naechsten Frame. */ default: /* Fuer alle restlichen Status. */ continue; /* Zum naechsten Frame. */ } } } } /* TCP-Header zusammenbasteln. */ MBHEAD * htontcp(register int i, /* Aktueller Socket. */ MBHEAD *Data, /* evl. Daten. */ unsigned short flags, /* TCP-Flags. */ unsigned short tcp_len, /* Headerlaenge. */ unsigned short WinSize, /* Fenstergroesse. */ BOOLEAN options) /* evl. Optionen. */ { register MBHEAD *bp; PSEUDO_HEADER pseudo_hdr; unsigned short checksum; WORD DataMbpc; /* Sicherung mbpc */ WORD DataMbgc; /* Sicherung mbgc. */ int SaveLen; bp = (MBHEAD *)allocb(ALLOC_MBHEAD); /* Buffer besorgen. */ put16((unsigned short)sockets[i].LocalPort, bp); /* Dest-Portīsetzen. */ put16((unsigned short)sockets[i].DestPort, bp); /* Source-Port setzen. */ put32((unsigned long)sockets[i].SendUnacked, bp); /* Ack-Nummer setzen. */ put32((unsigned long)sockets[i].RecvNext, bp); /* Seq-Nummer setzen. */ put16((unsigned short)flags, bp); /* TCP-Flags setzen. (ACK, FIN, SYN...). */ put16((unsigned short)WinSize, bp); /* Fenstergroesse setzen. */ put16((unsigned short)0, bp); /* Checksum ERSTMAL auf 0 setzen. */ put16((unsigned short)sockets[i].UrgPointer, bp); /* Urgent-Flag setzen. */ if (options) /* Nur wenn Optionen gewuenscht wird setzen. */ { put16((unsigned short)OPTEND, bp); /* End of Option List. */ put16((unsigned short)OPTMSS, bp); /* Maximum Segment Size. */ put16((unsigned short)OPTNOO, bp); /* No-Operation. */ put16((unsigned short)OPTPA3, bp); } else /* Keine Optionen setzen. */ { if (tcp_len > TCP_HEADER) /* Es gibt daten. */ { int i = 0; SaveLen = i = Data->mbpc - Data->mbgc; /* Laenge ermitteln. */ DataMbpc = Data->mbpc; /* Werte sichern. */ DataMbgc = Data->mbgc; while (i--) /* Alle zeichen einlesen und */ putchr(getchr(Data), bp); /* in Buffer schreiben. */ rwndmb(Data); /* Buffer zurueckspulen. */ } } rwndmb(bp); /* Frame zurueckspulen. */ /************************ Pseudo-Header ermitteln. *************************/ pseudo_hdr.source = my_ip_addr; /* Unsere IP-Adresse. */ pseudo_hdr.dest = sockets[i].IpDest; /* IP-Adresse vom Nachbarn. */ pseudo_hdr.protocol = TCP_PTCL; /* Protokoll-Typ. */ pseudo_hdr.length = tcp_len; /* TCP-Header + Daten. */ checksum = cksum(&pseudo_hdr, bp, (unsigned short)tcp_len);/* Checksume ermitteln. */ dealmb(bp); /* Alten buffer loeschen. */ bp = (MBHEAD *)allocb(ALLOC_MBHEAD); /* Neuen buffer besorgen. */ put16((unsigned short)sockets[i].LocalPort, bp); /* Dest-Portīsetzen. */ put16((unsigned short)sockets[i].DestPort, bp); /* Source-Port setzen. */ put32((unsigned long)sockets[i].SendUnacked, bp); /* Ack-Nummer setzen. */ put32((unsigned long)sockets[i].RecvNext, bp); /* Seq-Nummer setzen. */ put16((unsigned short)flags, bp); /* TCP-Flags setzen. (ACK, FIN, SYN...) */ put16((unsigned short)WinSize, bp); /* Fenstergroesse setzen. */ put16((unsigned short)checksum, bp); /* Checksum setzen. */ put16((unsigned short)sockets[i].UrgPointer, bp); /* Urgent-Flag setzen. */ if (options) /* Nur wenn Optionen gewuenscht wird setzen. */ { put16((unsigned short)OPTEND, bp); /* End of Option List. */ put16((unsigned short)OPTMSS, bp); /* Maximum Segment Size. */ put16((unsigned short)OPTNOO, bp); /* No-Operation. */ put16((unsigned short)OPTPA3, bp); } else /* Keine Optionen setzen. */ { if (tcp_len > TCP_HEADER) /* Es gibt daten. */ { int i = 0; i = Data->mbpc - SaveLen; /* Laenge ermitteln. */ if (i != Data->mbpc) { while (i--) getchr(Data); } while (SaveLen--) /* Alle zeichen einlesen und */ putchr(getchr(Data), bp); /* in buffer schreiben. */ } } rwndmb(bp); /* Daten zurueckspulen. */ return (bp); } /* Frame fuer IP-Router vorbereiten. */ void SendTcpFlag(register int i, /* Aktueller Socket. */ MBHEAD *Data, /* Reine Daten. */ unsigned int DataLen, /* Bufferlaenge. */ unsigned short Flag, /* TCP-Flags. */ unsigned short WinSize, /* Fenstergroesse setzen.*/ unsigned short Options) /* Optionen setzen. */ { MBHEAD *bp; unsigned short TcpLen; unsigned short TcpFlags; /* TCP-Headerlaenge + evl. Optionen + */ TcpLen = TCP_HEADER + Options + DataLen; /* Reine Daten ermitteln. */ if (Options) /* Nur wenn Optionen gewuenscht wird setzen. */ { TcpFlags = (TCP_HEADER + Options) << 10; /* TCP-Header + Optionen setzen.*/ Options = TRUE; /* Optionen setzen. */ } else /* Keine Optionen. */ { TcpFlags = TCP_HEADER << 10; Options = FALSE; /* Keine Optionen. */ } TcpFlags |= Flag; bp = htontcp(i, /* TCP-Header + Daten zusammenfuegen. */ Data, TcpFlags, TcpLen, WinSize, Options); ip_send(my_ip_addr, /* IP-Header basteln und ab in den IP-Router. */ sockets[i].IpDest, TCP_PTCL, sockets[i].tos, 0, bp, 0, 0, 0); } #endif /* TCPSTACK */ /* End of src/l3tcp.c. */