;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;                                                                 ;;
;; Copyright (C) KolibriOS team 2012-2013. All rights reserved.    ;;
;; Distributed under terms of the GNU General Public License       ;;
;;                                                                 ;;
;;  IPv6.INC                                                       ;;
;;                                                                 ;;
;;  Part of the tcp/ip network stack for KolibriOS                 ;;
;;                                                                 ;;
;;    Written by hidnplayr@kolibrios.org                           ;;
;;                                                                 ;;
;;          GNU GENERAL PUBLIC LICENSE                             ;;
;;             Version 2, June 1991                                ;;
;;                                                                 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

$Revision: 3251 $


struct  IPv6_header

        VersionTrafficFlow      dd ?    ; Version[0-3], Traffic class[4-11], Flow Label [12-31]
        PayloadLength           dw ?    ; 16 bits, unsigned length of payload (extension headers are part of this)
        NextHeader              db ?    ; Values are same as in IPv4 'Protocol' field
        HopLimit                db ?    ; Decremented by every node, packet is discarded when it reaches 0
        SourceAddress           rd 4    ; 128-bit addresses
        DestinationAddress      rd 4    ;
        Payload                 rb 0

ends


uglobal
align 4

        IPv6:
        .addresses      rd 4*NET_DEVICES_MAX
        .subnet         rd 4*NET_DEVICES_MAX
        .dns            rd 4*NET_DEVICES_MAX
        .gateway        rd 4*NET_DEVICES_MAX

        .packets_tx     rd NET_DEVICES_MAX
        .packets_rx     rd NET_DEVICES_MAX

endg


;-----------------------------------------------------------------
;
; IPv6_init
;
;  This function resets all IP variables
;
;-----------------------------------------------------------------
macro   IPv6_init {

        xor     eax, eax
        mov     edi, IPv6
        mov     ecx, (4*4*4+2*4)MAX_IP
        rep stosd

}



;-----------------------------------------------------------------
;
; IPv6_input:
;
;  Will check if IPv6 Packet isnt damaged
;  and call appropriate handler. (TCP/UDP/ICMP/..)
;
;  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 IPv6 header in edx
;       size of IPv6 packet in ecx
;  OUT: /
;
;-----------------------------------------------------------------
align 4
IPv6_input:

        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv6_input from: %x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x\n",\
        [edx + IPv6_header.SourceAddress + 0]:2,[edx + IPv6_header.SourceAddress + 1]:2,\
        [edx + IPv6_header.SourceAddress + 2]:2,[edx + IPv6_header.SourceAddress + 3]:2,\
        [edx + IPv6_header.SourceAddress + 4]:2,[edx + IPv6_header.SourceAddress + 5]:2,\
        [edx + IPv6_header.SourceAddress + 6]:2,[edx + IPv6_header.SourceAddress + 7]:2,\
        [edx + IPv6_header.SourceAddress + 8]:2,[edx + IPv6_header.SourceAddress + 9]:2,\
        [edx + IPv6_header.SourceAddress + 10]:2,[edx + IPv6_header.SourceAddress + 11]:2,\
        [edx + IPv6_header.SourceAddress + 12]:2,[edx + IPv6_header.SourceAddress + 13]:2,\
        [edx + IPv6_header.SourceAddress + 14]:2,[edx + IPv6_header.SourceAddress + 15]:2

        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv6_input to: %x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x\n",\
        [edx + IPv6_header.DestinationAddress + 0]:2,[edx + IPv6_header.DestinationAddress + 1]:2,\
        [edx + IPv6_header.DestinationAddress + 2]:2,[edx + IPv6_header.DestinationAddress + 3]:2,\
        [edx + IPv6_header.DestinationAddress + 4]:2,[edx + IPv6_header.DestinationAddress + 5]:2,\
        [edx + IPv6_header.DestinationAddress + 6]:2,[edx + IPv6_header.DestinationAddress + 7]:2,\
        [edx + IPv6_header.DestinationAddress + 8]:2,[edx + IPv6_header.DestinationAddress + 9]:2,\
        [edx + IPv6_header.DestinationAddress + 10]:2,[edx + IPv6_header.DestinationAddress + 11]:2,\
        [edx + IPv6_header.DestinationAddress + 12]:2,[edx + IPv6_header.DestinationAddress + 13]:2,\
        [edx + IPv6_header.DestinationAddress + 14]:2,[edx + IPv6_header.DestinationAddress + 15]:2

        sub     ecx, sizeof.IPv6_header
        jb      .dump

        cmp     cx, [edx + IPv6_header.PayloadLength]
        jb      .dump

;-------------------------------------------------------------------
; No, it's just a regular IP packet, pass it to the higher protocols

  .handle_it:
        movzx   ecx, [edx + IPv6_header.PayloadLength]
        lea     edi, [edx + IPv6_header.SourceAddress]          ; make edi ptr to source and dest IPv6 address
        lea     esi, [edx + IPv6_header.Payload]                ; make esi ptr to data
        mov     al, [edx + IPv6_header.NextHeader]

  .scan:
        cmp     al, 59  ; no next
        je      .dump

        cmp     al, 0
        je      .hop_by_hop

        cmp     al, 43
        je      .routing

        cmp     al, 44
        je      .fragment

        cmp     al, 60
        je      .dest_opts

;        cmp     al, IP_PROTO_TCP
;        je      TCP_input

;        cmp     al, IP_PROTO_UDP
;        je      UDP_input

;        cmp     al, 58
;        je      ICMP6_input

        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv6_input - unknown protocol: %u\n", al

  .dump:
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv6_input - dumping\n"
        call    kernel_free
        add     esp, 4

        ret

  .dump_options:
        add     esp, 2+4+4
        jmp     .dump

  .nextheader:
        pop     esi
        pop     ecx
        pop     ax
        jmp     .scan

;-------------------------
; Hop-by-Hop

  .hop_by_hop:
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv6_input - hop by hop\n"
        pushw   [esi]                   ; 8 bit identifier for option type
        movzx   eax, byte[esi + 1]      ; Hdr Ext Len
        inc     eax                     ; first 8 octets not counted
        shl     eax, 3                  ; * 8
        sub     ecx, eax
        push    ecx
        add     eax, esi
        push    eax
        inc     esi
        inc     esi

        mov     al, [esi]

        cmp     al, 0
        je      .pad_1

        cmp     al, 1
        je      .pad_n

        ; TODO: check with other known options

; unknown option.. discard packet or not?
; check highest two bits
        test    al, 0xc0        ; discard packet
        jnz     .dump_options

  .pad_n:
        movzx   eax, byte[esi + 1]
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv6_input - pad %u\n", eax
        inc     esi
        inc     esi
        add     esi, eax
        sub     ecx, eax
        jmp     .hop_by_hop

  .pad_1:
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv6_input - pad 1\n"
        inc     esi
        dec     ecx
        jmp     .hop_by_hop



  .dest_opts:
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv6_input - dest opts\n"
        jmp     .nextheader

  .routing:
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv6_input - routing\n"
        pushw   [esi]                   ; 8 bit identifier for option type
        movzx   eax, byte[esi + 1]      ; Hdr Ext Len
        inc     eax                     ; first 8 octets not counted
        shl     eax, 3                  ; * 8
        sub     ecx, eax
        push    ecx
        add     eax, esi
        push    eax
        inc     esi
        inc     esi

        cmp     al, 0
        je      .pad_1

        cmp     al, 1
        je      .pad_n

        mov     al, [esi]       ; routing type

        jmp     .nextheader

  .fragment:
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv6_input - fragment\n"

        jmp     .nextheader






;---------------------------------------------------------------------------
;
; IPv6_API
;
; This function is called by system function 75
;
; IN:  subfunction number in bl
;      device number in bh
;      ecx, edx, .. depends on subfunction
;
; OUT:
;
;---------------------------------------------------------------------------
align 4
IPv6_api:

        movzx   eax, bh
        shl     eax, 2

        and     ebx, 0x000000ff
        cmp     ebx, .number
        ja      .error
        jmp     dword [.table + 4*ebx]

  .table:
        dd      .packets_tx     ; 0
        dd      .packets_rx     ; 1
;        dd      .read_ip        ; 2
;        dd      .write_ip       ; 3
;        dd      .read_dns       ; 4
;        dd      .write_dns      ; 5
;        dd      .read_subnet    ; 6
;        dd      .write_subnet   ; 7
;        dd      .read_gateway   ; 8
;        dd      .write_gateway  ; 9
  .number = ($ - .table) / 4 - 1

  .error:
        mov     eax, -1
        ret

  .packets_tx:
        mov     eax, [IPv6.packets_tx + eax]
        ret

  .packets_rx:
        mov     eax, [IPv6.packets_rx + eax]
        ret