IP/TCP/UDP header vs C/C++
NOTE: This article is written in Romanian, for a translation please add me a comment.
Ei bine… nu mare imi fu uimirea dupa ultimile proiecte / teme, mici aplicatii. Uimirea ca habar nu am sa scriu un header tcp. Toata povestea a plecat de la o tema pentru facultate. Un modul de kernel linux/windows care trebuia sa filtreze pachetele TCP si UDP.
Asa ca… mai dupa explicatiile unui coleg, mai cu burta pe wikipedia & others… am priceput cum arata headerele pentru fiecare element mentionat mai sus, si… simt nevoia sa impartasesc si celorlalti, ca poate voua v-o fi mai usor decat mine alta data.
Dar am sa va trec mai intai prin header-ul ipv4, pentru ca trebuie sa stiti si despre el.
IP Header
Una bucata varianta ar fi astfel:
struct iphdr { unsigned char header_length:5, version:4; // nu stiu de ce am vaga impresie ca acel cinci e de fapt 4 :( unsigned char tos; unsigned short int length; unsigned short int id; unsigned char flags; unsigned short int offset; unsigned char ttl; unsigned char protocl; unsigned short int checksum; unsigned int id_src; unsigned int ip_dst; };
care separa header length de version, si care poate fi mult mai folositoare in cazul in care aveti nevoie de cele doua variabile.
In caz contrar, recomand
struct iphdr { UCHAR version; // Version and length UCHAR tos; // Type of service USHORT length; // Total datagram length USHORT id; // Identification USHORT flags; // Flags UCHAR ttl; // Time to live UCHAR protocol; // Protocol USHORT checksum; // Header checksum ULONG source; // Source address ULONG dest; // Destination address };
Ca studiu de caz ca ofer structura ipdhr extrasa din Linux kernel 2.6.24.2:
struct iphdr { #if defined(__LITTLE_ENDIAN_BITFIELD) __u8 ihl:4, version:4; #elif defined (__BIG_ENDIAN_BITFIELD) __u8 version:4, ihl:4; #else #error "Please fix " #endif __u8 tos; __be16 tot_len; __be16 id; __be16 frag_off; __u8 ttl; __u8 protocol; __sum16 check; __be32 saddr; __be32 daddr; /*The options start here. */ };
cu urmatoarele definitii:
typedef unsigned char __u8; typedef __u16 __bitwise __be16; // typedef unsigned short __u16; typedef __u16 __bitwise __sum16; // (despre __bitwise mai caut) typedef __u32 __bitwise __be32; // typedef unsigned int __u32;
Referinte:
+ http://en.wikipedia.org/wiki/IPv4
+ http://www.codeproject.com/KB/IP/drvfltip.aspx
TCP Header
Despre headerul tcp, nu prea are rost sa va povestesc eu, cand veti putea gasit explicat totul f.f.f.f. bine aici: http://en.wikipedia.org/wiki/Transmission_Control_Protocol
Ca si la header-ul ip, va ofer mai intai o varianta detaliata, in asa fel incat se poate prelua fiecare componenta in parte.
struct tcphdr { USHORT sourcePort; // Source Port USHORT destinationPort; // Destination Port ULONG nSequence; // Number of Sequence ULONG nAck; // Number of aknowledge UCHAR unused:4; // Unused UCHAR offset:4; // Data offset UCHAR fin:1, syn:1, rst:1, psh:1, ack:1, urg:1, ece:1, cwr:1; // Flags USHORT window; // Size of window USHORT checksum; // Total checksum USHORT urp; // Urgent pointer };
Daca insa NU ne intereseaza lucrul acesta, recomand versiunea urmatoare,
struct tcphdr { USHORT source; // Source Port USHORT dest; // Destination Port ULONG seq; // Number of Sequence ULONG nack; // Number of aknowledge UCHAR dataoffset; // Pointer to data UCHAR flags; // Flags USHORT windows; // Size of window USHORT checksum; // Total checksum USHORT urgentPointer; // Urgent pointer };
luand in calcul faptul ca pentru flags putem face teste cu expresii de tipul:
((struct tcphdr *)->flags & 0x01) // pentru FIN // #define CWR 128 // 0x80 // #define ECE 64 // 0x40 // #define URG 32 // 0x20 // #define ACK 16 // 0x10 // #define PSH 8 // 0x08 // #define RST 4 // 0x04 // #define SYN 2 // 0x02 // #define FIN 1 // 0x01
Din nou, ca stiudiu de caz – strucutra tcphdr din Linux kernel:
struct tcphdr { __be16 source; __be16 dest; __be32 seq; __be32 ack_seq; #if defined(__LITTLE_ENDIAN_BITFIELD) __u16 res1:4, doff:4, fin:1, syn:1, rst:1, psh:1, ack:1, urg:1, ece:1, cwr:1; #elif defined(__BIG_ENDIAN_BITFIELD) __u16 doff:4, res1:4, cwr:1, ece:1, urg:1, ack:1, psh:1, rst:1, syn:1, fin:1; #else #error "Adjust your defines" #endif __be16 window; __sum16 check; __be16 urg_ptr; };
Referinte:
+ http://en.wikipedia.org/wiki/Transmission_Control_Protocol
+ http://www.codeproject.com/KB/IP/drvfltip.aspx
+ http://www.tenouk.com/Module43b.html
UDPHeader
Ca ultima tema, headerul UDP, explicat iarasi, pe indelete in aceasta pagina: http://en.wikipedia.org/wiki/User_Datagram_Protocol,
care este insa mult mai simplu, si mult mai usor de transpus in cod:
struct udphdr { USHORT source; // Source Port USHORT dest; // Destination Port USHORT len; // Total length USHORT checksum; // Total checksum }; si ca studiu de caz - struct udphdr din Linux Kernel:struct udphdr { __be16 source; __be16 dest; __be16 len; __sum16 check; };Referinte:
+ http://en.wikipedia.org/wiki/User_Datagram_Protocol
+ http://www.codeproject.com/KB/IP/drvfltip.aspx
+ http://www.tenouk.com/Module43b.html