Forum: Mikrocontroller und Digitale Elektronik TCP/IP Stack - Connection closed nach ACK


von MiSc (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
ich bin gerade dabei einen TCP/IP Stack auf einem ATMega32 zu 
implementieren, als Netzwerk Schnittstelle kommt ein ENC28J60 zum 
Einsatz.

ARP, ICMP, DHCP und UDP funktionieren soweit schon einmal, doch beim TCP 
Teil gibt es ein Problem.
Ich teste den TCP Stack, indem ich mich mit einem Telnet-Client (telnet 
unter Linux) zum µC verbinde. Der Handshake funktioniert auch ohne 
Probleme, doch sofort nach dem Handshake meldet telnet "Connection 
closed by foreign host.", jedoch sendet weder der telnet Client noch der 
ATMega weitere Pakete (siehe WireShark Datei / Screenshot).
Verbinde ich mich mit dem telnet Client zu einem anderen Server (z.B. 
XAMPP), sehe ich in Wireshark die gleichen Pakete, allerdings bricht die 
Verbindung nicht ab, und ich kann mit telnet Pakete verschicken.

Weiß jemand wo der Fehler liegen könnte?

Hier ist der Ausschnitt der zugehörigen C Datei:
1
void handle_tcp(uint8_t* data) {
2
 EthernetFrame* eth = (EthernetFrame*)(data);
3
 TCPHeader* tcp = (TCPHeader*)(data + TCP_HEADER_POS);
4
 IPHeader* ip = (IPHeader*)(data + IP_HEADER_POS);
5
 
6
 // look if this port is registered
7
 uint8_t idx, i, len1;
8
 if((idx = tcpFindEntry(ntohs(tcp->dst_port))) < MAX_TCP_SOCKETS) {
9
10
  // syn from client
11
  if((tcp->flags & TCP_FLAG_MASK) == TCP_SYN && TCPSocket[idx].status == TCP_LISTENING) {
12
   
13
   TCPSocket[idx].status = TCP_SYN_RECV;
14
   TCPSocket[idx].ack_nr = ntohl(tcp->seq_nr) + 1;
15
   TCPSocket[idx].seq_nr = network_clock;
16
   TCPSocket[idx].src_port = ntohs(tcp->src_port);
17
   TCPSocket[idx].window = 384;
18
19
   generateEthernetFrame(send_buffer, eth->MAC_src, 0x0800); // ethernet: ip
20
   generateIPHeader(send_buffer + IP_HEADER_POS, ip->ip_src, 0x06, IP_HEADER_LEN + TCP_HEADER_LEN + 4 + 4);
21
   generateTCPPacket(send_buffer + TCP_HEADER_POS, idx, 0);
22
23
   // send syn | ack
24
   enc28j60PacketSend(MAX(60, ETHERNET_FRAME_LEN + IP_HEADER_LEN + TCP_HEADER_LEN + 4 + 4), send_buffer);
25
   return;
26
  }
27
 
28
   // send ack
29
  if((tcp->flags & TCP_ACK) && TCPSocket[idx].status == TCP_ESTABLISHED) {
30
   uint16_t len =  ntohs(ip->ip_len) - IP_HEADER_LEN;
31
   len -= tcp->off / 4;
32
33
   TCPSocket[idx].seq_nr = ntohl(tcp->ack_nr);
34
   TCPSocket[idx].ack_nr = ntohl(tcp->seq_nr) + len;
35
36
   generateEthernetFrame(send_buffer, eth->MAC_src, 0x0800); // ethernet: ip
37
   generateIPHeader(send_buffer + IP_HEADER_POS, ip->ip_src, 0x06, IP_HEADER_LEN + TCP_HEADER_LEN + TSV_LEN);
38
   generateTCPPacket(send_buffer + TCP_HEADER_POS, idx, 0);
39
40
   // send ack
41
   enc28j60PacketSend(MAX(60, ETHERNET_FRAME_LEN + IP_HEADER_LEN + TCP_HEADER_LEN + TSV_LEN), send_buffer);
42
43
   return;
44
  }
45
  
46
  // ack from client
47
  if((tcp->flags & TCP_FLAG_MASK) == TCP_ACK && TCPSocket[idx].status == TCP_SYN_RECV) {
48
   TCPSocket[idx].status = TCP_ESTABLISHED;
49
   TCPSocket[idx].seq_nr = ntohl(tcp->seq_nr);
50
   return;
51
  }
52
  
53
  // end connection
54
  if((tcp->flags & TCP_FIN) || (tcp->flags & TCP_RST)) {
55
   TCPSocket[idx].status = TCP_LISTENING;
56
   return;
57
  }
58
 }
59
}
60
61
void generateTCPPacket(uint8_t* data, uint8_t idx, uint16_t length) {
62
 TCPHeader* tcp = (TCPHeader*)(data);
63
64
 tcp->src_port = htons(TCPSocket[idx].port);
65
 tcp->dst_port = htons(TCPSocket[idx].src_port);
66
 tcp->flags = 0;
67
 switch(TCPSocket[idx].status) {
68
  case TCP_SYN_RECV:
69
   tcp->flags = TCP_SYN | TCP_ACK;
70
   break;
71
  
72
  case TCP_ESTABLISHED:
73
   tcp->flags = TCP_ACK;
74
   break;
75
 }
76
77
 tcp->off = 80;
78
 tcp->window_size = htons(TCPSocket[idx].window);
79
 tcp->urgent_ptr = 0;
80
 tcp->checksum = 0;
81
 tcp->seq_nr = htonl(TCPSocket[idx].seq_nr);
82
 tcp->ack_nr = htonl(TCPSocket[idx].ack_nr);
83
 
84
 if((TCPSocket[idx].status == TCP_SYN_RECV) ) {
85
  data[TCP_HEADER_LEN] = 2;
86
  data[TCP_HEADER_LEN + 1] = 4;
87
  data[TCP_HEADER_LEN + 2] = (TCP_MSS >> 8) & 0xff;
88
  data[TCP_HEADER_LEN + 3] = TCP_MSS & 0xff;
89
  
90
  data[TCP_HEADER_LEN + 4] = 1; // nop
91
  data[TCP_HEADER_LEN + 5] = 3; // windows scale = 0
92
  data[TCP_HEADER_LEN + 6] = 3;
93
  data[TCP_HEADER_LEN + 7] = 0;
94
  
95
  tcp->off = 0x60 + 16;
96
  length += 4 + 4;
97
 }
98
 
99
 uint16_t data_len = TCP_HEADER_LEN + length + 8;
100
 uint32_t start_val = data_len - 2;
101
102
 tcp->checksum = htons(checksum((data - IP_HEADER_LEN + 12), start_val, data_len));
103
}

von MiSc (Gast)


Lesenswert?

Ich habe den Fehler mittlerweile gefunden, schuld am Schließen der 
Verbindung war unter anderem der Router.

Dieser hat nach dem Handshake ein RST an den PC gesendet, hat aber als 
Absender IP die des ATMega Servers verwendet. Bei meiner weiteren 
Analyse habe ich entdeckt, dass er das macht, weil durch einen Fehler 
von mir das IG Bit in der MAC Adresse gesetzt war. Aus welchem Grund der 
Router das RST Paket gesendet hat, ist mir zwar dennoch nicht klar, 
jedoch funktioniert es jetzt.

Vielleicht hat ja jemand einmal ein ähnliches Problem und meine Lösung 
hilft dabei das Problem zu lösen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.