diff --git a/kernel/trunk/network/IPv4.inc b/kernel/trunk/network/IPv4.inc index 7580c5ef52..fb7baa42c1 100644 --- a/kernel/trunk/network/IPv4.inc +++ b/kernel/trunk/network/IPv4.inc @@ -215,7 +215,6 @@ macro IPv4_checksum ptr { ; It will also re-construct fragmented packets ; ; IN: Pointer to buffer in [esp] -; size of buffer in [esp+4] ; pointer to device struct in ebx ; pointer to IPv4 header in edx ; size of IPv4 packet in ecx @@ -223,7 +222,7 @@ macro IPv4_checksum ptr { ; ;----------------------------------------------------------------- align 4 -IPv4_input: ; TODO: add IPv4 raw sockets support +IPv4_input: DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: packet from %u.%u.%u.%u ",\ [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 + 2]:1,[edx + IPv4_header.DestinationAddress + 3]:1 + call NET_ptr_to_num4 + cmp edi, -1 + je .invalid_device + ;------------------------------- ; re-calculate the checksum @@ -240,40 +243,32 @@ IPv4_input: ; TODO: add IPv4 DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Checksum ok\n" -;----------------------------------- -; Check if destination IP is correct - - call NET_ptr_to_num4 - - ; check if it matches local ip (Using RFC1122 strong end system model) +;-------------------------------- +; Check if destination IP matches +; local ip (Using RFC1122 strong end system model) mov eax, [edx + IPv4_header.DestinationAddress] cmp eax, [IP_LIST + edi] je .ip_ok - ; check for broadcast (IP or (not SUBNET)) - +; network layer broadcast cmp eax, [BROADCAST_LIST + edi] je .ip_ok - ; or a special broadcast (255.255.255.255) - +; physical layer broadcast (255.255.255.255) cmp eax, 0xffffffff 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 cmp eax, 224 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 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" jmp .dump @@ -305,7 +300,6 @@ IPv4_input: ; TODO: add IPv4 xchg cl, ch ; sub ecx, esi ; - lea edi, [edx + IPv4_header.SourceAddress] ; make edi ptr to source and dest IPv4 address mov al, [edx + IPv4_header.Protocol] add esi, edx ; make esi ptr to data @@ -318,11 +312,60 @@ IPv4_input: ; TODO: add IPv4 cmp al, IP_PROTO_ICMP 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 .dump: 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 ret @@ -568,11 +611,12 @@ IPv4_find_fragment_slot: ; ; IPv4_output ; -; IN: eax = Destination IP +; IN: al = protocol +; ah = TTL ; ebx = device ptr (or 0 to let IP layer decide) ; ecx = data length ; edx = Source IP -; di = TTL shl 8 + protocol +; edi = Destination IP ; ; OUT: eax = pointer to buffer start / 0 on error ; ebx = device ptr (send packet through this device) @@ -589,7 +633,8 @@ IPv4_output: cmp ecx, 65500 ; Max IPv4 packet size 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 push edx test edi, edi @@ -601,7 +646,7 @@ IPv4_output: push ebx ; push the mac onto the stack push ax - inc [IPv4_packets_tx + edi] ; update stats + inc [IPv4_packets_tx + edi] ; update stats mov ax, ETHER_PROTO_IPv4 mov ebx, [NET_DRV_LIST + edi] @@ -642,7 +687,10 @@ IPv4_output: .arp_error: 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 ret @@ -678,9 +726,6 @@ IPv4_output_raw: 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 push esi eax @@ -707,7 +752,7 @@ IPv4_output_raw: mov dword[esp+4+4+4], eax 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 rep movsb @@ -734,11 +779,14 @@ IPv4_output_raw: ret .error: - add esp, 6 + add esp, 6+8+4+4 + mov ebx, ENOBUFS ; FIXME: NOBUFS or MSGSIZE error + or eax, -1 + ret + .arp_error: add esp, 8+4+4 - .too_large: - DEBUGF DEBUG_NETWORK_ERROR, "IPv4_output_raw: Failed\n" + mov ebx, ENOTCONN or eax, -1 ret @@ -746,117 +794,120 @@ IPv4_output_raw: ;-------------------------------------------------------- ; ; -; IN: dword [esp] = pointer to buffer containing ipv4 packet to be fragmented -; esi = pointer to ip header in that buffer -; ecx = max size of fragments +; IN: [esp] = pointer to buffer containing ipv4 packet to be fragmented +; edi = pointer to ip header in that buffer +; ebx = device ptr ; ; OUT: / ; ;-------------------------------------------------------- +proc IPv4_fragment stdcall buffer -align 4 -IPv4_fragment: +locals + offset dd ? + headerlength dd ? + headerptr dd ? + dataptr dd ? + remaining dd ? + segmentsize dd ? +endl DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_fragment\n" - and ecx, not 111b ; align 4 - - cmp ecx, sizeof.IPv4_header + 8 ; must be able to put at least 8 bytes - jb .err2 - - push esi ecx - mov eax, [esi + IPv4_header.DestinationAddress] - call ARP_IP_to_MAC - pop ecx esi - cmp eax, -1 - 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 +; We must be able to put at least 8 bytes per segment + movzx eax, byte[edi] ; IHL + and eax, 0xf + shl eax, 2 + mov [headerlength], eax + add eax, 8 + mov ecx, [ebx + NET_DEVICE.mtu] + and ecx, not 11b + cmp ecx, eax + jb .fail mov [edi + IPv4_header.HeaderChecksum], 0 - ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<< send the packet - mov ecx, [esp + 1*4] + mov [segmentsize], ecx + 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 - call [ebx + NET_DEVICE.transmit] - ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<< - mov ecx, [esp+4] - add [esp], ecx + cmp [remaining], 0 + 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 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] 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] call mutex_unlock diff --git a/kernel/trunk/network/icmp.inc b/kernel/trunk/network/icmp.inc index a34dcd6d46..d1d7d50939 100644 --- a/kernel/trunk/network/icmp.inc +++ b/kernel/trunk/network/icmp.inc @@ -133,8 +133,9 @@ macro ICMP_init { ; IN: Pointer to buffer in [esp] ; ebx = pointer to device struct ; ecx = ICMP Packet size +; edx = ptr to IPv4 header ; esi = ptr to ICMP Packet data -; edi = ptr to ipv4 source and dest address +; edi = interface number*4 ; ; OUT: / ; @@ -144,8 +145,13 @@ ICMP_input: 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 - push esi ecx + push esi ecx edx push [esi + ICMP_header.Checksum] mov [esi + ICMP_header.Checksum], 0 xor edx, edx @@ -153,17 +159,11 @@ ICMP_input: call checksum_2 pop si cmp dx, si - pop ecx esi + pop edx ecx esi jne .checksum_mismatch 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 inc [ICMP_PACKETS_RX + edi] @@ -177,10 +177,10 @@ ICMP_input: call mutex_lock popa - mov edx, [eax] ; ipv4 source address + add ecx, esi + sub ecx, edx + mov esi, edx mov eax, net_sockets - .try_more: -; mov , [esi + ICMP_header.Identifier] .next_socket: mov eax, [eax + SOCKET.NextPtr] or eax, eax @@ -192,12 +192,6 @@ ICMP_input: cmp [eax + SOCKET.Protocol], IP_PROTO_ICMP jne .next_socket - cmp [eax + IP_SOCKET.RemoteIP], edx - jne .next_socket - -; cmp [eax + ICMP_SOCKET.Identifier], -; jne .next_socket - pusha mov ecx, socket_mutex call mutex_unlock @@ -376,7 +370,7 @@ end if ; ; IN: eax = socket ptr ; ecx = data length -; esi = data offset +; edx = data pointer ; ;----------------------------------------------------------------- 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 push edx - - mov di, IP_PROTO_ICMP SHL 8 + 128 ; TTL - mov edx, [eax + IP_SOCKET.LocalIP] 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 - jz .exit + jz .fail pop esi push eax @@ -415,10 +409,14 @@ ICMP_output_raw: jnz @f call NET_ptr_to_num4 inc [ICMP_PACKETS_TX + edi] - @@: + @@: ret - .exit: + + .fail: + pop edx DEBUGF DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n" + or eax, -1 + mov ebx, EMSGSIZE ;;; FIXME ret diff --git a/kernel/trunk/network/socket.inc b/kernel/trunk/network/socket.inc index b5432ed145..cf618a854e 100644 --- a/kernel/trunk/network/socket.inc +++ b/kernel/trunk/network/socket.inc @@ -27,9 +27,9 @@ struct SOCKET PID dd ? ; process ID TID dd ? ; thread ID - Domain dd ? ; INET/LOCAL/.. + Domain dd ? ; INET4/INET6/LOCAL/.. Type dd ? ; RAW/STREAM/DGRAM - Protocol dd ? ; ICMP/IPv4/ARP/TCP/UDP + Protocol dd ? ; UDP/TCP/ARP/ICMP errorcode dd ? 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 RemoteIP rd 4 ; network byte order + ttl db ? + rb 3 ; align ends @@ -150,14 +152,6 @@ struct UDP_SOCKET IP_SOCKET ends - -struct ICMP_SOCKET IP_SOCKET - - Identifier dw ? - -ends - - struct RING_BUFFER mutex MUTEX @@ -313,6 +307,8 @@ SOCKET_open: cmp ecx, AF_INET4 jne .no_inet4 + mov [eax + IP_SOCKET.ttl], 128 + cmp edx, SOCK_DGRAM je .udp @@ -354,6 +350,10 @@ SOCKET_open: align 4 .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.snd_proc], SOCKET_send_udp mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram @@ -373,6 +373,10 @@ align 4 align 4 .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.rcv_proc], SOCKET_receive_dgram mov [eax + SOCKET.connect_proc], IPv4_connect @@ -381,6 +385,10 @@ align 4 align 4 .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.rcv_proc], SOCKET_receive_dgram mov [eax + SOCKET.connect_proc], IPv4_connect @@ -975,14 +983,14 @@ SOCKET_send_ip: DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: IPv4\n" mov [esp+32], ecx - call IPv4_output_raw ; FIXME: IPv4_output_raw should return error codes! + call IPv4_output_raw cmp eax, -1 je .error ret .error: - mov dword[esp+32], -1 - mov dword[esp+20], EMSGSIZE + mov dword[esp+32], eax + mov dword[esp+20], ebx ret @@ -992,14 +1000,14 @@ SOCKET_send_icmp: DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: ICMP\n" mov [esp+32], ecx - call ICMP_output_raw ; FIXME: errorcodes + call ICMP_output_raw cmp eax, -1 je .error ret .error: - mov dword[esp+32], -1 - mov dword[esp+20], EMSGSIZE + mov dword[esp+32], eax + mov dword[esp+20], ebx ret @@ -1126,17 +1134,23 @@ SOCKET_get_opt: ret - ;----------------------------------------------------------------- ; ; SOCKET_set_options ; ; IN: ecx = socket number -; edx = pointer to the options: -; dd level, optname, optlen, optval +; edx = pointer to socket_options ; OUT: -1 on error ; ;----------------------------------------------------------------- + +struct socket_options + level dd ? + optname dd ? + optlen dd ? + optval dd ? +ends + align 4 SOCKET_set_opt: @@ -1145,22 +1159,20 @@ SOCKET_set_opt: call SOCKET_num_to_ptr 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 - cmp dword [edx+4], SO_BINDTODEVICE - je .bind - - .invalid: - mov dword[esp+32], -1 - mov dword[esp+20], EINVAL - ret + .socket: + cmp [edx + socket_options.optname], SO_BINDTODEVICE + jne .invalid .bind: - cmp dword[edx+8], 0 + cmp [edx + socket_options.optlen], 0 je .unbind - movzx edx, byte[edx + 12] + movzx edx, byte[edx + socket_options.optval] cmp edx, NET_DEVICES_MAX ja .invalid @@ -1180,11 +1192,27 @@ SOCKET_set_opt: mov dword[esp+32], 0 ; success! 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: mov dword[esp+20], EALREADY mov dword[esp+32], -1 ret + .invalid: + mov dword[esp+20], EINVAL + mov dword[esp+32], -1 + ret + @@ -1474,6 +1502,7 @@ SOCKET_input: call mutex_unlock popa + add esp, 8 call NET_BUFF_free ret diff --git a/kernel/trunk/network/stack.inc b/kernel/trunk/network/stack.inc index ff7b9d4224..ec10d5a9ee 100644 --- a/kernel/trunk/network/stack.inc +++ b/kernel/trunk/network/stack.inc @@ -53,6 +53,12 @@ IP_PROTO_IP = 0 IP_PROTO_ICMP = 1 IP_PROTO_TCP = 6 IP_PROTO_UDP = 17 +IP_PROTO_RAW = 255 + +; IP options +IP_TOS = 1 +IP_TTL = 2 +IP_HDRINCL = 3 ; PPP protocol numbers PPP_PROTO_IPv4 = 0x2100 @@ -71,6 +77,9 @@ SOCK_STREAM = 1 SOCK_DGRAM = 2 SOCK_RAW = 3 +; Socket level +SOL_SOCKET = 0xffff + ; Socket options SO_ACCEPTCON = 1 shl 0 SO_BROADCAST = 1 shl 1 @@ -89,10 +98,6 @@ SO_NONBLOCK = 1 shl 31 MSG_PEEK = 0x02 MSG_DONTWAIT = 0x40 -; Socket level -SOL_SOCKET = 0 - - ; Socket States SS_NOFDREF = 0x0001 ; no file table ref any more SS_ISCONNECTED = 0x0002 ; socket connected to a peer diff --git a/kernel/trunk/network/tcp_input.inc b/kernel/trunk/network/tcp_input.inc index d6731c7235..12c46870a9 100644 --- a/kernel/trunk/network/tcp_input.inc +++ b/kernel/trunk/network/tcp_input.inc @@ -24,9 +24,10 @@ $Revision$ ; ; IN: [esp] = ptr to buffer ; ebx = ptr to device struct -; ecx = segment size +; ecx = TCP segment size +; edx = ptr to IPv4 header ; esi = ptr to TCP segment -; edi = ptr to ipv4 source address, followed by ipv4 dest address +; edi = interface number*4 ; ; OUT: / ; @@ -37,13 +38,14 @@ TCP_input: ; record the current time 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 + push edi add_to_queue TCP_queue, TCP_QUEUE_SIZE, sizeof.TCP_queue_entry, .fail + pop edi add esp, sizeof.TCP_queue_entry - call NET_ptr_to_num4 inc [TCP_segments_rx + edi] xor edx, edx @@ -55,6 +57,7 @@ TCP_input: ret .fail: + pop edi DEBUGF DEBUG_NETWORK_VERBOSE, "TCP incoming queue is full, discarding packet!\n" call NET_ptr_to_num4 @@ -94,7 +97,7 @@ endl mov ebx, [esi + TCP_queue_entry.device_ptr] 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 DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: size=%u time=%d\n", ecx, [timer_ticks] @@ -111,8 +114,8 @@ endl push ecx esi pushw [esi + TCP_header.Checksum] mov [esi + TCP_header.Checksum], 0 - TCP_checksum (edi), (edi+4) - pop cx ; previous checksum + TCP_checksum (edi+IPv4_header.SourceAddress), (edi+IPv4_header.DestinationAddress) + pop cx ; previous checksum cmp cx, dx pop edx ecx jne .drop_no_socket @@ -170,7 +173,7 @@ endl jne .socket_loop mov eax, [ebx + IP_SOCKET.RemoteIP] - cmp eax, [edi] ; Ipv4 source address + cmp eax, [edi + IPv4_header.SourceAddress] je @f test eax, eax jnz .socket_loop @@ -233,7 +236,7 @@ endl call mutex_unlock popa - push ecx edx esi edi ;;; + push ecx edx esi edi call SOCKET_fork pop edi esi edx ecx @@ -244,7 +247,7 @@ endl mov [temp_bits], TCP_BIT_DROPSOCKET - push dword [edi + 4] ; Ipv4 destination addres + push [edi + IPv4_header.DestinationAddress] pop [ebx + IP_SOCKET.LocalIP] push [edx + TCP_header.DestinationPort] @@ -1211,7 +1214,7 @@ align 4 ;;; 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] push [edx + TCP_header.SourcePort] @@ -1673,11 +1676,13 @@ align 4 .respond_seg_ack: mov cl, TH_RST + xor ebx, ebx ; FIXME: find a way to get the receiving device ptr call TCP_respond_segment jmp .drop_no_socket .respond_seg_syn: mov cl, TH_RST + TH_ACK + xor ebx, ebx ; FIXME: find a way to get the receiving device ptr call TCP_respond_segment jmp .drop_no_socket diff --git a/kernel/trunk/network/tcp_output.inc b/kernel/trunk/network/tcp_output.inc index a7e8ad2041..301fe7e897 100644 --- a/kernel/trunk/network/tcp_output.inc +++ b/kernel/trunk/network/tcp_output.inc @@ -503,10 +503,11 @@ endl ; Create the IP packet mov ecx, esi - mov edx, [eax + IP_SOCKET.LocalIP] ; source ip mov ebx, [eax + IP_SOCKET.device] - mov eax, [eax + IP_SOCKET.RemoteIP] ; dest ip - mov di, IP_PROTO_TCP shl 8 + 128 + mov edx, [eax + IP_SOCKET.LocalIP] ; source ip + mov edi, [eax + IP_SOCKET.RemoteIP] ; dest ip + mov al, [eax + IP_SOCKET.ttl] + mov ah, IP_PROTO_TCP call IPv4_output jz .ip_error diff --git a/kernel/trunk/network/tcp_subr.inc b/kernel/trunk/network/tcp_subr.inc index 618b56bdc7..9ce90d7eb1 100644 --- a/kernel/trunk/network/tcp_subr.inc +++ b/kernel/trunk/network/tcp_subr.inc @@ -266,7 +266,7 @@ TCP_outflags: -;--------------------------------------- +;----------------------------------------------------------------- ; ; The fast way to send an ACK/RST/keepalive segment ; @@ -275,7 +275,10 @@ TCP_outflags: ; IN: ebx = socket ptr ; cl = flags ; -;-------------------------------------- +; OUT: / +; +;----------------------------------------------------------------- + align 4 TCP_respond: @@ -285,11 +288,12 @@ TCP_respond: ; Create the IP packet push cx ebx - mov eax, [ebx + IP_SOCKET.RemoteIP] 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 di, IP_PROTO_TCP shl 8 + 128 + mov ebx, [ebx + IP_SOCKET.device] call IPv4_output jz .error pop esi cx @@ -347,33 +351,32 @@ TCP_respond: ret - - - - - - -;------------------------- +;----------------------------------------------------------------- +; ; TCP_respond_segment: ; -; IN: edx = segment ptr (a previously received segment) -; edi = ptr to dest and src IPv4 addresses +; IN: ebx = device ptr +; edx = segment ptr (a previously received segment) +; edi = ptr to IPv4 header ; cl = flags +; +; OUT: / +; +;----------------------------------------------------------------- align 4 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 push cx edx - mov edx, [edi + 4] - mov eax, [edi] + mov edx, [edi + IPv4_header.DestinationAddress] + mov edi, [edi + IPv4_header.SourceAddress] mov ecx, sizeof.TCP_header - mov di, IP_PROTO_TCP shl 8 + 128 - xor ebx, ebx ;;; fixme + mov ax, IP_PROTO_TCP shl 8 + 128 call IPv4_output jz .error pop esi cx diff --git a/kernel/trunk/network/udp.inc b/kernel/trunk/network/udp.inc index c8ae773507..4a160def0c 100644 --- a/kernel/trunk/network/udp.inc +++ b/kernel/trunk/network/udp.inc @@ -57,15 +57,15 @@ macro UDP_checksum IP1, IP2 { ; esi = ptr to udp packet, ecx = packet size ; Pseudoheader mov edx, IP_PROTO_UDP - add dl, [IP1+1] - adc dh, [IP1+0] - adc dl, [IP1+3] - adc dh, [IP1+2] + add dl, byte[IP1+1] + adc dh, byte[IP1+0] + adc dl, byte[IP1+3] + adc dh, byte[IP1+2] - adc dl, [IP2+1] - adc dh, [IP2+0] - adc dl, [IP2+3] - adc dh, [IP2+2] + adc dl, byte[IP2+1] + adc dh, byte[IP2+0] + adc dl, byte[IP2+3] + adc dh, byte[IP2+2] adc dl, cl ; byte[esi+UDP_header.Length+1] 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: ; ; 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 -; [esp+4] = size of buffer +; IN: [esp] = ptr to buffer ; ebx = ptr to device struct -; ecx = UDP Packet size -; esi = ptr to UDP header -; edi = ptr to ipv4 source and dest address +; ecx = UDP packet size +; edx = ptr to IPv4 header +; esi = ptr to UDP packet data +; edi = interface number*4 ; ; 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 - UDP_checksum (edi), (edi+4) + mov eax, edx + UDP_checksum (eax+IPv4_header.SourceAddress), (eax+IPv4_header.DestinationAddress) jnz .checksum_mismatch .no_checksum: @@ -148,9 +149,7 @@ UDP_input: mov cx, [esi + UDP_header.SourcePort] mov dx, [esi + UDP_header.DestinationPort] - mov edi, [edi + 4] ; ipv4 source address mov eax, net_sockets - .next_socket: mov eax, [eax + SOCKET.NextPtr] or eax, eax @@ -172,15 +171,15 @@ UDP_input: call mutex_unlock 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 ; je @f -; cmp [eax + IP_SOCKET.RemoteIP], edi +; cmp [eax + IP_SOCKET.RemoteIP], ; jne .next_socket ; @@: -; -; FIXME: UDP should check remote IP, but not under all circumstances! cmp [eax + UDP_SOCKET.RemotePort], 0 je .updateport @@ -194,7 +193,6 @@ UDP_input: popa .updatesock: - call NET_ptr_to_num4 inc [UDP_PACKETS_RX + edi] movzx ecx, [esi + UDP_header.Length] @@ -257,10 +255,11 @@ UDP_output: sub esp, 4 ; Data ptr will be placed here push edx esi - mov edx, [eax + IP_SOCKET.LocalIP] mov ebx, [eax + IP_SOCKET.device] - mov eax, [eax + IP_SOCKET.RemoteIP] - mov di, IP_PROTO_UDP shl 8 + 128 + mov edx, [eax + IP_SOCKET.LocalIP] + mov edi, [eax + IP_SOCKET.RemoteIP] + mov al, [eax + IP_SOCKET.ttl] + mov ah, IP_PROTO_UDP add ecx, sizeof.UDP_header call IPv4_output jz .fail @@ -347,10 +346,6 @@ UDP_connect: call SOCKET_find_port @@: - push eax - init_queue (eax + SOCKET_QUEUE_LOCATION) ; Set up data receiving queue - pop eax - push eax lea ecx, [eax + SOCKET.mutex] call mutex_unlock diff --git a/programs/network.inc b/programs/network.inc index 42b399e7b0..877ed7e4ad 100644 --- a/programs/network.inc +++ b/programs/network.inc @@ -11,12 +11,16 @@ IPPROTO_IP = 0 IPPROTO_ICMP = 1 IPPROTO_TCP = 6 IPPROTO_UDP = 17 +IPPROTO_RAW = 255 + +; IP options +IP_TTL = 2 ; Address families AF_UNSPEC = 0 AF_LOCAL = 1 AF_INET4 = 2 ; IPv4 -AF_INET6 = 28 ; IPv6 (not supported yet) +AF_INET6 = 28 ; IPv6 PF_UNSPEC = AF_UNSPEC PF_LOCAL = AF_LOCAL @@ -43,8 +47,14 @@ API_ARP = 5 shl 16 API_PPPOE = 6 shl 16 ; Socket flags for user calls -MSG_PEEK = 0x02 -MSG_DONTWAIT = 0x40 +MSG_PEEK = 0x02 +MSG_DONTWAIT = 0x40 + +; Socket levels +SOL_SOCKET = 0xffff + +; Socket options +SO_BINDTODEVICE = 1 shl 9 struct sockaddr_in sin_family dw ? ; sa_family_t diff --git a/programs/network/icmp/icmp.inc b/programs/network/icmp/icmp.inc index bcafff37e9..fb689adc65 100644 --- a/programs/network/icmp/icmp.inc +++ b/programs/network/icmp/icmp.inc @@ -1,77 +1,75 @@ ; ICMP types & codes -ICMP_ECHOREPLY equ 0 ; echo reply message +ICMP_ECHOREPLY = 0 ; echo reply message -ICMP_UNREACH equ 3 -ICMP_UNREACH_NET equ 0 ; bad net -ICMP_UNREACH_HOST equ 1 ; bad host -ICMP_UNREACH_PROTOCOL equ 2 ; bad protocol -ICMP_UNREACH_PORT equ 3 ; bad port -ICMP_UNREACH_NEEDFRAG equ 4 ; IP_DF caused drop -ICMP_UNREACH_SRCFAIL equ 5 ; src route failed -ICMP_UNREACH_NET_UNKNOWN equ 6 ; unknown net -ICMP_UNREACH_HOST_UNKNOWN equ 7 ; unknown host -ICMP_UNREACH_ISOLATED equ 8 ; src host isolated -ICMP_UNREACH_NET_PROHIB equ 9 ; prohibited access -ICMP_UNREACH_HOST_PROHIB equ 10 ; ditto -ICMP_UNREACH_TOSNET equ 11 ; bad tos for net -ICMP_UNREACH_TOSHOST equ 12 ; bad tos for host -ICMP_UNREACH_FILTER_PROHIB equ 13 ; admin prohib -ICMP_UNREACH_HOST_PRECEDENCE equ 14 ; host prec vio. -ICMP_UNREACH_PRECEDENCE_CUTOFF equ 15 ; prec cutoff +ICMP_UNREACH = 3 +ICMP_UNREACH_NET = 0 ; bad net +ICMP_UNREACH_HOST = 1 ; bad host +ICMP_UNREACH_PROTOCOL = 2 ; bad protocol +ICMP_UNREACH_PORT = 3 ; bad port +ICMP_UNREACH_NEEDFRAG = 4 ; IP_DF caused drop +ICMP_UNREACH_SRCFAIL = 5 ; src route failed +ICMP_UNREACH_NET_UNKNOWN = 6 ; unknown net +ICMP_UNREACH_HOST_UNKNOWN = 7 ; unknown host +ICMP_UNREACH_ISOLATED = 8 ; src host isolated +ICMP_UNREACH_NET_PROHIB = 9 ; prohibited access +ICMP_UNREACH_HOST_PROHIB = 10 ; ditto +ICMP_UNREACH_TOSNET = 11 ; bad tos for net +ICMP_UNREACH_TOSHOST = 12 ; bad tos for host +ICMP_UNREACH_FILTER_PROHIB = 13 ; admin prohib +ICMP_UNREACH_HOST_PRECEDENCE = 14 ; host prec vio. +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_NET equ 0 ; for network -ICMP_REDIRECT_HOST equ 1 ; for host -ICMP_REDIRECT_TOSNET equ 2 ; for tos and net -ICMP_REDIRECT_TOSHOST equ 3 ; for tos and host +ICMP_REDIRECT = 5 ; shorter route, codes: +ICMP_REDIRECT_NET = 0 ; for network +ICMP_REDIRECT_HOST = 1 ; for host +ICMP_REDIRECT_TOSNET = 2 ; for tos and net +ICMP_REDIRECT_TOSHOST = 3 ; for tos and host -ICMP_ALTHOSTADDR equ 6 ; alternate host address -ICMP_ECHO equ 8 ; echo service -ICMP_ROUTERADVERT equ 9 ; router advertisement -ICMP_ROUTERADVERT_NORMAL equ 0 ; normal advertisement -ICMP_ROUTERADVERT_NOROUTE_COMMON equ 16 ; selective routing +ICMP_ALTHOSTADDR = 6 ; alternate host address +ICMP_ECHO = 8 ; echo service +ICMP_ROUTERADVERT = 9 ; router advertisement +ICMP_ROUTERADVERT_NORMAL = 0 ; normal advertisement +ICMP_ROUTERADVERT_NOROUTE_COMMON = 16 ; selective routing -ICMP_ROUTERSOLICIT equ 10 ; router solicitation -ICMP_TIMXCEED equ 11 ; time exceeded, code: -ICMP_TIMXCEED_INTRANS equ 0 ; ttl==0 in transit -ICMP_TIMXCEED_REASS equ 1 ; ttl==0 in reass +ICMP_ROUTERSOLICIT = 10 ; router solicitation +ICMP_TIMXCEED = 11 ; time exceeded, code: +ICMP_TIMXCEED_INTRANS = 0 ; ttl==0 in transit +ICMP_TIMXCEED_REASS = 1 ; ttl==0 in reass -ICMP_PARAMPROB equ 12 ; ip header bad -ICMP_PARAMPROB_ERRATPTR equ 0 ; error at param ptr -ICMP_PARAMPROB_OPTABSENT equ 1 ; req. opt. absent -ICMP_PARAMPROB_LENGTH equ 2 ; bad length +ICMP_PARAMPROB = 12 ; ip header bad +ICMP_PARAMPROB_ERRATPTR = 0 ; error at param ptr +ICMP_PARAMPROB_OPTABSENT = 1 ; req. opt. absent +ICMP_PARAMPROB_LENGTH = 2 ; bad length -ICMP_TSTAMP equ 13 ; timestamp request -ICMP_TSTAMPREPLY equ 14 ; timestamp reply -ICMP_IREQ equ 15 ; information request -ICMP_IREQREPLY equ 16 ; information reply -ICMP_MASKREQ equ 17 ; address mask request -ICMP_MASKREPLY equ 18 ; address mask reply -ICMP_TRACEROUTE equ 30 ; traceroute -ICMP_DATACONVERR equ 31 ; data conversion error -ICMP_MOBILE_REDIRECT equ 32 ; mobile host redirect -ICMP_IPV6_WHEREAREYOU equ 33 ; IPv6 where-are-you -ICMP_IPV6_IAMHERE equ 34 ; IPv6 i-am-here -ICMP_MOBILE_REGREQUEST equ 35 ; mobile registration req -ICMP_MOBILE_REGREPLY equ 36 ; mobile registreation reply -ICMP_SKIP equ 39 ; SKIP +ICMP_TSTAMP = 13 ; timestamp r= est +ICMP_TSTAMPREPLY = 14 ; timestamp reply +ICMP_IREQ = 15 ; information r= est +ICMP_IREQREPLY = 16 ; information reply +ICMP_MASKREQ = 17 ; address mask r= est +ICMP_MASKREPLY = 18 ; address mask reply +ICMP_TRACEROUTE = 30 ; traceroute +ICMP_DATACONVERR = 31 ; data conversion error +ICMP_MOBILE_REDIRECT = 32 ; mobile host redirect +ICMP_IPV6_WHEREAREYOU = 33 ; IPv6 where-are-you +ICMP_IPV6_IAMHERE = 34 ; IPv6 i-am-here +ICMP_MOBILE_REGREQUEST = 35 ; mobile registration req +ICMP_MOBILE_REGREPLY = 36 ; mobile registreation reply +ICMP_SKIP = 39 ; SKIP -ICMP_PHOTURIS equ 40 ; Photuris -ICMP_PHOTURIS_UNKNOWN_INDEX equ 1 ; unknown sec index -ICMP_PHOTURIS_AUTH_FAILED equ 2 ; auth failed -ICMP_PHOTURIS_DECRYPT_FAILED equ 3 ; decrypt failed +ICMP_PHOTURIS = 40 ; Photuris +ICMP_PHOTURIS_UNKNOWN_INDEX = 1 ; unknown sec index +ICMP_PHOTURIS_AUTH_FAILED = 2 ; auth failed +ICMP_PHOTURIS_DECRYPT_FAILED = 3 ; decrypt failed -virtual at 0 - ICMP_Packet: - .Type db ? - .Code db ? - .Checksum dw ? - .Identifier dw ? - .SequenceNumber dw ? - .Data: -end virtual \ No newline at end of file +struct ICMP_header + Type db ? + Code db ? + Checksum dw ? + Identifier dw ? + SequenceNumber dw ? +ends \ No newline at end of file diff --git a/programs/network/icmp/ping.asm b/programs/network/icmp/ping.asm index 9cdc285519..06f303f856 100644 --- a/programs/network/icmp/ping.asm +++ b/programs/network/icmp/ping.asm @@ -12,8 +12,6 @@ ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; TODO: ttl, user selectable size/number of packets - format binary as "" BUFFERSIZE = 1500 @@ -28,16 +26,18 @@ use32 dd I_END ; initialized size dd IM_END+0x1000 ; required memory dd IM_END+0x1000 ; stack pointer - dd s ; parameters + dd params ; parameters dd 0 ; path include '../../proc32.inc' include '../../macros.inc' purge mov,add,sub include '../../dll.inc' +include '../../struct.inc' include '../../network.inc' include 'icmp.inc' +include 'ip.inc' START: @@ -53,13 +53,28 @@ START: push 1 call [con_start] push title - push 25 + push 250 push 80 push 25 push 80 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 - cmp byte[s], 0 + cmp byte[params], 0 jne parse_param push str_welcome @@ -69,8 +84,8 @@ main: push str_prompt call [con_write_asciiz] ; read string - mov esi, s - push 256 + mov esi, params + push 1024 push esi call [con_gets] ; check for exit @@ -93,10 +108,14 @@ main: mov [stats.time], 0 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 - mov esi, s + mov esi, params mov ecx, 1024 .addrloop: lodsb @@ -122,6 +141,42 @@ parse_param: jne @f mov [count], -1 ; infinite 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 .invalid: @@ -135,7 +190,7 @@ parse_param: push esp ; fourth parameter push 0 ; third parameter push 0 ; second parameter - push s ; first parameter + push params ; first parameter call [getaddrinfo] pop esi ; test for error @@ -166,9 +221,19 @@ parse_param: mov [socketnum], eax 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 -; call [con_cls] push str3 call [con_write_asciiz] @@ -176,9 +241,10 @@ parse_param: push [ip_ptr] call [con_write_asciiz] - push (icmp_packet.length - ICMP_Packet.Data) + push [size] push str3b call [con_printf] + add esp, 2*4 mainloop: call [con_get_flags] @@ -188,9 +254,14 @@ mainloop: inc [stats.tx] mcall 26, 10 ; Get high precision timer count 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 sub eax, [time_reference] jz @f @@ -203,54 +274,102 @@ mainloop: @@: mov [time_reference], eax +; Receive reply mcall recv, [socketnum], buffer_ptr, BUFFERSIZE, MSG_DONTWAIT cmp eax, -1 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 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 -; OK, we have a response, update stats and let the user know - inc [stats.rx] - mov eax, [time_reference] - 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] +; Validate the packet + add esi, sizeof.ICMP_header + mov ecx, [size] mov edi, icmp_packet.data repe cmpsb 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] xor edx, edx mov ebx, 10 div ebx push edx push eax -; movzx eax, word[buffer_ptr + ICMP_Packet.SequenceNumber] -; push eax push [recvd] push str7 call [con_printf] + add esp, 5*4 jmp .continue + + .ttl_exceeded: + push str14 + call [con_write_asciiz] + + jmp .continue + + ; Error in packet, print it to user .miscomp: - sub edi, icmp_packet.data + sub edi, icmp_packet.data+1 push edi push str9 call [con_printf] + add esp, 2*4 jmp .continue ; Invalid reply @@ -271,14 +390,14 @@ mainloop: cmp [count], -1 je .forever dec [count] - jz done + jz .stats .forever: - mcall 5, 100 ; wait a second - +; wait a second before sending next request + mcall 5, 100 jmp mainloop -; Done.. -done: +; Print statistics + .stats: cmp [stats.rx], 0 jne @f xor eax, eax @@ -298,6 +417,7 @@ done: push [stats.tx] push str12 call [con_printf] + add esp, 5*4 jmp main ; DNS error @@ -320,24 +440,61 @@ exit_now: 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 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 - 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 str3 db 'Pinging to ',0 str3b db ' with %u data bytes',10,0 str4 db 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 -str11 db 'Answer: ',0 -str7 db 'bytes=%u time=%u.%u ms',10,0 +str11 db 'Answer from %u.%u.%u.%u: ',0 +str7 db 'bytes=%u time=%u.%u ms TTL=%u',10,0 str8 db 'Timeout',10,0 -str9 db 'Miscompare at offset %u',10,0 -str10 db 'Invalid reply',10,0 +str9 db 'miscompare at offset %u.',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 @@ -350,6 +507,9 @@ sockaddr1: time_reference dd ? ip_ptr dd ? count dd ? +size dd ? +ttl dd ? +timeout dd ? recvd dd ? ; received number of bytes in last packet stats: @@ -381,18 +541,17 @@ import console, \ socketnum dd ? -icmp_packet db 8 ; type +icmp_packet db ICMP_ECHO ; type db 0 ; code - dw 0 ; + dw 0 ; checksum .id dw IDENTIFIER ; identifier .seq dw 0x0000 ; sequence number .data db 'abcdefghijklmnopqrstuvwxyz012345' - .length = $ - icmp_packet I_END: + rb 65504-32 -s db 0 - rb 1024 -buffer_ptr rb BUFFERSIZE +params rb 1024 +buffer_ptr: rb BUFFERSIZE IM_END: diff --git a/programs/network/zeroconf/zeroconf.asm b/programs/network/zeroconf/zeroconf.asm index 92fe31ec09..caf5a42c90 100644 --- a/programs/network/zeroconf/zeroconf.asm +++ b/programs/network/zeroconf/zeroconf.asm @@ -20,7 +20,7 @@ format binary as "" ; CONFIGURATION -TIMEOUT = 3 ; in seconds +TIMEOUT = 5 ; in seconds BUFFER = 1024 ; in bytes DHCP_TRIES = 3 ; number of times to try contacting DHCP server __DEBUG__ = 1 ; enable/disable @@ -318,8 +318,8 @@ dhcp: pushd [ebp + interface.number] pushd 4 ; length of option - pushd 1 shl 9 ; SO_BINDTODEVICE - pushd 0 ; SOL_SOCKET + pushd SO_BINDTODEVICE + pushd SOL_SOCKET mcall 75, 8, [ebp + interface.socketNum], esp add esp, 16 cmp eax, -1