Improved RAW sockets. Added ability to set TTL thorugh setsockopt, Improved ping program.

git-svn-id: svn://kolibrios.org@5842 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
hidnplayr 2015-10-11 18:23:40 +00:00
parent 3315ff7280
commit b6883ee547
12 changed files with 617 additions and 368 deletions

View File

@ -215,7 +215,6 @@ macro IPv4_checksum ptr {
; It will also re-construct fragmented packets ; It will also re-construct fragmented packets
; ;
; IN: Pointer to buffer in [esp] ; IN: Pointer to buffer in [esp]
; size of buffer in [esp+4]
; pointer to device struct in ebx ; pointer to device struct in ebx
; pointer to IPv4 header in edx ; pointer to IPv4 header in edx
; size of IPv4 packet in ecx ; size of IPv4 packet in ecx
@ -223,7 +222,7 @@ macro IPv4_checksum ptr {
; ;
;----------------------------------------------------------------- ;-----------------------------------------------------------------
align 4 align 4
IPv4_input: ; TODO: add IPv4 raw sockets support IPv4_input:
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: packet from %u.%u.%u.%u ",\ DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: packet from %u.%u.%u.%u ",\
[edx + IPv4_header.SourceAddress + 0]:1,[edx + IPv4_header.SourceAddress + 1]:1,\ [edx + IPv4_header.SourceAddress + 0]:1,[edx + IPv4_header.SourceAddress + 1]:1,\
@ -232,6 +231,10 @@ IPv4_input: ; TODO: add IPv4
[edx + IPv4_header.DestinationAddress + 0]:1,[edx + IPv4_header.DestinationAddress + 1]:1,\ [edx + IPv4_header.DestinationAddress + 0]:1,[edx + IPv4_header.DestinationAddress + 1]:1,\
[edx + IPv4_header.DestinationAddress + 2]:1,[edx + IPv4_header.DestinationAddress + 3]:1 [edx + IPv4_header.DestinationAddress + 2]:1,[edx + IPv4_header.DestinationAddress + 3]:1
call NET_ptr_to_num4
cmp edi, -1
je .invalid_device
;------------------------------- ;-------------------------------
; re-calculate the checksum ; re-calculate the checksum
@ -240,40 +243,32 @@ IPv4_input: ; TODO: add IPv4
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Checksum ok\n" DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Checksum ok\n"
;----------------------------------- ;--------------------------------
; Check if destination IP is correct ; Check if destination IP matches
call NET_ptr_to_num4
; check if it matches local ip (Using RFC1122 strong end system model)
; local ip (Using RFC1122 strong end system model)
mov eax, [edx + IPv4_header.DestinationAddress] mov eax, [edx + IPv4_header.DestinationAddress]
cmp eax, [IP_LIST + edi] cmp eax, [IP_LIST + edi]
je .ip_ok je .ip_ok
; check for broadcast (IP or (not SUBNET)) ; network layer broadcast
cmp eax, [BROADCAST_LIST + edi] cmp eax, [BROADCAST_LIST + edi]
je .ip_ok je .ip_ok
; or a special broadcast (255.255.255.255) ; physical layer broadcast (255.255.255.255)
cmp eax, 0xffffffff cmp eax, 0xffffffff
je .ip_ok je .ip_ok
; maybe it's a multicast (224.0.0.0/4) ; multicast (224.0.0.0/4 = 224.0.0.0 to 239.255.255.255)
and eax, 0x0fffffff and eax, 0x0fffffff
cmp eax, 224 cmp eax, 224
je .ip_ok je .ip_ok
; maybe we just dont have an IP yet and should accept everything on the IP level ; maybe we just dont have an IP yet and should accept everything on the IP level
cmp [IP_LIST + edi], 0 cmp [IP_LIST + edi], 0
je .ip_ok je .ip_ok
; or it's just not meant for us.. :( ; or it's just not meant for us.. :(
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Destination address does not match!\n" DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Destination address does not match!\n"
jmp .dump jmp .dump
@ -305,7 +300,6 @@ IPv4_input: ; TODO: add IPv4
xchg cl, ch ; xchg cl, ch ;
sub ecx, esi ; sub ecx, esi ;
lea edi, [edx + IPv4_header.SourceAddress] ; make edi ptr to source and dest IPv4 address
mov al, [edx + IPv4_header.Protocol] mov al, [edx + IPv4_header.Protocol]
add esi, edx ; make esi ptr to data add esi, edx ; make esi ptr to data
@ -318,11 +312,60 @@ IPv4_input: ; TODO: add IPv4
cmp al, IP_PROTO_ICMP cmp al, IP_PROTO_ICMP
je ICMP_input je ICMP_input
;-------------------------------
; Look for a matching RAW socket
pusha
mov ecx, socket_mutex
call mutex_lock
popa
add ecx, esi
sub ecx, edx
mov esi, edx
movzx edx, al
mov eax, net_sockets
.next_socket:
mov eax, [eax + SOCKET.NextPtr]
or eax, eax
jz .dump_unlock
cmp [eax + SOCKET.Domain], AF_INET4
jne .next_socket
cmp [eax + SOCKET.Protocol], edx
jne .next_socket
pusha
mov ecx, socket_mutex
call mutex_unlock
popa
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: found matching RAW socket: 0x%x\n", eax
pusha
lea ecx, [eax + SOCKET.mutex]
call mutex_lock
popa
jmp SOCKET_input
.dump_unlock:
pusha
mov ecx, socket_mutex
call mutex_unlock
popa
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: unknown protocol %u\n", al DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: unknown protocol %u\n", al
.dump: .dump:
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: dumping\n" DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: dumping\n"
inc [IPv4_packets_dumped] ; FIXME: use correct interface inc [IPv4_packets_dumped + edi]
call NET_BUFF_free
ret
.invalid_device:
DEBUGF DEBUG_NETWORK_ERROR, "IPv4_input: packet originated from invalid device\n"
call NET_BUFF_free call NET_BUFF_free
ret ret
@ -568,11 +611,12 @@ IPv4_find_fragment_slot:
; ;
; IPv4_output ; IPv4_output
; ;
; IN: eax = Destination IP ; IN: al = protocol
; ah = TTL
; ebx = device ptr (or 0 to let IP layer decide) ; ebx = device ptr (or 0 to let IP layer decide)
; ecx = data length ; ecx = data length
; edx = Source IP ; edx = Source IP
; di = TTL shl 8 + protocol ; edi = Destination IP
; ;
; OUT: eax = pointer to buffer start / 0 on error ; OUT: eax = pointer to buffer start / 0 on error
; ebx = device ptr (send packet through this device) ; ebx = device ptr (send packet through this device)
@ -589,7 +633,8 @@ IPv4_output:
cmp ecx, 65500 ; Max IPv4 packet size cmp ecx, 65500 ; Max IPv4 packet size
ja .too_large ja .too_large
push ecx di eax push ecx ax edi
mov eax, edi
call IPv4_route ; outputs device number in edi, dest ip in eax, source IP in edx call IPv4_route ; outputs device number in edi, dest ip in eax, source IP in edx
push edx push edx
test edi, edi test edi, edi
@ -601,7 +646,7 @@ IPv4_output:
push ebx ; push the mac onto the stack push ebx ; push the mac onto the stack
push ax push ax
inc [IPv4_packets_tx + edi] ; update stats inc [IPv4_packets_tx + edi] ; update stats
mov ax, ETHER_PROTO_IPv4 mov ax, ETHER_PROTO_IPv4
mov ebx, [NET_DRV_LIST + edi] mov ebx, [NET_DRV_LIST + edi]
@ -642,7 +687,10 @@ IPv4_output:
.arp_error: .arp_error:
DEBUGF DEBUG_NETWORK_ERROR, "IPv4_output: ARP error=%x\n", eax DEBUGF DEBUG_NETWORK_ERROR, "IPv4_output: ARP error=%x\n", eax
add esp, 3*4+2 add esp, 4
pop eax
DEBUGF DEBUG_NETWORK_ERROR, "IPv4_output: ip=0x%x\n", eax
add esp, 4+2
xor eax, eax xor eax, eax
ret ret
@ -678,9 +726,6 @@ IPv4_output_raw:
DEBUGF 1,"IPv4_output_raw: size=%u ptr=%x socket=%x\n", ecx, esi, eax DEBUGF 1,"IPv4_output_raw: size=%u ptr=%x socket=%x\n", ecx, esi, eax
cmp ecx, 1480 ;;;;; FIXME
ja .too_large
sub esp, 8 sub esp, 8
push esi eax push esi eax
@ -707,7 +752,7 @@ IPv4_output_raw:
mov dword[esp+4+4+4], eax mov dword[esp+4+4+4], eax
pop eax esi pop eax esi
;; todo: check socket options if we should add header, or just compute checksum ;; TODO: check socket options if we should add header, or just compute checksum
push edi ecx push edi ecx
rep movsb rep movsb
@ -734,11 +779,14 @@ IPv4_output_raw:
ret ret
.error: .error:
add esp, 6 add esp, 6+8+4+4
mov ebx, ENOBUFS ; FIXME: NOBUFS or MSGSIZE error
or eax, -1
ret
.arp_error: .arp_error:
add esp, 8+4+4 add esp, 8+4+4
.too_large: mov ebx, ENOTCONN
DEBUGF DEBUG_NETWORK_ERROR, "IPv4_output_raw: Failed\n"
or eax, -1 or eax, -1
ret ret
@ -746,117 +794,120 @@ IPv4_output_raw:
;-------------------------------------------------------- ;--------------------------------------------------------
; ;
; ;
; IN: dword [esp] = pointer to buffer containing ipv4 packet to be fragmented ; IN: [esp] = pointer to buffer containing ipv4 packet to be fragmented
; esi = pointer to ip header in that buffer ; edi = pointer to ip header in that buffer
; ecx = max size of fragments ; ebx = device ptr
; ;
; OUT: / ; OUT: /
; ;
;-------------------------------------------------------- ;--------------------------------------------------------
proc IPv4_fragment stdcall buffer
align 4 locals
IPv4_fragment: offset dd ?
headerlength dd ?
headerptr dd ?
dataptr dd ?
remaining dd ?
segmentsize dd ?
endl
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_fragment\n" DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_fragment\n"
and ecx, not 111b ; align 4 ; We must be able to put at least 8 bytes per segment
movzx eax, byte[edi] ; IHL
cmp ecx, sizeof.IPv4_header + 8 ; must be able to put at least 8 bytes and eax, 0xf
jb .err2 shl eax, 2
mov [headerlength], eax
push esi ecx add eax, 8
mov eax, [esi + IPv4_header.DestinationAddress] mov ecx, [ebx + NET_DEVICE.mtu]
call ARP_IP_to_MAC and ecx, not 11b
pop ecx esi cmp ecx, eax
cmp eax, -1 jb .fail
jz .err2
push ebx
push ax
mov ebx, [NET_DRV_LIST]
lea eax, [ebx + ETH_DEVICE.mac]
push eax
push esi ; ptr to ip header
sub ecx, sizeof.IPv4_header ; substract header size
push ecx ; max data size
push dword 0 ; offset
.new_fragment:
DEBUGF DEBUG_NETWORK_VERBOSE, "Ipv4_fragment: new fragment"
mov ax, ETHER_PROTO_IPv4
lea ebx, [esp + 4*4]
call ETH_output
jz .err
; copy header
mov esi, [esp + 2*4]
mov ecx, 5 ; 5 dwords: TODO: use IHL field of the header!
rep movsd
; copy data
mov esi, [esp + 2*4]
add esi, sizeof.IPv4_header
add esi, [esp] ; offset
mov ecx, [esp + 1*4]
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_fragment: copying %u bytes\n", ecx
rep movsb
; now, correct header
mov ecx, [esp + 1*4]
add ecx, sizeof.IPv4_header
xchg cl, ch
mov [edi + IPv4_header.TotalLength], cx
mov ecx, [esp] ; offset
xchg cl, ch
; cmp dword[esp + 4*4], 0 ; last fragment?;<<<<<<
; je .last_fragment
or cx, 1 shl 2 ; more fragments
; .last_fragment:
mov [edi + IPv4_header.FlagsAndFragmentOffset], cx
mov [edi + IPv4_header.HeaderChecksum], 0 mov [edi + IPv4_header.HeaderChecksum], 0
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<< send the packet mov [segmentsize], ecx
mov ecx, [esp + 1*4] mov [headerptr], edi
movzx ecx, [edi + IPv4_header.TotalLength]
xchg cl, ch
sub ecx, [headerlength]
mov [remaining], ecx
mov [offset], 0
push edx eax add edi, [headerlength]
mov [dataptr], edi
.loop:
DEBUGF DEBUG_NETWORK_VERBOSE, "Ipv4_fragment: new fragment"
mov ecx, [segmentsize]
cmp ecx, [remaining]
jbe @f
mov ecx, [remaining]
@@:
mov ax, ETHER_PROTO_IPv4
mov edx, [esp]
add edx, [edx + NET_BUFF.offset]
; add edx, ETH_header.DstMAC ; = 0
call ETH_output
jz .fail
push edi
mov edx, ecx
; copy header
mov esi, [headerptr]
mov ecx, [headerlength]
shr ecx, 2
rep movsd
; copy data
mov esi, [dataptr]
add esi, [offset]
mov ecx, edx
sub ecx, [headerlength]
shr ecx, 2
rep movsd
pop edi
; now, correct header
; packet length
mov ax, dx
xchg al, ah
mov [edi + IPv4_header.TotalLength], ax
; offset
mov eax, [offset]
xchg al, ah
sub edx, [headerlength]
sub [remaining], edx
je @f
jb .fail
or ah, 1 shl 2 ; more fragments
add [offset], edx
@@:
mov [edi + IPv4_header.FlagsAndFragmentOffset], ax
; Send the fragment
IPv4_checksum edi IPv4_checksum edi
call [ebx + NET_DEVICE.transmit] call [ebx + NET_DEVICE.transmit]
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
mov ecx, [esp+4] cmp [remaining], 0
add [esp], ecx jne .loop
mov ecx, [esp+3*4+6+4] ; ptr to begin of buff
add ecx, [esp+3*4+6+4+4] ; buff size
sub ecx, [esp+2*4] ; ptr to ip header
add ecx, [esp] ; offset
DEBUGF DEBUG_NETWORK_VERBOSE, "Ipv4_fragment: %u bytes remaining\n", ecx
cmp ecx, [esp+1*4]
jae .new_fragment
mov [esp+4], ecx ; set fragment size to remaining packet size
jmp .new_fragment
.err:
DEBUGF DEBUG_NETWORK_ERROR, "Ipv4_fragment: failed\n"
.done:
add esp, 12 + 4 + 6
.err2:
DEBUGF DEBUG_NETWORK_VERBOSE, "Ipv4_fragment: dumping\n"
call NET_BUFF_free call NET_BUFF_free
ret ret
.fail:
DEBUGF DEBUG_NETWORK_ERROR, "Ipv4_fragment: failed\n"
call NET_BUFF_free
ret
endp
;--------------------------------------------------------------------------- ;---------------------------------------------------------------------------
@ -973,11 +1024,6 @@ IPv4_connect:
pushd [edx + 4] pushd [edx + 4]
pop [eax + IP_SOCKET.RemoteIP] pop [eax + IP_SOCKET.RemoteIP]
; Set up data receiving queue
push eax
init_queue (eax + SOCKET_QUEUE_LOCATION)
pop eax
lea ecx, [eax + SOCKET.mutex] lea ecx, [eax + SOCKET.mutex]
call mutex_unlock call mutex_unlock

View File

@ -133,8 +133,9 @@ macro ICMP_init {
; IN: Pointer to buffer in [esp] ; IN: Pointer to buffer in [esp]
; ebx = pointer to device struct ; ebx = pointer to device struct
; ecx = ICMP Packet size ; ecx = ICMP Packet size
; edx = ptr to IPv4 header
; esi = ptr to ICMP Packet data ; esi = ptr to ICMP Packet data
; edi = ptr to ipv4 source and dest address ; edi = interface number*4
; ;
; OUT: / ; OUT: /
; ;
@ -144,8 +145,13 @@ ICMP_input:
DEBUGF DEBUG_NETWORK_VERBOSE, "ICMP_input\n" DEBUGF DEBUG_NETWORK_VERBOSE, "ICMP_input\n"
; Dump all multicasts and broadcasts
mov eax, [IP_LIST + edi]
cmp eax, [edx + IPv4_header.DestinationAddress]
jne .dump
; Check the checksum ; Check the checksum
push esi ecx push esi ecx edx
push [esi + ICMP_header.Checksum] push [esi + ICMP_header.Checksum]
mov [esi + ICMP_header.Checksum], 0 mov [esi + ICMP_header.Checksum], 0
xor edx, edx xor edx, edx
@ -153,17 +159,11 @@ ICMP_input:
call checksum_2 call checksum_2
pop si pop si
cmp dx, si cmp dx, si
pop ecx esi pop edx ecx esi
jne .checksum_mismatch jne .checksum_mismatch
DEBUGF DEBUG_NETWORK_VERBOSE, "ICMP_input: Checksum OK\n" DEBUGF DEBUG_NETWORK_VERBOSE, "ICMP_input: Checksum OK\n"
; Ualidate device ptr
mov eax, edi
call NET_ptr_to_num4
cmp edi, -1
je .dump
; Update stats ; Update stats
inc [ICMP_PACKETS_RX + edi] inc [ICMP_PACKETS_RX + edi]
@ -177,10 +177,10 @@ ICMP_input:
call mutex_lock call mutex_lock
popa popa
mov edx, [eax] ; ipv4 source address add ecx, esi
sub ecx, edx
mov esi, edx
mov eax, net_sockets mov eax, net_sockets
.try_more:
; mov , [esi + ICMP_header.Identifier]
.next_socket: .next_socket:
mov eax, [eax + SOCKET.NextPtr] mov eax, [eax + SOCKET.NextPtr]
or eax, eax or eax, eax
@ -192,12 +192,6 @@ ICMP_input:
cmp [eax + SOCKET.Protocol], IP_PROTO_ICMP cmp [eax + SOCKET.Protocol], IP_PROTO_ICMP
jne .next_socket jne .next_socket
cmp [eax + IP_SOCKET.RemoteIP], edx
jne .next_socket
; cmp [eax + ICMP_SOCKET.Identifier],
; jne .next_socket
pusha pusha
mov ecx, socket_mutex mov ecx, socket_mutex
call mutex_unlock call mutex_unlock
@ -376,7 +370,7 @@ end if
; ;
; IN: eax = socket ptr ; IN: eax = socket ptr
; ecx = data length ; ecx = data length
; esi = data offset ; edx = data pointer
; ;
;----------------------------------------------------------------- ;-----------------------------------------------------------------
align 4 align 4
@ -385,13 +379,13 @@ ICMP_output_raw:
DEBUGF DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet for socket %x, data ptr=%x\n", eax, edx DEBUGF DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet for socket %x, data ptr=%x\n", eax, edx
push edx push edx
mov di, IP_PROTO_ICMP SHL 8 + 128 ; TTL
mov edx, [eax + IP_SOCKET.LocalIP]
mov ebx, [eax + IP_SOCKET.device] mov ebx, [eax + IP_SOCKET.device]
mov eax, [eax + IP_SOCKET.RemoteIP] mov edx, [eax + IP_SOCKET.LocalIP]
mov edi, [eax + IP_SOCKET.RemoteIP]
mov al, [eax + IP_SOCKET.ttl]
mov ah, IP_PROTO_ICMP
call IPv4_output call IPv4_output
jz .exit jz .fail
pop esi pop esi
push eax push eax
@ -415,10 +409,14 @@ ICMP_output_raw:
jnz @f jnz @f
call NET_ptr_to_num4 call NET_ptr_to_num4
inc [ICMP_PACKETS_TX + edi] inc [ICMP_PACKETS_TX + edi]
@@: @@:
ret ret
.exit:
.fail:
pop edx
DEBUGF DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n" DEBUGF DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n"
or eax, -1
mov ebx, EMSGSIZE ;;; FIXME
ret ret

View File

@ -27,9 +27,9 @@ struct SOCKET
PID dd ? ; process ID PID dd ? ; process ID
TID dd ? ; thread ID TID dd ? ; thread ID
Domain dd ? ; INET/LOCAL/.. Domain dd ? ; INET4/INET6/LOCAL/..
Type dd ? ; RAW/STREAM/DGRAM Type dd ? ; RAW/STREAM/DGRAM
Protocol dd ? ; ICMP/IPv4/ARP/TCP/UDP Protocol dd ? ; UDP/TCP/ARP/ICMP
errorcode dd ? errorcode dd ?
device dd ? ; driver pointer, socket pointer if it's an LOCAL socket device dd ? ; driver pointer, socket pointer if it's an LOCAL socket
@ -47,6 +47,8 @@ struct IP_SOCKET SOCKET
LocalIP rd 4 ; network byte order LocalIP rd 4 ; network byte order
RemoteIP rd 4 ; network byte order RemoteIP rd 4 ; network byte order
ttl db ?
rb 3 ; align
ends ends
@ -150,14 +152,6 @@ struct UDP_SOCKET IP_SOCKET
ends ends
struct ICMP_SOCKET IP_SOCKET
Identifier dw ?
ends
struct RING_BUFFER struct RING_BUFFER
mutex MUTEX mutex MUTEX
@ -313,6 +307,8 @@ SOCKET_open:
cmp ecx, AF_INET4 cmp ecx, AF_INET4
jne .no_inet4 jne .no_inet4
mov [eax + IP_SOCKET.ttl], 128
cmp edx, SOCK_DGRAM cmp edx, SOCK_DGRAM
je .udp je .udp
@ -354,6 +350,10 @@ SOCKET_open:
align 4 align 4
.udp: .udp:
push eax
init_queue (eax + SOCKET_QUEUE_LOCATION) ; Set up data receiving queue
pop eax
mov [eax + SOCKET.Protocol], IP_PROTO_UDP mov [eax + SOCKET.Protocol], IP_PROTO_UDP
mov [eax + SOCKET.snd_proc], SOCKET_send_udp mov [eax + SOCKET.snd_proc], SOCKET_send_udp
mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
@ -373,6 +373,10 @@ align 4
align 4 align 4
.raw_ip: .raw_ip:
push eax
init_queue (eax + SOCKET_QUEUE_LOCATION) ; Set up data receiving queue
pop eax
mov [eax + SOCKET.snd_proc], SOCKET_send_ip mov [eax + SOCKET.snd_proc], SOCKET_send_ip
mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
mov [eax + SOCKET.connect_proc], IPv4_connect mov [eax + SOCKET.connect_proc], IPv4_connect
@ -381,6 +385,10 @@ align 4
align 4 align 4
.raw_icmp: .raw_icmp:
push eax
init_queue (eax + SOCKET_QUEUE_LOCATION) ; Set up data receiving queue
pop eax
mov [eax + SOCKET.snd_proc], SOCKET_send_icmp mov [eax + SOCKET.snd_proc], SOCKET_send_icmp
mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
mov [eax + SOCKET.connect_proc], IPv4_connect mov [eax + SOCKET.connect_proc], IPv4_connect
@ -975,14 +983,14 @@ SOCKET_send_ip:
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: IPv4\n" DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: IPv4\n"
mov [esp+32], ecx mov [esp+32], ecx
call IPv4_output_raw ; FIXME: IPv4_output_raw should return error codes! call IPv4_output_raw
cmp eax, -1 cmp eax, -1
je .error je .error
ret ret
.error: .error:
mov dword[esp+32], -1 mov dword[esp+32], eax
mov dword[esp+20], EMSGSIZE mov dword[esp+20], ebx
ret ret
@ -992,14 +1000,14 @@ SOCKET_send_icmp:
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: ICMP\n" DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: ICMP\n"
mov [esp+32], ecx mov [esp+32], ecx
call ICMP_output_raw ; FIXME: errorcodes call ICMP_output_raw
cmp eax, -1 cmp eax, -1
je .error je .error
ret ret
.error: .error:
mov dword[esp+32], -1 mov dword[esp+32], eax
mov dword[esp+20], EMSGSIZE mov dword[esp+20], ebx
ret ret
@ -1126,17 +1134,23 @@ SOCKET_get_opt:
ret ret
;----------------------------------------------------------------- ;-----------------------------------------------------------------
; ;
; SOCKET_set_options ; SOCKET_set_options
; ;
; IN: ecx = socket number ; IN: ecx = socket number
; edx = pointer to the options: ; edx = pointer to socket_options
; dd level, optname, optlen, optval
; OUT: -1 on error ; OUT: -1 on error
; ;
;----------------------------------------------------------------- ;-----------------------------------------------------------------
struct socket_options
level dd ?
optname dd ?
optlen dd ?
optval dd ?
ends
align 4 align 4
SOCKET_set_opt: SOCKET_set_opt:
@ -1145,22 +1159,20 @@ SOCKET_set_opt:
call SOCKET_num_to_ptr call SOCKET_num_to_ptr
jz .invalid jz .invalid
cmp dword [edx], SOL_SOCKET cmp [edx + socket_options.level], IP_PROTO_IP
je .ip
cmp [edx + socket_options.level], SOL_SOCKET
jne .invalid jne .invalid
cmp dword [edx+4], SO_BINDTODEVICE .socket:
je .bind cmp [edx + socket_options.optname], SO_BINDTODEVICE
jne .invalid
.invalid:
mov dword[esp+32], -1
mov dword[esp+20], EINVAL
ret
.bind: .bind:
cmp dword[edx+8], 0 cmp [edx + socket_options.optlen], 0
je .unbind je .unbind
movzx edx, byte[edx + 12] movzx edx, byte[edx + socket_options.optval]
cmp edx, NET_DEVICES_MAX cmp edx, NET_DEVICES_MAX
ja .invalid ja .invalid
@ -1180,11 +1192,27 @@ SOCKET_set_opt:
mov dword[esp+32], 0 ; success! mov dword[esp+32], 0 ; success!
ret ret
.ip:
cmp [edx + socket_options.optname], IP_TTL
jne .invalid
.ttl:
mov bl, byte[edx + socket_options.optval]
mov [eax + IP_SOCKET.ttl], bl
mov dword[esp+32], 0 ; success!
ret
.already: .already:
mov dword[esp+20], EALREADY mov dword[esp+20], EALREADY
mov dword[esp+32], -1 mov dword[esp+32], -1
ret ret
.invalid:
mov dword[esp+20], EINVAL
mov dword[esp+32], -1
ret
@ -1474,6 +1502,7 @@ SOCKET_input:
call mutex_unlock call mutex_unlock
popa popa
add esp, 8
call NET_BUFF_free call NET_BUFF_free
ret ret

View File

@ -53,6 +53,12 @@ IP_PROTO_IP = 0
IP_PROTO_ICMP = 1 IP_PROTO_ICMP = 1
IP_PROTO_TCP = 6 IP_PROTO_TCP = 6
IP_PROTO_UDP = 17 IP_PROTO_UDP = 17
IP_PROTO_RAW = 255
; IP options
IP_TOS = 1
IP_TTL = 2
IP_HDRINCL = 3
; PPP protocol numbers ; PPP protocol numbers
PPP_PROTO_IPv4 = 0x2100 PPP_PROTO_IPv4 = 0x2100
@ -71,6 +77,9 @@ SOCK_STREAM = 1
SOCK_DGRAM = 2 SOCK_DGRAM = 2
SOCK_RAW = 3 SOCK_RAW = 3
; Socket level
SOL_SOCKET = 0xffff
; Socket options ; Socket options
SO_ACCEPTCON = 1 shl 0 SO_ACCEPTCON = 1 shl 0
SO_BROADCAST = 1 shl 1 SO_BROADCAST = 1 shl 1
@ -89,10 +98,6 @@ SO_NONBLOCK = 1 shl 31
MSG_PEEK = 0x02 MSG_PEEK = 0x02
MSG_DONTWAIT = 0x40 MSG_DONTWAIT = 0x40
; Socket level
SOL_SOCKET = 0
; Socket States ; Socket States
SS_NOFDREF = 0x0001 ; no file table ref any more SS_NOFDREF = 0x0001 ; no file table ref any more
SS_ISCONNECTED = 0x0002 ; socket connected to a peer SS_ISCONNECTED = 0x0002 ; socket connected to a peer

View File

@ -24,9 +24,10 @@ $Revision$
; ;
; IN: [esp] = ptr to buffer ; IN: [esp] = ptr to buffer
; ebx = ptr to device struct ; ebx = ptr to device struct
; ecx = segment size ; ecx = TCP segment size
; edx = ptr to IPv4 header
; esi = ptr to TCP segment ; esi = ptr to TCP segment
; edi = ptr to ipv4 source address, followed by ipv4 dest address ; edi = interface number*4
; ;
; OUT: / ; OUT: /
; ;
@ -37,13 +38,14 @@ TCP_input:
; record the current time ; record the current time
push [timer_ticks] ; in 1/100 seconds push [timer_ticks] ; in 1/100 seconds
push ebx ecx esi edi ; mind the order (see TCP_queue_entry struct) push ebx ecx esi edx ; mind the order (see TCP_queue_entry struct)
mov esi, esp mov esi, esp
push edi
add_to_queue TCP_queue, TCP_QUEUE_SIZE, sizeof.TCP_queue_entry, .fail add_to_queue TCP_queue, TCP_QUEUE_SIZE, sizeof.TCP_queue_entry, .fail
pop edi
add esp, sizeof.TCP_queue_entry add esp, sizeof.TCP_queue_entry
call NET_ptr_to_num4
inc [TCP_segments_rx + edi] inc [TCP_segments_rx + edi]
xor edx, edx xor edx, edx
@ -55,6 +57,7 @@ TCP_input:
ret ret
.fail: .fail:
pop edi
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP incoming queue is full, discarding packet!\n" DEBUGF DEBUG_NETWORK_VERBOSE, "TCP incoming queue is full, discarding packet!\n"
call NET_ptr_to_num4 call NET_ptr_to_num4
@ -94,7 +97,7 @@ endl
mov ebx, [esi + TCP_queue_entry.device_ptr] mov ebx, [esi + TCP_queue_entry.device_ptr]
mov ecx, [esi + TCP_queue_entry.segment_size] mov ecx, [esi + TCP_queue_entry.segment_size]
mov edi, [esi + TCP_queue_entry.ip_ptr] ; ptr to ipv4 source address, followed by ipv4 destination address mov edi, [esi + TCP_queue_entry.ip_ptr] ; ptr to ipv4 header
mov esi, [esi + TCP_queue_entry.segment_ptr] ; change esi last mov esi, [esi + TCP_queue_entry.segment_ptr] ; change esi last
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: size=%u time=%d\n", ecx, [timer_ticks] DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: size=%u time=%d\n", ecx, [timer_ticks]
@ -111,8 +114,8 @@ endl
push ecx esi push ecx esi
pushw [esi + TCP_header.Checksum] pushw [esi + TCP_header.Checksum]
mov [esi + TCP_header.Checksum], 0 mov [esi + TCP_header.Checksum], 0
TCP_checksum (edi), (edi+4) TCP_checksum (edi+IPv4_header.SourceAddress), (edi+IPv4_header.DestinationAddress)
pop cx ; previous checksum pop cx ; previous checksum
cmp cx, dx cmp cx, dx
pop edx ecx pop edx ecx
jne .drop_no_socket jne .drop_no_socket
@ -170,7 +173,7 @@ endl
jne .socket_loop jne .socket_loop
mov eax, [ebx + IP_SOCKET.RemoteIP] mov eax, [ebx + IP_SOCKET.RemoteIP]
cmp eax, [edi] ; Ipv4 source address cmp eax, [edi + IPv4_header.SourceAddress]
je @f je @f
test eax, eax test eax, eax
jnz .socket_loop jnz .socket_loop
@ -233,7 +236,7 @@ endl
call mutex_unlock call mutex_unlock
popa popa
push ecx edx esi edi ;;; push ecx edx esi edi
call SOCKET_fork call SOCKET_fork
pop edi esi edx ecx pop edi esi edx ecx
@ -244,7 +247,7 @@ endl
mov [temp_bits], TCP_BIT_DROPSOCKET mov [temp_bits], TCP_BIT_DROPSOCKET
push dword [edi + 4] ; Ipv4 destination addres push [edi + IPv4_header.DestinationAddress]
pop [ebx + IP_SOCKET.LocalIP] pop [ebx + IP_SOCKET.LocalIP]
push [edx + TCP_header.DestinationPort] push [edx + TCP_header.DestinationPort]
@ -1211,7 +1214,7 @@ align 4
;;; TODO: check if it's a broadcast or multicast, and drop if so ;;; TODO: check if it's a broadcast or multicast, and drop if so
push dword [edi] ; Ipv4 source addres push [edi + IPv4_header.SourceAddress]
pop [ebx + IP_SOCKET.RemoteIP] pop [ebx + IP_SOCKET.RemoteIP]
push [edx + TCP_header.SourcePort] push [edx + TCP_header.SourcePort]
@ -1673,11 +1676,13 @@ align 4
.respond_seg_ack: .respond_seg_ack:
mov cl, TH_RST mov cl, TH_RST
xor ebx, ebx ; FIXME: find a way to get the receiving device ptr
call TCP_respond_segment call TCP_respond_segment
jmp .drop_no_socket jmp .drop_no_socket
.respond_seg_syn: .respond_seg_syn:
mov cl, TH_RST + TH_ACK mov cl, TH_RST + TH_ACK
xor ebx, ebx ; FIXME: find a way to get the receiving device ptr
call TCP_respond_segment call TCP_respond_segment
jmp .drop_no_socket jmp .drop_no_socket

View File

@ -503,10 +503,11 @@ endl
; Create the IP packet ; Create the IP packet
mov ecx, esi mov ecx, esi
mov edx, [eax + IP_SOCKET.LocalIP] ; source ip
mov ebx, [eax + IP_SOCKET.device] mov ebx, [eax + IP_SOCKET.device]
mov eax, [eax + IP_SOCKET.RemoteIP] ; dest ip mov edx, [eax + IP_SOCKET.LocalIP] ; source ip
mov di, IP_PROTO_TCP shl 8 + 128 mov edi, [eax + IP_SOCKET.RemoteIP] ; dest ip
mov al, [eax + IP_SOCKET.ttl]
mov ah, IP_PROTO_TCP
call IPv4_output call IPv4_output
jz .ip_error jz .ip_error

View File

@ -266,7 +266,7 @@ TCP_outflags:
;--------------------------------------- ;-----------------------------------------------------------------
; ;
; The fast way to send an ACK/RST/keepalive segment ; The fast way to send an ACK/RST/keepalive segment
; ;
@ -275,7 +275,10 @@ TCP_outflags:
; IN: ebx = socket ptr ; IN: ebx = socket ptr
; cl = flags ; cl = flags
; ;
;-------------------------------------- ; OUT: /
;
;-----------------------------------------------------------------
align 4 align 4
TCP_respond: TCP_respond:
@ -285,11 +288,12 @@ TCP_respond:
; Create the IP packet ; Create the IP packet
push cx ebx push cx ebx
mov eax, [ebx + IP_SOCKET.RemoteIP]
mov edx, [ebx + IP_SOCKET.LocalIP] mov edx, [ebx + IP_SOCKET.LocalIP]
mov ebx, [ebx + IP_SOCKET.device] mov edi, [ebx + IP_SOCKET.RemoteIP]
mov al, [ebx + IP_SOCKET.ttl]
mov ah, IP_PROTO_TCP
mov ecx, sizeof.TCP_header mov ecx, sizeof.TCP_header
mov di, IP_PROTO_TCP shl 8 + 128 mov ebx, [ebx + IP_SOCKET.device]
call IPv4_output call IPv4_output
jz .error jz .error
pop esi cx pop esi cx
@ -347,33 +351,32 @@ TCP_respond:
ret ret
;-----------------------------------------------------------------
;
;-------------------------
; TCP_respond_segment: ; TCP_respond_segment:
; ;
; IN: edx = segment ptr (a previously received segment) ; IN: ebx = device ptr
; edi = ptr to dest and src IPv4 addresses ; edx = segment ptr (a previously received segment)
; edi = ptr to IPv4 header
; cl = flags ; cl = flags
;
; OUT: /
;
;-----------------------------------------------------------------
align 4 align 4
TCP_respond_segment: TCP_respond_segment:
DEBUGF DEBUG_NETWORK_VERBOSE,"TCP_respond_segment: frame=%x flags=%x\n", edx, cl DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_respond_segment: frame=%x flags=%x\n", edx, cl
;--------------------- ;---------------------
; Create the IP packet ; Create the IP packet
push cx edx push cx edx
mov edx, [edi + 4] mov edx, [edi + IPv4_header.DestinationAddress]
mov eax, [edi] mov edi, [edi + IPv4_header.SourceAddress]
mov ecx, sizeof.TCP_header mov ecx, sizeof.TCP_header
mov di, IP_PROTO_TCP shl 8 + 128 mov ax, IP_PROTO_TCP shl 8 + 128
xor ebx, ebx ;;; fixme
call IPv4_output call IPv4_output
jz .error jz .error
pop esi cx pop esi cx

View File

@ -57,15 +57,15 @@ macro UDP_checksum IP1, IP2 { ; esi = ptr to udp packet, ecx = packet size
; Pseudoheader ; Pseudoheader
mov edx, IP_PROTO_UDP mov edx, IP_PROTO_UDP
add dl, [IP1+1] add dl, byte[IP1+1]
adc dh, [IP1+0] adc dh, byte[IP1+0]
adc dl, [IP1+3] adc dl, byte[IP1+3]
adc dh, [IP1+2] adc dh, byte[IP1+2]
adc dl, [IP2+1] adc dl, byte[IP2+1]
adc dh, [IP2+0] adc dh, byte[IP2+0]
adc dl, [IP2+3] adc dl, byte[IP2+3]
adc dh, [IP2+2] adc dh, byte[IP2+2]
adc dl, cl ; byte[esi+UDP_header.Length+1] adc dl, cl ; byte[esi+UDP_header.Length+1]
adc dh, ch ; byte[esi+UDP_header.Length+0] adc dh, ch ; byte[esi+UDP_header.Length+0]
@ -103,14 +103,14 @@ macro UDP_checksum IP1, IP2 { ; esi = ptr to udp packet, ecx = packet size
; UDP_input: ; UDP_input:
; ;
; Called by IPv4_input, ; Called by IPv4_input,
; this procedure will inject the udp data diagrams in the application sockets. ; this procedure will inject the UDP data in the application sockets.
; ;
; IN: [esp] = Pointer to buffer ; IN: [esp] = ptr to buffer
; [esp+4] = size of buffer
; ebx = ptr to device struct ; ebx = ptr to device struct
; ecx = UDP Packet size ; ecx = UDP packet size
; esi = ptr to UDP header ; edx = ptr to IPv4 header
; edi = ptr to ipv4 source and dest address ; esi = ptr to UDP packet data
; edi = interface number*4
; ;
; OUT: / ; OUT: /
; ;
@ -127,7 +127,8 @@ UDP_input:
; otherwise, we will re-calculate the checksum and add it to this value, thus creating 0 when it is correct ; otherwise, we will re-calculate the checksum and add it to this value, thus creating 0 when it is correct
UDP_checksum (edi), (edi+4) mov eax, edx
UDP_checksum (eax+IPv4_header.SourceAddress), (eax+IPv4_header.DestinationAddress)
jnz .checksum_mismatch jnz .checksum_mismatch
.no_checksum: .no_checksum:
@ -148,9 +149,7 @@ UDP_input:
mov cx, [esi + UDP_header.SourcePort] mov cx, [esi + UDP_header.SourcePort]
mov dx, [esi + UDP_header.DestinationPort] mov dx, [esi + UDP_header.DestinationPort]
mov edi, [edi + 4] ; ipv4 source address
mov eax, net_sockets mov eax, net_sockets
.next_socket: .next_socket:
mov eax, [eax + SOCKET.NextPtr] mov eax, [eax + SOCKET.NextPtr]
or eax, eax or eax, eax
@ -172,15 +171,15 @@ UDP_input:
call mutex_unlock call mutex_unlock
popa popa
;;; TODO: when packet is processed, check more sockets! ;;; TODO: when packet is processed, check more sockets?!
; FIXME: check remote IP if possible
;
; cmp [eax + IP_SOCKET.RemoteIP], 0xffffffff ; cmp [eax + IP_SOCKET.RemoteIP], 0xffffffff
; je @f ; je @f
; cmp [eax + IP_SOCKET.RemoteIP], edi ; cmp [eax + IP_SOCKET.RemoteIP],
; jne .next_socket ; jne .next_socket
; @@: ; @@:
;
; FIXME: UDP should check remote IP, but not under all circumstances!
cmp [eax + UDP_SOCKET.RemotePort], 0 cmp [eax + UDP_SOCKET.RemotePort], 0
je .updateport je .updateport
@ -194,7 +193,6 @@ UDP_input:
popa popa
.updatesock: .updatesock:
call NET_ptr_to_num4
inc [UDP_PACKETS_RX + edi] inc [UDP_PACKETS_RX + edi]
movzx ecx, [esi + UDP_header.Length] movzx ecx, [esi + UDP_header.Length]
@ -257,10 +255,11 @@ UDP_output:
sub esp, 4 ; Data ptr will be placed here sub esp, 4 ; Data ptr will be placed here
push edx esi push edx esi
mov edx, [eax + IP_SOCKET.LocalIP]
mov ebx, [eax + IP_SOCKET.device] mov ebx, [eax + IP_SOCKET.device]
mov eax, [eax + IP_SOCKET.RemoteIP] mov edx, [eax + IP_SOCKET.LocalIP]
mov di, IP_PROTO_UDP shl 8 + 128 mov edi, [eax + IP_SOCKET.RemoteIP]
mov al, [eax + IP_SOCKET.ttl]
mov ah, IP_PROTO_UDP
add ecx, sizeof.UDP_header add ecx, sizeof.UDP_header
call IPv4_output call IPv4_output
jz .fail jz .fail
@ -347,10 +346,6 @@ UDP_connect:
call SOCKET_find_port call SOCKET_find_port
@@: @@:
push eax
init_queue (eax + SOCKET_QUEUE_LOCATION) ; Set up data receiving queue
pop eax
push eax push eax
lea ecx, [eax + SOCKET.mutex] lea ecx, [eax + SOCKET.mutex]
call mutex_unlock call mutex_unlock

View File

@ -11,12 +11,16 @@ IPPROTO_IP = 0
IPPROTO_ICMP = 1 IPPROTO_ICMP = 1
IPPROTO_TCP = 6 IPPROTO_TCP = 6
IPPROTO_UDP = 17 IPPROTO_UDP = 17
IPPROTO_RAW = 255
; IP options
IP_TTL = 2
; Address families ; Address families
AF_UNSPEC = 0 AF_UNSPEC = 0
AF_LOCAL = 1 AF_LOCAL = 1
AF_INET4 = 2 ; IPv4 AF_INET4 = 2 ; IPv4
AF_INET6 = 28 ; IPv6 (not supported yet) AF_INET6 = 28 ; IPv6
PF_UNSPEC = AF_UNSPEC PF_UNSPEC = AF_UNSPEC
PF_LOCAL = AF_LOCAL PF_LOCAL = AF_LOCAL
@ -43,8 +47,14 @@ API_ARP = 5 shl 16
API_PPPOE = 6 shl 16 API_PPPOE = 6 shl 16
; Socket flags for user calls ; Socket flags for user calls
MSG_PEEK = 0x02 MSG_PEEK = 0x02
MSG_DONTWAIT = 0x40 MSG_DONTWAIT = 0x40
; Socket levels
SOL_SOCKET = 0xffff
; Socket options
SO_BINDTODEVICE = 1 shl 9
struct sockaddr_in struct sockaddr_in
sin_family dw ? ; sa_family_t sin_family dw ? ; sa_family_t

View File

@ -1,77 +1,75 @@
; ICMP types & codes ; ICMP types & codes
ICMP_ECHOREPLY equ 0 ; echo reply message ICMP_ECHOREPLY = 0 ; echo reply message
ICMP_UNREACH equ 3 ICMP_UNREACH = 3
ICMP_UNREACH_NET equ 0 ; bad net ICMP_UNREACH_NET = 0 ; bad net
ICMP_UNREACH_HOST equ 1 ; bad host ICMP_UNREACH_HOST = 1 ; bad host
ICMP_UNREACH_PROTOCOL equ 2 ; bad protocol ICMP_UNREACH_PROTOCOL = 2 ; bad protocol
ICMP_UNREACH_PORT equ 3 ; bad port ICMP_UNREACH_PORT = 3 ; bad port
ICMP_UNREACH_NEEDFRAG equ 4 ; IP_DF caused drop ICMP_UNREACH_NEEDFRAG = 4 ; IP_DF caused drop
ICMP_UNREACH_SRCFAIL equ 5 ; src route failed ICMP_UNREACH_SRCFAIL = 5 ; src route failed
ICMP_UNREACH_NET_UNKNOWN equ 6 ; unknown net ICMP_UNREACH_NET_UNKNOWN = 6 ; unknown net
ICMP_UNREACH_HOST_UNKNOWN equ 7 ; unknown host ICMP_UNREACH_HOST_UNKNOWN = 7 ; unknown host
ICMP_UNREACH_ISOLATED equ 8 ; src host isolated ICMP_UNREACH_ISOLATED = 8 ; src host isolated
ICMP_UNREACH_NET_PROHIB equ 9 ; prohibited access ICMP_UNREACH_NET_PROHIB = 9 ; prohibited access
ICMP_UNREACH_HOST_PROHIB equ 10 ; ditto ICMP_UNREACH_HOST_PROHIB = 10 ; ditto
ICMP_UNREACH_TOSNET equ 11 ; bad tos for net ICMP_UNREACH_TOSNET = 11 ; bad tos for net
ICMP_UNREACH_TOSHOST equ 12 ; bad tos for host ICMP_UNREACH_TOSHOST = 12 ; bad tos for host
ICMP_UNREACH_FILTER_PROHIB equ 13 ; admin prohib ICMP_UNREACH_FILTER_PROHIB = 13 ; admin prohib
ICMP_UNREACH_HOST_PRECEDENCE equ 14 ; host prec vio. ICMP_UNREACH_HOST_PRECEDENCE = 14 ; host prec vio.
ICMP_UNREACH_PRECEDENCE_CUTOFF equ 15 ; prec cutoff ICMP_UNREACH_PRECEDENCE_CUTOFF = 15 ; prec cutoff
ICMP_SOURCEQUENCH equ 4 ; Packet lost, slow down ICMP_SOURCEQUENCH = 4 ; Packet lost, slow down
ICMP_REDIRECT equ 5 ; shorter route, codes: ICMP_REDIRECT = 5 ; shorter route, codes:
ICMP_REDIRECT_NET equ 0 ; for network ICMP_REDIRECT_NET = 0 ; for network
ICMP_REDIRECT_HOST equ 1 ; for host ICMP_REDIRECT_HOST = 1 ; for host
ICMP_REDIRECT_TOSNET equ 2 ; for tos and net ICMP_REDIRECT_TOSNET = 2 ; for tos and net
ICMP_REDIRECT_TOSHOST equ 3 ; for tos and host ICMP_REDIRECT_TOSHOST = 3 ; for tos and host
ICMP_ALTHOSTADDR equ 6 ; alternate host address ICMP_ALTHOSTADDR = 6 ; alternate host address
ICMP_ECHO equ 8 ; echo service ICMP_ECHO = 8 ; echo service
ICMP_ROUTERADVERT equ 9 ; router advertisement ICMP_ROUTERADVERT = 9 ; router advertisement
ICMP_ROUTERADVERT_NORMAL equ 0 ; normal advertisement ICMP_ROUTERADVERT_NORMAL = 0 ; normal advertisement
ICMP_ROUTERADVERT_NOROUTE_COMMON equ 16 ; selective routing ICMP_ROUTERADVERT_NOROUTE_COMMON = 16 ; selective routing
ICMP_ROUTERSOLICIT equ 10 ; router solicitation ICMP_ROUTERSOLICIT = 10 ; router solicitation
ICMP_TIMXCEED equ 11 ; time exceeded, code: ICMP_TIMXCEED = 11 ; time exceeded, code:
ICMP_TIMXCEED_INTRANS equ 0 ; ttl==0 in transit ICMP_TIMXCEED_INTRANS = 0 ; ttl==0 in transit
ICMP_TIMXCEED_REASS equ 1 ; ttl==0 in reass ICMP_TIMXCEED_REASS = 1 ; ttl==0 in reass
ICMP_PARAMPROB equ 12 ; ip header bad ICMP_PARAMPROB = 12 ; ip header bad
ICMP_PARAMPROB_ERRATPTR equ 0 ; error at param ptr ICMP_PARAMPROB_ERRATPTR = 0 ; error at param ptr
ICMP_PARAMPROB_OPTABSENT equ 1 ; req. opt. absent ICMP_PARAMPROB_OPTABSENT = 1 ; req. opt. absent
ICMP_PARAMPROB_LENGTH equ 2 ; bad length ICMP_PARAMPROB_LENGTH = 2 ; bad length
ICMP_TSTAMP equ 13 ; timestamp request ICMP_TSTAMP = 13 ; timestamp r= est
ICMP_TSTAMPREPLY equ 14 ; timestamp reply ICMP_TSTAMPREPLY = 14 ; timestamp reply
ICMP_IREQ equ 15 ; information request ICMP_IREQ = 15 ; information r= est
ICMP_IREQREPLY equ 16 ; information reply ICMP_IREQREPLY = 16 ; information reply
ICMP_MASKREQ equ 17 ; address mask request ICMP_MASKREQ = 17 ; address mask r= est
ICMP_MASKREPLY equ 18 ; address mask reply ICMP_MASKREPLY = 18 ; address mask reply
ICMP_TRACEROUTE equ 30 ; traceroute ICMP_TRACEROUTE = 30 ; traceroute
ICMP_DATACONVERR equ 31 ; data conversion error ICMP_DATACONVERR = 31 ; data conversion error
ICMP_MOBILE_REDIRECT equ 32 ; mobile host redirect ICMP_MOBILE_REDIRECT = 32 ; mobile host redirect
ICMP_IPV6_WHEREAREYOU equ 33 ; IPv6 where-are-you ICMP_IPV6_WHEREAREYOU = 33 ; IPv6 where-are-you
ICMP_IPV6_IAMHERE equ 34 ; IPv6 i-am-here ICMP_IPV6_IAMHERE = 34 ; IPv6 i-am-here
ICMP_MOBILE_REGREQUEST equ 35 ; mobile registration req ICMP_MOBILE_REGREQUEST = 35 ; mobile registration req
ICMP_MOBILE_REGREPLY equ 36 ; mobile registreation reply ICMP_MOBILE_REGREPLY = 36 ; mobile registreation reply
ICMP_SKIP equ 39 ; SKIP ICMP_SKIP = 39 ; SKIP
ICMP_PHOTURIS equ 40 ; Photuris ICMP_PHOTURIS = 40 ; Photuris
ICMP_PHOTURIS_UNKNOWN_INDEX equ 1 ; unknown sec index ICMP_PHOTURIS_UNKNOWN_INDEX = 1 ; unknown sec index
ICMP_PHOTURIS_AUTH_FAILED equ 2 ; auth failed ICMP_PHOTURIS_AUTH_FAILED = 2 ; auth failed
ICMP_PHOTURIS_DECRYPT_FAILED equ 3 ; decrypt failed ICMP_PHOTURIS_DECRYPT_FAILED = 3 ; decrypt failed
virtual at 0 struct ICMP_header
ICMP_Packet: Type db ?
.Type db ? Code db ?
.Code db ? Checksum dw ?
.Checksum dw ? Identifier dw ?
.Identifier dw ? SequenceNumber dw ?
.SequenceNumber dw ? ends
.Data:
end virtual

View File

@ -12,8 +12,6 @@
;; ;; ;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TODO: ttl, user selectable size/number of packets
format binary as "" format binary as ""
BUFFERSIZE = 1500 BUFFERSIZE = 1500
@ -28,16 +26,18 @@ use32
dd I_END ; initialized size dd I_END ; initialized size
dd IM_END+0x1000 ; required memory dd IM_END+0x1000 ; required memory
dd IM_END+0x1000 ; stack pointer dd IM_END+0x1000 ; stack pointer
dd s ; parameters dd params ; parameters
dd 0 ; path dd 0 ; path
include '../../proc32.inc' include '../../proc32.inc'
include '../../macros.inc' include '../../macros.inc'
purge mov,add,sub purge mov,add,sub
include '../../dll.inc' include '../../dll.inc'
include '../../struct.inc'
include '../../network.inc' include '../../network.inc'
include 'icmp.inc' include 'icmp.inc'
include 'ip.inc'
START: START:
@ -53,13 +53,28 @@ START:
push 1 push 1
call [con_start] call [con_start]
push title push title
push 25 push 250
push 80 push 80
push 25 push 25
push 80 push 80
call [con_init] call [con_init]
; expand payload to 65504 bytes
mov edi, icmp_packet.data+32
mov ecx, 65504/32-1
.expand_payload:
mov esi, icmp_packet.data
movsd
movsd
movsd
movsd
movsd
movsd
movsd
movsd
dec ecx
jnz .expand_payload
; main loop ; main loop
cmp byte[s], 0 cmp byte[params], 0
jne parse_param jne parse_param
push str_welcome push str_welcome
@ -69,8 +84,8 @@ main:
push str_prompt push str_prompt
call [con_write_asciiz] call [con_write_asciiz]
; read string ; read string
mov esi, s mov esi, params
push 256 push 1024
push esi push esi
call [con_gets] call [con_gets]
; check for exit ; check for exit
@ -93,10 +108,14 @@ main:
mov [stats.time], 0 mov [stats.time], 0
parse_param: parse_param:
mov [count], 4 ; default number of pings to send ; parameters defaults
mov [count], 4
mov [size], 32
mov [ttl], 128
mov [timeout], 300
; Check if any additional parameters were given ; Check if any additional parameters were given
mov esi, s mov esi, params
mov ecx, 1024 mov ecx, 1024
.addrloop: .addrloop:
lodsb lodsb
@ -122,6 +141,42 @@ parse_param:
jne @f jne @f
mov [count], -1 ; infinite mov [count], -1 ; infinite
jmp .param_loop jmp .param_loop
@@:
cmp al, 'n'
jne @f
call ascii_to_dec
test ebx, ebx
jz .invalid
mov [count], ebx
jmp .param_loop
@@:
cmp al, 'l'
jne @f
call ascii_to_dec
test ebx, ebx
jz .invalid
cmp ebx, 65500
ja .invalid
mov [size], ebx
jmp .param_loop
@@:
cmp al, 'i'
jne @f
call ascii_to_dec
test ebx, ebx
jz .invalid
cmp ebx, 255
ja .invalid
mov [ttl], ebx
jmp .param_loop
@@:
cmp al, 'w'
jne @f
call ascii_to_dec
test ebx, ebx
jz .invalid
mov [timeout], ebx
jmp .param_loop
@@: @@:
; implement more parameters here ; implement more parameters here
.invalid: .invalid:
@ -135,7 +190,7 @@ parse_param:
push esp ; fourth parameter push esp ; fourth parameter
push 0 ; third parameter push 0 ; third parameter
push 0 ; second parameter push 0 ; second parameter
push s ; first parameter push params ; first parameter
call [getaddrinfo] call [getaddrinfo]
pop esi pop esi
; test for error ; test for error
@ -166,9 +221,19 @@ parse_param:
mov [socketnum], eax mov [socketnum], eax
mcall connect, [socketnum], sockaddr1, 18 mcall connect, [socketnum], sockaddr1, 18
cmp eax, -1
je fail2
pushd [ttl]
pushd 4 ; length of option
pushd IP_TTL
pushd IPPROTO_IP
mcall setsockopt, [socketnum], esp
add esp, 16
cmp eax, -1
je fail2
mcall 40, EVM_STACK mcall 40, EVM_STACK
; call [con_cls]
push str3 push str3
call [con_write_asciiz] call [con_write_asciiz]
@ -176,9 +241,10 @@ parse_param:
push [ip_ptr] push [ip_ptr]
call [con_write_asciiz] call [con_write_asciiz]
push (icmp_packet.length - ICMP_Packet.Data) push [size]
push str3b push str3b
call [con_printf] call [con_printf]
add esp, 2*4
mainloop: mainloop:
call [con_get_flags] call [con_get_flags]
@ -188,9 +254,14 @@ mainloop:
inc [stats.tx] inc [stats.tx]
mcall 26, 10 ; Get high precision timer count mcall 26, 10 ; Get high precision timer count
mov [time_reference], eax mov [time_reference], eax
mcall send, [socketnum], icmp_packet, icmp_packet.length, 0 mov esi, [size]
add esi, sizeof.ICMP_header
xor edi, edi
mcall send, [socketnum], icmp_packet
cmp eax, -1
je fail2
mcall 23, 300 ; 3 seconds time-out mcall 23, [timeout]
mcall 26, 10 ; Get high precision timer count mcall 26, 10 ; Get high precision timer count
sub eax, [time_reference] sub eax, [time_reference]
jz @f jz @f
@ -203,54 +274,102 @@ mainloop:
@@: @@:
mov [time_reference], eax mov [time_reference], eax
; Receive reply
mcall recv, [socketnum], buffer_ptr, BUFFERSIZE, MSG_DONTWAIT mcall recv, [socketnum], buffer_ptr, BUFFERSIZE, MSG_DONTWAIT
cmp eax, -1 cmp eax, -1
je .no_response je .no_response
test eax, eax
jz fail2
sub eax, ICMP_Packet.Data ; IP header length
movzx esi, byte[buffer_ptr]
and esi, 0xf
shl esi, 2
; Check packet length
sub eax, esi
sub eax, sizeof.ICMP_header
jb .invalid jb .invalid
mov [recvd], eax mov [recvd], eax
cmp word[buffer_ptr + ICMP_Packet.Identifier], IDENTIFIER ; make esi point to ICMP packet header
add esi, buffer_ptr
; we have a response, print the sender IP
push esi
mov eax, [buffer_ptr + IPv4_header.SourceAddress]
rol eax, 16
movzx ebx, ah
push ebx
movzx ebx, al
push ebx
shr eax, 16
movzx ebx, ah
push ebx
movzx ebx, al
push ebx
push str11
call [con_printf]
add esp, 5*4
pop esi
; What kind of response is it?
cmp [esi + ICMP_header.Type], ICMP_ECHOREPLY
je .echo_reply
cmp [esi + ICMP_header.Type], ICMP_TIMXCEED
je .ttl_exceeded
jmp .invalid
.echo_reply:
cmp [esi + ICMP_header.Identifier], IDENTIFIER
jne .invalid jne .invalid
; OK, we have a response, update stats and let the user know ; Validate the packet
inc [stats.rx] add esi, sizeof.ICMP_header
mov eax, [time_reference] mov ecx, [size]
add [stats.time], eax
push str11 ; TODO: print IP address of packet sender
call [con_write_asciiz]
; validate the packet
lea esi, [buffer_ptr + ICMP_Packet.Data]
mov ecx, [recvd]
mov edi, icmp_packet.data mov edi, icmp_packet.data
repe cmpsb repe cmpsb
jne .miscomp jne .miscomp
; All OK, print to the user! ; update stats
inc [stats.rx]
mov eax, [time_reference]
add [stats.time], eax
movzx eax, [buffer_ptr + IPv4_header.TimeToLive]
push eax
mov eax, [time_reference] mov eax, [time_reference]
xor edx, edx xor edx, edx
mov ebx, 10 mov ebx, 10
div ebx div ebx
push edx push edx
push eax push eax
; movzx eax, word[buffer_ptr + ICMP_Packet.SequenceNumber]
; push eax
push [recvd] push [recvd]
push str7 push str7
call [con_printf] call [con_printf]
add esp, 5*4
jmp .continue jmp .continue
.ttl_exceeded:
push str14
call [con_write_asciiz]
jmp .continue
; Error in packet, print it to user ; Error in packet, print it to user
.miscomp: .miscomp:
sub edi, icmp_packet.data sub edi, icmp_packet.data+1
push edi push edi
push str9 push str9
call [con_printf] call [con_printf]
add esp, 2*4
jmp .continue jmp .continue
; Invalid reply ; Invalid reply
@ -271,14 +390,14 @@ mainloop:
cmp [count], -1 cmp [count], -1
je .forever je .forever
dec [count] dec [count]
jz done jz .stats
.forever: .forever:
mcall 5, 100 ; wait a second ; wait a second before sending next request
mcall 5, 100
jmp mainloop jmp mainloop
; Done.. ; Print statistics
done: .stats:
cmp [stats.rx], 0 cmp [stats.rx], 0
jne @f jne @f
xor eax, eax xor eax, eax
@ -298,6 +417,7 @@ done:
push [stats.tx] push [stats.tx]
push str12 push str12
call [con_printf] call [con_printf]
add esp, 5*4
jmp main jmp main
; DNS error ; DNS error
@ -320,24 +440,61 @@ exit_now:
mcall -1 mcall -1
ascii_to_dec:
lodsb
cmp al, ' '
jne .fail
xor eax, eax
xor ebx, ebx
.loop:
lodsb
test al, al
jz .done
cmp al, ' '
je .done
sub al, '0'
jb .fail
cmp al, 9
ja .fail
lea ebx, [ebx*4+ebx]
lea ebx, [ebx*2+eax]
jmp .loop
.fail:
xor ebx, ebx
.done:
dec esi
ret
; data ; data
title db 'ICMP echo (ping) client',0 title db 'ICMP echo (ping) client',0
str_welcome db 'Please enter the hostname or IP-address of the host you want to ping,',10 str_welcome db 'Please enter the hostname or IP-address of the host you want to ping,',10
db 'or just press enter to exit.',10,0 db 'or just press enter to exit.',10,10
db 'Options:',10
db ' -t Send packets till users abort.',10
db ' -n number Number of requests to send.',10
db ' -i TTL Time to live.',10
db ' -l size Size of echo request.',10
db ' -w time-out Time-out in hundredths of a second.',10,0
str_prompt db 10,'> ',0 str_prompt db 10,'> ',0
str3 db 'Pinging to ',0 str3 db 'Pinging to ',0
str3b db ' with %u data bytes',10,0 str3b db ' with %u data bytes',10,0
str4 db 10,0 str4 db 10,0
str5 db 'Name resolution failed.',10,0 str5 db 'Name resolution failed.',10,0
str6 db 'Could not open socket',10,0 str6 db 'Socket error.',10,0
str13 db 'Invalid parameter(s)',10,0 str13 db 'Invalid parameter(s)',10,0
str11 db 'Answer: ',0 str11 db 'Answer from %u.%u.%u.%u: ',0
str7 db 'bytes=%u time=%u.%u ms',10,0 str7 db 'bytes=%u time=%u.%u ms TTL=%u',10,0
str8 db 'Timeout',10,0 str8 db 'Timeout',10,0
str9 db 'Miscompare at offset %u',10,0 str9 db 'miscompare at offset %u.',10,0
str10 db 'Invalid reply',10,0 str10 db 'invalid reply.',10,0
str14 db 'TTL expired.',10,0
str12 db 10,'Statistics:',10,'%u packets sent, %u packets received',10,'average response time=%u.%u ms',10,0 str12 db 10,'Statistics:',10,'%u packets sent, %u packets received',10,'average response time=%u.%u ms',10,0
@ -350,6 +507,9 @@ sockaddr1:
time_reference dd ? time_reference dd ?
ip_ptr dd ? ip_ptr dd ?
count dd ? count dd ?
size dd ?
ttl dd ?
timeout dd ?
recvd dd ? ; received number of bytes in last packet recvd dd ? ; received number of bytes in last packet
stats: stats:
@ -381,18 +541,17 @@ import console, \
socketnum dd ? socketnum dd ?
icmp_packet db 8 ; type icmp_packet db ICMP_ECHO ; type
db 0 ; code db 0 ; code
dw 0 ; dw 0 ; checksum
.id dw IDENTIFIER ; identifier .id dw IDENTIFIER ; identifier
.seq dw 0x0000 ; sequence number .seq dw 0x0000 ; sequence number
.data db 'abcdefghijklmnopqrstuvwxyz012345' .data db 'abcdefghijklmnopqrstuvwxyz012345'
.length = $ - icmp_packet
I_END: I_END:
rb 65504-32
s db 0 params rb 1024
rb 1024 buffer_ptr: rb BUFFERSIZE
buffer_ptr rb BUFFERSIZE
IM_END: IM_END:

View File

@ -20,7 +20,7 @@ format binary as ""
; CONFIGURATION ; CONFIGURATION
TIMEOUT = 3 ; in seconds TIMEOUT = 5 ; in seconds
BUFFER = 1024 ; in bytes BUFFER = 1024 ; in bytes
DHCP_TRIES = 3 ; number of times to try contacting DHCP server DHCP_TRIES = 3 ; number of times to try contacting DHCP server
__DEBUG__ = 1 ; enable/disable __DEBUG__ = 1 ; enable/disable
@ -318,8 +318,8 @@ dhcp:
pushd [ebp + interface.number] pushd [ebp + interface.number]
pushd 4 ; length of option pushd 4 ; length of option
pushd 1 shl 9 ; SO_BINDTODEVICE pushd SO_BINDTODEVICE
pushd 0 ; SOL_SOCKET pushd SOL_SOCKET
mcall 75, 8, [ebp + interface.socketNum], esp mcall 75, 8, [ebp + interface.socketNum], esp
add esp, 16 add esp, 16
cmp eax, -1 cmp eax, -1