I managed to write a program with (Qbasic and a TSR I wrote) that picked up a network packet and displayed its contents in hex form. When analyzing it along with source code from the mTCP internet package for DOS, it turns out that I can start reading the IP header at the 15th byte. So I made code to reflect this:
;Here DS:DI contains the network packet including the IPV4 packet
;and ES:DI points to a far struct with a bunch of members to be filled in with data
xor AX,AX
xor BX,BX
mov AL,[DS:SI+0Eh] ;version + IHL (4 bits each)
mov CX,[DS:SI+0Ch] ;ether type (2 bytes)
mov BL,AL
and AL,0Fh
shr BL,04h
and BL,0Fh
mov [ES:DI+IPihl],AX ; IHL field value as 16-bit
mov [ES:DI+IPver],BX ;IP version value as 16-bit
mov [ES:DI+ethertype],CX ;ethernet type as CX (its returning 8h instead of 800h which is bad)
mov AL,[DS:SI+0Fh] ;DSCP + ECN fields. ECN needs to be 2 bits and DSCP 6 bits
mov BX,[DS:SI+10h] ;Length (Returns 15360. Isn't this too large of a value?)
mov CX,[DS:SI+12h] ;identification field
mov DX,[DS:SI+14h] ;Flag and Fragment offset combined
mov [ES:DI+IPdscpecn],AX ;Copy DSCP+ECN together to my struct
shr DX,13 ;move Flag feld to the right
mov [ES:DI+IPsz],BX ;store size
and DX,7h ;and limit flag field to 3 bits
mov BX,[DS:SI+14h] ;Get Flag and fragment offset again
mov [ES:DI+IPid],CX ;Store identification
and BX,1FFFh ;Take only the fragment offset value
mov [ES:DI+IPfl],DX ;Save the flag field
mov [ES:DI+IPfrago],BX ;Save fragment offset value
mov BX,[DS:SI+18h] ;Get header checksum
mov AL,[DS:SI+17h] ;Get protocol number (returns 6 which is correct)
mov [ES:DI+IPchks],BX ;header checksum
mov [ES:DI+IPprot],AX ;store protocol
mov ECX,[DS:SI+1Ah] ;Get source IP address
mov EDX,[DS:SI+1Eh] ;Get destination IP address
mov AL,[DS:SI+16h] ;Get time to live
mov [ES:DI+IPsrcaddr],ECX ;Save source address (seems to be backwards when printed in hex)
mov [ES:DI+IPdstaddr],EDX ;Save destination address
mov [ES:DI+IPttl],AX ;Store time to live (correct)
The part I think is the most problemmatic is the data length. I see the value 15360. If I took the value in hex, flip the bytes and converted it to normal, I get a small number like 60 or 64 which I think is reasonable because the only other item accessing the particular interface is a linux utility CURL just to attempt to access the IP.
How do I fix this?
Am I to do everything backwards on a bit-by-bit basis with a lot of shifting and carry checking?
I want a solution that would not be slow.
My goal is to extract each field of the IPV4 header correctly into 16-bit variables (or 32-bit variables in the case of IP addresses).
The reason I limit data collection to the external struct to 16 and 32-bit variables is because I evaluate the data in Quickbasic and their structs do not support 8-bit numbers directly.
Any advice?
Thanks