From eda11ddd3633454440bed976643dc920c289e762 Mon Sep 17 00:00:00 2001 From: hidnplayr Date: Tue, 17 Jul 2012 21:36:34 +0000 Subject: [PATCH] Getting ready for better IP routing git-svn-id: svn://kolibrios.org@2877 a494cfbc-eb01-0410-851d-a64ba20cac60 --- kernel/branches/net/network/ARP.inc | 30 +++------- kernel/branches/net/network/IPv4.inc | 69 +++++++++++----------- kernel/branches/net/network/icmp.inc | 30 ++++------ kernel/branches/net/network/socket.inc | 31 +++++++++- kernel/branches/net/network/stack.inc | 6 +- kernel/branches/net/network/tcp_output.inc | 3 +- kernel/branches/net/network/tcp_subr.inc | 4 +- kernel/branches/net/network/udp.inc | 15 ++--- 8 files changed, 97 insertions(+), 91 deletions(-) diff --git a/kernel/branches/net/network/ARP.inc b/kernel/branches/net/network/ARP.inc index 726522a5c2..257297f9b4 100644 --- a/kernel/branches/net/network/ARP.inc +++ b/kernel/branches/net/network/ARP.inc @@ -282,6 +282,7 @@ ARP_input: ; ARP_output_request ; ; IN: ip in eax +; device in edi ; OUT: / ; ;--------------------------------------------------------------------------- @@ -290,7 +291,6 @@ ARP_output_request: DEBUGF 1,"Create ARP Packet\n" - call IPv4_dest_to_dev push eax ; DestIP pushd [IP_LIST+edi] ; SenderIP @@ -441,9 +441,11 @@ ARP_del_entry: ; This function translates an IP address to a MAC address ; ; IN: eax = IPv4 address +; edi = device number ; OUT: eax = -1 on error, -2 means request send ; else, ax = first two bytes of mac (high 16 bits of eax will be 0) ; ebx = last four bytes of mac +; edi = unchanged ; ;----------------------------------------------------------------- align 4 @@ -457,27 +459,9 @@ ARP_IP_to_MAC: cmp eax, 0xffffffff je .broadcast -; if ((Remote IP & subnet_mask) == (local IP & subnet_mask )) -; destination is on same subnet -; else, destination is remote and must use a gateway - - call IPv4_dest_to_dev - mov ebx, [IP_LIST + edi] - and ebx, [SUBNET_LIST + edi] - - mov ecx, eax - and ecx, [SUBNET_LIST + edi] - - cmp ecx, ebx - je .local - - mov eax, [GATEWAY_LIST + edi] - DEBUGF 1,"requested IP is not on subnet, using default gateway\n" - ;-------------------------------- ; Try to find the IP in ARP_table - .local: mov ecx, [NumARP] test ecx, ecx jz .not_in_list @@ -494,7 +478,7 @@ ARP_IP_to_MAC: ;-------------------- ; Send an ARP request - push eax ; save IP for ARP_output_request + push eax edi ; save IP for ARP_output_request ; Now create the ARP entry pushw ARP_REQUEST_TTL ; TTL @@ -510,7 +494,7 @@ ARP_IP_to_MAC: je .full ; And send a request - pop eax + pop edi eax call ARP_output_request ; IP in eax ;; TODO: check if driver could transmit packet @@ -523,7 +507,7 @@ ARP_IP_to_MAC: jne .invalid movzx eax, word [esi + ARP_entry.MAC] - mov ebx, dword[esi + ARP_entry.MAC+2] + mov ebx, dword[esi + ARP_entry.MAC + 2] ret .invalid: @@ -532,7 +516,7 @@ ARP_IP_to_MAC: .full: DEBUGF 1,"ARP table is full!\n" - pop eax + add esp, 8 mov eax, -1 ret diff --git a/kernel/branches/net/network/IPv4.inc b/kernel/branches/net/network/IPv4.inc index fff7f6630b..2bb2aa8eed 100644 --- a/kernel/branches/net/network/IPv4.inc +++ b/kernel/branches/net/network/IPv4.inc @@ -556,9 +556,9 @@ IPv4_find_fragment_slot: ; IPv4_output ; ; IN: eax = dest ip -; ebx = source ip +; ebx = output device ptr/0 for automatic choice ; ecx = data length -; dx = fragment id +; edx = source ip ; di = TTL shl 8 + protocol ; ; OUT: eax = pointer to buffer start @@ -576,38 +576,36 @@ IPv4_output: cmp ecx, 65500 ; Max IPv4 packet size ja .too_large - push ecx eax ebx dx di + push ecx eax edx di + call IPv4_dest_to_dev ; outputs device number in edi, dest ip in eax call ARP_IP_to_MAC - test eax, 0xffff0000 ; error bits jnz .arp_error - - push ebx ; push the mac + push ebx ; push the mac onto the stack push ax - call IPv4_dest_to_dev - inc [IP_PACKETS_TX+edi] - mov ebx, [NET_DRV_LIST+edi] + inc [IP_PACKETS_TX + edi] ; update stats + + mov ebx, [NET_DRV_LIST + edi] lea eax, [ebx + ETH_DEVICE.mac] mov edx, esp - mov ecx, [esp + 18] + mov ecx, [esp + 10 + 6] add ecx, sizeof.IPv4_header - mov di , ETHER_IPv4 + mov di, ETHER_IPv4 call ETH_output jz .eth_error + add esp, 6 ; pop the mac out of the stack - add esp, 6 ; pop the mac - + xchg cl, ch ; internet byte order mov [edi + IPv4_header.VersionAndIHL], 0x45 ; IPv4, normal length (no Optional header) mov [edi + IPv4_header.TypeOfService], 0 ; nothing special, just plain ip packet mov [edi + IPv4_header.TotalLength], cx - rol [edi + IPv4_header.TotalLength], 8 ; internet byte order - mov [edi + IPv4_header.FlagsAndFragmentOffset], 0x0000 - mov [edi + IPv4_header.HeaderChecksum], 0 + mov [edi + IPv4_header.Identification], 0 ; fragment id: FIXME + mov [edi + IPv4_header.FlagsAndFragmentOffset], 0 pop word [edi + IPv4_header.TimeToLive] ; ttl shl 8 + protocol ; [edi + IPv4_header.Protocol] - popw [edi + IPv4_header.Identification] ; fragment id + mov [edi + IPv4_header.HeaderChecksum], 0 popd [edi + IPv4_header.SourceAddress] popd [edi + IPv4_header.DestinationAddress] @@ -620,19 +618,19 @@ IPv4_output: .eth_error: DEBUGF 1,"IPv4_output: ethernet error\n" - add esp, 3*4+2*2+6 - sub edi, edi + add esp, 3*4+2+6 + xor edi, edi ret .arp_error: DEBUGF 1,"IPv4_output: ARP error (0x%x)\n", eax - add esp, 4+4+4+2+2 - sub edi, edi + add esp, 3*4+2 + xor edi, edi ret .too_large: DEBUGF 1,"IPv4_output: error: Packet too large!\n" - sub edi, edi + xor edi, edi ret @@ -661,22 +659,20 @@ IPv4_output_raw: sub esp, 8 push esi eax + call IPv4_dest_to_dev call ARP_IP_to_MAC test eax, 0xffff0000 ; error bits jnz .arp_error - .continue: - - push ebx ; push the mac + push ebx ; push the mac push ax - call IPv4_dest_to_dev - inc [IP_PACKETS_TX+edi] - mov ebx, [NET_DRV_LIST+edi] + inc [IP_PACKETS_TX + edi] + mov ebx, [NET_DRV_LIST + edi] lea eax, [ebx + ETH_DEVICE.mac] mov edx, esp - mov ecx, [esp + 6+4] + mov ecx, [esp + 6 + 4] add ecx, sizeof.IPv4_header mov di, ETHER_IPv4 call ETH_output @@ -851,24 +847,23 @@ IPv4_fragment: ; ; IPv4_dest_to_dev ; -; IN: eax = Destination IP -; OUT: edi = device id * 4 +; IN: eax = Destination IP +; OUT: edi = device id * 4 +; eax = ip of gateway if nescessary, unchanged otherwise ; ;--------------------------------------------------------------------------- align 4 IPv4_dest_to_dev: cmp eax, 0xffffffff - je .invalid + je .broadcast xor edi, edi mov ecx, MAX_IP - .loop: mov ebx, [IP_LIST+edi] and ebx, [SUBNET_LIST+edi] jz .next - mov edx, eax and edx, [SUBNET_LIST+edi] @@ -880,11 +875,15 @@ IPv4_dest_to_dev: jnz .loop .invalid: - xor edi, edi ; if none found, use device 0 as default device + xor edi, edi ; if none found, use device 0 as default + mov eax, [GATEWAY_LIST] .found_it: DEBUGF 1,"IPv4_dest_to_dev: %u\n", edi + ret + .broadcast: + xor edi, edi ret diff --git a/kernel/branches/net/network/icmp.inc b/kernel/branches/net/network/icmp.inc index cc1062152d..e21bec5105 100644 --- a/kernel/branches/net/network/icmp.inc +++ b/kernel/branches/net/network/icmp.inc @@ -284,7 +284,6 @@ ICMP_input: ; ecx = data length ; dh = type ; dl = code -; high 16 bits of edx = fragment id (for IP header) ; esi = data offset ; edi = identifier shl 16 + sequence number ; @@ -294,42 +293,36 @@ ICMP_output: DEBUGF 1,"Creating ICMP Packet\n" - push esi edi edx + push esi edi dx - mov ebx, [eax + IP_SOCKET.LocalIP] + mov edx, [eax + IP_SOCKET.LocalIP] mov eax, [eax + IP_SOCKET.RemoteIP] add ecx, sizeof.ICMP_header - mov di , IP_PROTO_ICMP SHL 8 + 128 ; TTL - shr edx, 16 - + mov di, IP_PROTO_ICMP SHL 8 + 128 ; TTL call IPv4_output jz .exit DEBUGF 1,"full icmp packet size: %u\n", edx - pop eax - mov word [edi + ICMP_header.Type], ax ; Write both type and code bytes at once - pop eax - mov [edi + ICMP_header.SequenceNumber], ax - shr eax, 16 - mov [edi + ICMP_header.Identifier], ax + pop word [edi + ICMP_header.Type] ; Write both type and code bytes at once + pop dword [edi + ICMP_header.Identifier] ; identifier and sequence number mov [edi + ICMP_header.Checksum], 0 - push eax ebx ecx edx + push ebx ecx edx mov esi, edi xor edx, edx call checksum_1 call checksum_2 mov [edi + ICMP_header.Checksum], dx - pop edx ecx ebx eax esi + pop edx ecx ebx esi sub ecx, sizeof.ICMP_header add edi, sizeof.ICMP_header push cx - shr cx , 2 + shr cx, 2 rep movsd pop cx - and cx , 3 + and cx, 3 rep movsb sub edi, edx ;;; TODO: find a better way to remember start of packet @@ -339,7 +332,7 @@ ICMP_output: ret .exit: DEBUGF 1,"Creating ICMP Packet failed\n" - add esp, 3*4 + add esp,2*4+2 ret @@ -362,8 +355,7 @@ ICMP_output_raw: push edx mov di, IP_PROTO_ICMP SHL 8 + 128 ; TTL - shr edx, 16 - mov ebx, [eax + IP_SOCKET.LocalIP] + mov edx, [eax + IP_SOCKET.LocalIP] mov eax, [eax + IP_SOCKET.RemoteIP] call IPv4_output jz .exit diff --git a/kernel/branches/net/network/socket.inc b/kernel/branches/net/network/socket.inc index b9adbd514c..ab2add9839 100644 --- a/kernel/branches/net/network/socket.inc +++ b/kernel/branches/net/network/socket.inc @@ -29,6 +29,7 @@ struct SOCKET Type dd ? ; RAW/STREAM/DGRAP Protocol dd ? ; ICMP/IPv4/ARP/TCP/UDP errorcode dd ? + device dd ? options dd ? state dd ? @@ -925,7 +926,7 @@ SOCKET_get_opt: ; ; IN: ecx = socket number ; edx = pointer to the options: -; dd level, optname, optval, optlen +; dd level, optname, optlen, optval ; OUT: -1 on error ; ;----------------------------------------------------------------- @@ -937,8 +938,36 @@ SOCKET_set_opt: call SOCKET_num_to_ptr jz s_error + cmp dword [edx], SOL_SOCKET + jne s_error + cmp dword [edx+4], SO_BINDTODEVICE + je .bind + jmp s_error + + .bind: + cmp dword [edx+8], 0 + je .unbind + + movzx edx, byte [edx + 9] + cmp edx, MAX_NET_DEVICES + ja s_error + + mov edx, [NET_DRV_LIST + 4*edx] + test edx, edx + jz s_error + mov [eax + SOCKET.device], edx + + DEBUGF 1,"Bound socket %x to device %x\n",eax, edx + + mov dword [esp+32], 0 ; success! + ret + + .unbind: + mov [eax + SOCKET.device], 0 + + mov dword [esp+32], 0 ; success! ret diff --git a/kernel/branches/net/network/stack.inc b/kernel/branches/net/network/stack.inc index d950a5e3d9..95e19e2593 100644 --- a/kernel/branches/net/network/stack.inc +++ b/kernel/branches/net/network/stack.inc @@ -1,6 +1,6 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; -;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;; +;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;; ;; Distributed under terms of the GNU General Public License ;; ;; ;; ;; STACK.INC ;; @@ -70,6 +70,10 @@ SO_OOBINLINE = 1 shl 5 SO_REUSEADDR = 1 shl 6 SO_REUSEPORT = 1 shl 7 SO_USELOOPBACK = 1 shl 8 +SO_BINDTODEVICE = 1 shl 9 + +; Socket level +SOL_SOCKET = 0 ; Socket States diff --git a/kernel/branches/net/network/tcp_output.inc b/kernel/branches/net/network/tcp_output.inc index e69baf0541..ecba2ab0ab 100644 --- a/kernel/branches/net/network/tcp_output.inc +++ b/kernel/branches/net/network/tcp_output.inc @@ -421,7 +421,8 @@ TCP_output: mov ecx, esi - mov ebx, [eax + IP_SOCKET.LocalIP] ; source ip + mov ebx, [eax + SOCKET.device] + mov edx, [eax + IP_SOCKET.LocalIP] ; source ip mov eax, [eax + IP_SOCKET.RemoteIP] ; dest ip mov di, IP_PROTO_TCP shl 8 + 128 call IPv4_output diff --git a/kernel/branches/net/network/tcp_subr.inc b/kernel/branches/net/network/tcp_subr.inc index b9ae34bc70..dd5aec4ea8 100644 --- a/kernel/branches/net/network/tcp_subr.inc +++ b/kernel/branches/net/network/tcp_subr.inc @@ -330,9 +330,9 @@ TCP_respond_socket: push cx ebx mov eax, [ebx + IP_SOCKET.RemoteIP] - mov ebx, [ebx + IP_SOCKET.LocalIP] + mov edx, [ebx + IP_SOCKET.LocalIP] mov ecx, sizeof.TCP_header - mov di , IP_PROTO_TCP shl 8 + 128 + mov di, IP_PROTO_TCP shl 8 + 128 call IPv4_output test edi, edi jz .error diff --git a/kernel/branches/net/network/udp.inc b/kernel/branches/net/network/udp.inc index cd32df9fde..2360607e1f 100644 --- a/kernel/branches/net/network/udp.inc +++ b/kernel/branches/net/network/udp.inc @@ -1,6 +1,6 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; -;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;; +;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;; ;; Distributed under terms of the GNU General Public License ;; ;; ;; ;; UDP.INC ;; @@ -242,18 +242,15 @@ UDP_output: DEBUGF 1,"local port: %u\n", dx rol dx, 8 - mov ebx, [eax + IP_SOCKET.LocalIP] - mov eax, [eax + IP_SOCKET.RemoteIP] - - mov di, IP_PROTO_UDP shl 8 + 128 sub esp, 8 ; Data ptr and data size will be placed here - add ecx, sizeof.UDP_header - -;;; TODO: fragment id push edx esi + mov ebx, [eax + SOCKET.device] + mov edx, [eax + IP_SOCKET.LocalIP] + mov eax, [eax + IP_SOCKET.RemoteIP] + mov di, IP_PROTO_UDP shl 8 + 128 + add ecx, sizeof.UDP_header call IPv4_output jz .fail - mov [esp + 8], eax ; pointer to buffer start mov [esp + 8 + 4], edx ; buffer size