Hallo.
Ich Schreibe zurzeit auf Linux einen Webserver basierend auf
raw-sockets, um diesen später auf Mikrocontrollern verwenden zu können.
Ich habe bereits das ARP und das ICMP protocol implementiert. Einige
ping abfragen funktionieren auch, aber dann stürzt das Programm ab. Ich
finde den fehler einfach nicht, weder mit gdb noch mit valgrind konnte
ich die Uhrsache finden.
Das Projekt:
https://github.com/Daniel-Abrecht/DPA-UCS/tree/4572546dcaf9bae11d4227ffe5d25165ef1ed3f1
Ausgabe von Valgrind:
rtt min/avg/max/mdev = 35.107/57.925/80.882/18.514 ms
Verwendeter Compiler:
1
daniel@daniel-Inspiron-7720:~$ gcc --version
2
gcc (Ubuntu 4.9.2-10ubuntu13) 4.9.2
3
Copyright (C) 2014 Free Software Foundation, Inc.
4
This is free software; see the source for copying conditions. There is NO
5
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Ich kann mir einfach nicht erklären, wie die Variable
currentTransmission.to in der Datei src/server/protocol/ip.c auf Zeile
69 den Wert 0x40 haben konnte.
Wo hab ich diesmal einen Fehler gemacht? Meine debugging fähigkeiten
stossen hier an ihre Grenzen.
aufgerufen? Bzw. wo werden die drei Parameter, die an die Funktion zu
übergeben sind, auf ihre richtigen Werte gesetzt? Hab es auf die
Schnelle durch Ankucken der .c Dateien im Browser nicht gefunden.
Bzw. es könnte hier drin versteckt sein:
1
while(true){
2
if(
3
!(*handler)(
4
&f->info->src,
5
&f->info->dest,
6
&IPv4_transmissionBegin,
7
&IPv4_transmissionEnd,
8
f->offset,
9
f->length,
10
payload,
11
!(fragment.flags&IPv4_FLAG_MORE_FRAGMENTS)
12
)
Aber da mag ich nicht drin rumsuchen. Muss man den Code so verworren
schreiben, oder geht es auch normal? ;-)
Welchen Übergabewert Parameter an eine Funktion haben bzw. wo genau die
Zuweisung passiert, sollte in aller Regel auf einen Blick erfassbar
sein. Wenn das nicht der Fall ist, macht man sich das Leben damit
unnötig schwer.
Da das Ganze im Moment eh auf Linux läuft, hindert Dich ja nichts daran
Debug-Informationen auf die Konsole und/oder in eine Datei auszugeben.
Das wäre so das Erste, was ich persönlich machen würde.
>> aufgerufen? Bzw. wo werden die drei Parameter, die an die Funktion zu> übergeben sind, auf ihre richtigen Werte gesetzt? Hab es auf die> Schnelle durch Ankucken der .c Dateien im Browser nicht gefunden.
Das ist in src/server/protocol/icmp.c
Villeicht sollte ich das in DPAUCS_icmpInit() umbenenenn...
> Aber da mag ich nicht drin rumsuchen. Muss man den Code so verworren> schreiben, oder geht es auch normal? ;-)
Nunja, später soll handler auch &DPAUCS_tcp_handler oder
&DPAUCS_udp_handler sein können und ich will mir die möglichkeit
offenhalten später auch z.B. IPv6 zu implementieren, ohne später höhere
layer verändern zu müssen. Ausserdem will ich icmp oder tcp support
einfach deaktivieren können, ohne viel am Code ändern zu müssen.
Was wäre den hier gut und normal? Wäre ein switch case und week symbols
besser? Oder ein switch case mit Makros?
> Welchen Übergabewert Parameter an eine Funktion haben bzw. wo genau die> Zuweisung passiert, sollte in aller Regel auf einen Blick erfassbar> sein. Wenn das nicht der Fall ist, macht man sich das Leben damit> unnötig schwer.
Ist dass den nicht immer schwierig wenn man ein Projekt zum ersten mal
sieht?
> Da das Ganze im Moment eh auf Linux läuft, hindert Dich ja nichts daran> Debug-Informationen auf die Konsole und/oder in eine Datei auszugeben.> Das wäre so das Erste, was ich persönlich machen würde.
Stimmt, das werde ich morgen mal versuchen.
Debug ausgaben auf der Konsole auszugeben hat mir nur Dinge gezeigt, die
ich sowiso schon wusste. Mit gdb konnte ich dass problem jetzt jedoch
eindeutig identifizieren. Es ist ein Buffer Overflow.
Ausschnitt aus gdb:
1
Hardware watchpoint 2: currentTransmission.from
2
3
Old value = (void *) 0x7fffffffe3bc
4
New value = (void *) 0x1
5
0x000000000040189d in DPAUCS_stream_referenceWrite (stream=0x6a7120 <outputStream>,
6
p=0x6a7264 <packetInputBuffer+36>, size=64) at src/server/stream.c:32
7
32 BUFFER_PUT(stream->buffer_buffer,entry);
8
(gdb) backtrace
9
#0 0x000000000040189d in DPAUCS_stream_referenceWrite (stream=0x6a7120 <outputStream>,
10
p=0x6a7264 <packetInputBuffer+36>, size=64) at src/server/stream.c:32
11
#1 0x0000000000402473 in DPAUCS_icmp_handler (from=0x7fffffffe3b0, to=0x7fffffffe3bc,
Daniel A. schrieb:> Das ist in src/server/protocol/icmp.c
Bei einer static-Funktion fände ich es sinnvoller, wenn man dies auch im
gleichen Modul wiederfinden würde.
Ich verstehe das static Keyword bei globalen Symbolen als prinzip der
Sichtbarkei derselben, welches dazu benutzt werden kann die direkte
verwendung des Symbols in anderen Compilationsunits zu verhindern. Wo
die Variable verwendet wird spielt keine Rolle, wichtig ist, dass das
Symbol nur in der selben Compilationsunit verwendet werden kann und
damit die versehentliche Mehrfachdefinition von Symbolen mit
unterschiedlichem zweck vermieden wird. Ich weiss, das es in diesem fall
nicht notwendig wäre, aber ich versuche meine Designgrundsätze
konsistent beizubehalten. Ausserdem kommt man so nicht auf die Idee nach
dem Symbol an Orten zu suchen, wo es nicht vorkommen kann.