Subversion Repositories Kolibri OS

Rev

Rev 1166 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2008. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;  IP.INC                                                         ;;
  7. ;;                                                                 ;;
  8. ;;  Part of the tcp/ip network stack for KolibriOS                 ;;
  9. ;;                                                                 ;;
  10. ;;  Based on the work of [Johnny_B] and [smb]                      ;;
  11. ;;                                                                 ;;
  12. ;;    Written by hidnplayr@kolibrios.org                           ;;
  13. ;;                                                                 ;;
  14. ;;          GNU GENERAL PUBLIC LICENSE                             ;;
  15. ;;             Version 2, June 1991                                ;;
  16. ;;                                                                 ;;
  17. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  18.  
  19. $Revision: 922 $
  20.  
  21. ; IP underlying protocols numbers
  22.  
  23. ETHER_IPv4      equ 0x0008      ; Reversed from 0800 for intel
  24.  
  25. MAX_FRAGMENTS   equ 16
  26. MAX_IP          equ MAX_NET_DEVICES
  27.  
  28. struct  IPv4_Packet
  29.         .VersionAndIHL          db  ?  ; Version[0-3 bits] and IHL(header length)[4-7 bits]
  30.         .TypeOfService          db  ?
  31.         .TotalLength            dw  ?
  32.         .Identification         dw  ?
  33.         .FlagsAndFragmentOffset dw  ?  ; Flags[0-2] and FragmentOffset[3-15]
  34.         .TimeToLive             db  ?  ;
  35.         .Protocol               db  ?
  36.         .HeaderChecksum         dw  ?
  37.         .SourceAddress          dd  ?
  38.         .DestinationAddress     dd  ?
  39.         .DataOrOptional:
  40. ends
  41.  
  42. struct  FRAGMENT_slot
  43.         .ttl                    dw  ?  ; Time to live for this entry, 0 for empty slot's
  44.         .id                     dw  ?  ; Identification field from IP header
  45.         .SrcIP                  dd  ?  ; .. from IP header
  46.         .DstIP                  dd  ?  ; .. from IP header
  47.         .ptr                    dd  ?  ; Pointer to first packet
  48.         .size:
  49. ends
  50.  
  51. struct  FRAGMENT_entry                 ; This structure will replace the ethernet header in fragmented ip packets
  52.         .PrevPtr                dd  ?  ; Pointer to previous fragment entry  (-1 for first packet)
  53.         .NextPtr                dd  ?  ; Pointer to next fragment entry (-1 for last packet)
  54.         .Owner                  dd  ?  ; Pointer to structure of driver
  55.                                 rb  2  ; to match ethernet header size
  56.         .Data:                         ; Ip header begins here (we will need the IP header to re-construct the complete packet)
  57. ends
  58.  
  59. align 4
  60. uglobal
  61.         BROADCAST       dd  ?
  62.         IP_LIST         rd  MAX_IP
  63.         SUBNET_LIST     rd  MAX_IP
  64.         DNS_LIST        rd  MAX_IP
  65.         GATEWAY_LIST    rd  MAX_IP
  66.         IP_PACKETS_TX   rd  MAX_IP
  67.         IP_PACKETS_RX   rd  MAX_IP
  68.         FRAGMENT_LIST   rb  MAX_FRAGMENTS*FRAGMENT_slot.size
  69. endg
  70.  
  71.  
  72. ;-----------------------------------------------------------------
  73. ;
  74. ; IPv4_init
  75. ;
  76. ;  This function resets all IP variables
  77. ;
  78. ;  IN:  /
  79. ;  OUT: /
  80. ;
  81. ;-----------------------------------------------------------------
  82.  
  83. align 4
  84. IPv4_init:
  85.  
  86.         or      eax, -1
  87.         mov     edi, BROADCAST
  88.         mov     ecx, 1+4*MAX_IP
  89.         rep     stosd
  90.  
  91.         xor     eax, eax
  92.         mov     edi, FRAGMENT_LIST
  93.         mov     ecx, FRAGMENT_slot.size*MAX_FRAGMENTS/4 + 2*MAX_IP
  94.         rep     stosd
  95.  
  96.         ret
  97.  
  98.  
  99.  
  100. ;-----------------------------------------------------------------
  101. ;
  102. ; IP_Handler:
  103. ;
  104. ;  Called by eth_handler,
  105. ;  will check if IP Packet isnt damaged
  106. ;  and call appropriate handler. (TCP/UDP/ICMP/..)
  107. ;
  108. ;  It will also re-construct fragmented packets
  109. ;
  110. ;  IN:  Pointer to buffer in [esp]
  111. ;       size of buffer in [esp+4]
  112. ;       pointer to device struct in ebx
  113. ;       pointer to IP Packet data in edx
  114. ;  OUT: /
  115. ;
  116. ;-----------------------------------------------------------------
  117.  
  118. align 4
  119. IPv4_Handler:
  120.  
  121.         DEBUGF  1,"IP_Handler - start\n"
  122.         mov     cx , [edx + IPv4_Packet.HeaderChecksum]
  123.         xchg    ch , cl                                         ; Get the checksum in intel format
  124.  
  125.         mov     word [edx + IPv4_Packet.HeaderChecksum], 0      ; Clear checksum field to recalculating checksum
  126.  
  127.         movzx   eax, byte [edx + IPv4_Packet.VersionAndIHL]     ; Calculate Header length by using IHL field
  128.         and     eax, 0x0000000F  ;
  129.         shl     eax, 2           ;
  130.  
  131.         push    edx
  132.         stdcall checksum_jb, edx, eax                           ; buf_ptr, buf_size
  133.         pop     edx
  134.         cmp     cx , ax
  135.         jnz     .dump                                           ; if CHECKSUM isn't valid then dump Packet
  136.  
  137.         mov     eax, [edx + IPv4_Packet.DestinationAddress]
  138.         mov     edi, BROADCAST
  139.         mov     ecx, MAX_IP+1
  140.         repnz   scasd
  141.         jz      .ip_ok
  142.  
  143.         not     eax
  144.         test    eax, 127 shl 24 ; 127.x.x.x
  145.         jz      .ip_ok
  146.  
  147. ;  TODO: we need to check for broadcasts (other then 255.255.255.255)
  148.  
  149.         jmp     .dump
  150.  
  151.   .ip_ok:
  152.         call    ETH_struc2dev                                   ; TODO: make this work on other protocols too!
  153.         inc     [IP_PACKETS_RX+4*edi]
  154.         DEBUGF  1,"IP_Handler - packet from %u.%u.%u.%u\n",\
  155.         [edx + IPv4_Packet.SourceAddress]:1,[edx + IPv4_Packet.SourceAddress + 1]:1,[edx + IPv4_Packet.SourceAddress + 2]:1,[edx + IPv4_Packet.SourceAddress + 3]:1
  156.  
  157.         mov     al , [edx + IPv4_Packet.VersionAndIHL]
  158.         and     al , 0x0f                                       ; get IHL(header length)
  159.         cmp     al , 0x05                                       ; IHL!= 5*4(20 bytes)
  160.         jnz     .dump                                           ; TODO: dont dump packets wich have optional fiels !!!                   /!\
  161.  
  162.         cmp     byte [edx + IPv4_Packet.TimeToLive], 0
  163.         je      .dump
  164.  
  165.         movzx   eax, word [edx + IPv4_Packet.FlagsAndFragmentOffset]
  166.         xchg    al , ah
  167.  
  168.         test    ax , 1 shl 13                                   ; Is 'more fragments' flag set ?
  169.         jnz     .yes_fragments                                  ; If so, we definately have a fragmented packet
  170.  
  171.         test    ax , 0x1fff                                     ; If flag is not set, but there is a fragment offset, the packet is last in series of fragmented packets
  172.         jnz     .last_fragment
  173.  
  174.    .handle_it:                                                  ; We reach here if packet hasnt been fragmented, or when it already has been re-constructed
  175.         movzx   eax, byte [edx + IPv4_Packet.VersionAndIHL]     ; Calculate Header length by using IHL field
  176.         and     eax, 0x0000000F                                 ;
  177.         shl     eax, 2                                          ;
  178.  
  179.         movzx   ecx, word [edx + IPv4_Packet.TotalLength]       ; Calculate length of encapsulated Packet
  180.         xchg    cl , ch                                         ;
  181.         sub     ecx, eax                                        ;
  182.  
  183.         add     eax, edx
  184.         push    eax
  185.         mov     al , [edx + IPv4_Packet.Protocol]
  186.         pop     edx                                             ; Offset to data (tcp/udp/icmp/.. Packet)
  187.  
  188.         cmp     al , IP_PROTO_TCP
  189. ;        je      TCP_Handler
  190.  
  191.         cmp     al , IP_PROTO_UDP
  192.         je      UDP_Handler
  193.  
  194.         cmp     al , IP_PROTO_ICMP
  195.         je      ICMP_Handler
  196.  
  197.         DEBUGF  1,"IP_Handler - unknown protocol:%u\n",al
  198.  
  199.   .dump:
  200.         DEBUGF  1,"IP_Handler - done\n"
  201. ;        inc     [dumped_rx_count]
  202.         call    kernel_free
  203.         add     esp, 4                                          ; pop (balance stack)
  204.         ret
  205.  
  206.  
  207.   .yes_fragments:
  208.         shl     ax , 3
  209.         DEBUGF  1,"Fragmented packet, offset:%u, id:%x\n", ax, [edx + IPv4_Packet.Identification]:4
  210.  
  211.         test    ax , ax                                         ; Is this the first packet of the fragment?
  212.         jnz     .not_first_fragment
  213.  
  214.         DEBUGF  1,"First fragmented packet received!\n"
  215.                                                                 ; try to locate a free slot..
  216.         mov     ecx, MAX_FRAGMENTS
  217.         mov     esi, FRAGMENT_LIST
  218.      .find_free_slot:
  219.         cmp     word [esi + FRAGMENT_slot.ttl], 0
  220.         je      .found_free_slot
  221.         add     esi, FRAGMENT_slot.size
  222.         loop    .find_free_slot
  223.         jmp     .dump                                           ; If no free slot was found, dump the packet
  224.  
  225.      .found_free_slot:                                          ; We found a free slot, let's fill in the FRAGMENT_slot structure
  226.         mov     word [esi + FRAGMENT_slot.ttl], 15              ; RFC recommends 15 secs as ttl
  227.         mov     ax , word [edx + IPv4_Packet.Identification]
  228.         mov     word [esi + FRAGMENT_slot.id], ax
  229.         mov     eax, dword [edx + IPv4_Packet.SourceAddress]
  230.         mov     dword [esi + FRAGMENT_slot.SrcIP], eax
  231.         mov     eax, dword [edx + IPv4_Packet.DestinationAddress]
  232.         mov     dword [esi + FRAGMENT_slot.DstIP], eax
  233.         pop     eax
  234.         mov     dword [esi + FRAGMENT_slot.ptr], eax
  235.                                                                 ; Now, replace ethernet header in original buffer with a FRAGMENT_entry structure
  236.         mov     [eax + FRAGMENT_entry.NextPtr], -1
  237.         mov     [eax + FRAGMENT_entry.PrevPtr], -1
  238.         mov     [eax + FRAGMENT_entry.Owner], ebx
  239.  
  240.         add     esp, 4                                          ; balance stack and exit
  241.         ret
  242.  
  243.  
  244.  
  245.   .not_first_fragment:
  246.         DEBUGF  1,"Middle fragmented packet received!\n"
  247.  
  248.         call    .find_fragment_slot
  249.         cmp     esi, -1
  250.         je      .dump
  251.  
  252.         mov     word [esi + FRAGMENT_slot.ttl], 15              ; Reset the ttl
  253.         mov     esi, [esi + FRAGMENT_slot.ptr]
  254.         or      edi, -1
  255.      .find_last_entry:                                          ; The following routine will try to find the last entry
  256.         cmp     edi, [esi + FRAGMENT_entry.PrevPtr]
  257.         jne     .destroy_slot                                   ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!)
  258.         mov     edi, esi
  259.         mov     esi, [esi + FRAGMENT_entry.NextPtr]
  260.         cmp     esi, -1
  261.         jne     .find_last_entry
  262.                                                                 ; We found the last entry (pointer is noww in edi)
  263.                                                                 ; We are going to overwrite the ethernet header in received packet with a FRAGMENT_entry structure
  264.  
  265.         pop     eax                                             ; pointer to packet
  266.         mov     [edi + FRAGMENT_entry.NextPtr], eax             ; update pointer of previous entry to the new entry
  267.         mov     [eax + FRAGMENT_entry.NextPtr], -1
  268.         mov     [eax + FRAGMENT_entry.PrevPtr], edi
  269.         mov     [eax + FRAGMENT_entry.Owner], ebx
  270.  
  271.         add     esp, 4
  272.         ret
  273.  
  274.  
  275.  
  276.   .last_fragment:
  277.         DEBUGF  1,"Last fragmented packet received!\n"
  278.         call    .find_fragment_slot
  279.         cmp     esi, -1
  280.         je      .dump
  281.  
  282.         mov     esi, [esi + FRAGMENT_slot.ptr]                  ; We found the first entry, let's calculate total size of the packet in eax, so we can allocate a buffer
  283.         push    esi
  284.         xor     eax, eax                                        ;
  285.         or      edi, -1
  286.      .count_bytes:
  287.         cmp     [esi + FRAGMENT_entry.PrevPtr], edi
  288.         jne     .destroy_slot_pop                                               ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!)
  289.         mov     cx, word [esi + FRAGMENT_entry.Data + IPv4_Packet.TotalLength]    ; Add total length
  290.         xchg    cl, ch
  291.         DEBUGF  1,"Packet size: %u\n", cx
  292.         add     ax, cx
  293.         movzx   cx, byte [esi + FRAGMENT_entry.Data + IPv4_Packet.VersionAndIHL]  ; Sub Header length
  294.         and     cx, 0x000F
  295.         shl     cx, 2
  296.         DEBUGF  1,"Header size: %u\n", cx
  297.         sub     ax, cx
  298.         mov     edi, esi
  299.         mov     esi, [esi + FRAGMENT_entry.NextPtr]
  300.         cmp     esi, -1
  301.         jne     .count_bytes
  302.  
  303.         mov     esi, [esp+4]  ;;;
  304.         mov     [edi + FRAGMENT_entry.NextPtr], esi                            ; Add this packet to the chain, this simplifies the following code
  305.         mov     [esi + FRAGMENT_entry.NextPtr], -1
  306.         mov     [esi + FRAGMENT_entry.PrevPtr], edi
  307.         mov     [esi + FRAGMENT_entry.Owner], ebx
  308.  
  309.         mov     cx, [edx + IPv4_Packet.TotalLength]                            ; Note: This time we dont substract Header length
  310.         xchg    cl , ch
  311.         DEBUGF  1,"Packet size: %u\n", cx
  312.         add     ax , cx
  313.         DEBUGF  1,"Total Received data size: %u\n", eax
  314.  
  315.         push    eax
  316.         mov     ax , [edx + IPv4_Packet.FlagsAndFragmentOffset]
  317.         xchg    al , ah
  318.         shl     ax , 3
  319.         add     cx , ax
  320.         pop     eax
  321.         DEBUGF  1,"Total Fragment size: %u\n", ecx
  322.  
  323.         cmp     ax, cx
  324.         jne     .destroy_slot_pop
  325.  
  326.         push    eax
  327.         push    eax
  328.         call    kernel_alloc
  329.         test    eax, eax
  330.         je      .destroy_slot_pop                                                       ; If we dont have enough space to allocate the buffer, discard all packets in slot
  331.         mov     edx, [esp+4]                                                            ; Get pointer to first fragment entry back in edx
  332.  
  333.      .rebuild_packet_loop:
  334.         movzx   ecx, word [edx + FRAGMENT_entry.Data + IPv4_Packet.FlagsAndFragmentOffset]      ; Calculate the fragment offset
  335.         xchg    cl , ch                                                                         ;   intel byte order
  336.         shl     cx , 3                                                                          ;   multiply by 8 and clear first 3 bits
  337.         DEBUGF  1,"Fragment offset: %u\n", cx
  338.  
  339.         lea     edi, [eax + ecx]                                                                ; Notice that edi will be equal to eax for first fragment
  340.         movzx   ebx, byte [edx + FRAGMENT_entry.Data + IPv4_Packet.VersionAndIHL]               ; Find header size (in ebx) of fragment
  341.         and     bx , 0x000F                                                                     ;
  342.         shl     bx , 2                                                                          ;
  343.  
  344.         lea     esi, [edx + FRAGMENT_entry.Data]                                                ; Set esi to the correct begin of fragment
  345.         movzx   ecx, word [edx + FRAGMENT_entry.Data + IPv4_Packet.TotalLength]                 ; Calculate total length of fragment
  346.         xchg    cl, ch                                                                          ;  intel byte order
  347.  
  348.         cmp     edi, eax                                                                        ; Is this packet the first fragment ?
  349.         je      .first_fragment
  350.         sub     cx, bx                                                                          ; If not, dont copy the header
  351.         add     esi, ebx                                                                        ;
  352.      .first_fragment:
  353.  
  354.         push    cx                                                                              ; First copy dword-wise, then byte-wise
  355.         shr     cx, 2                                                                           ;
  356.         rep     movsd                                                                           ;
  357.         pop     cx                                                                              ;
  358.         and     cx, 3                                                                           ;
  359.         rep     movsb                                                                           ;
  360.  
  361.         push    eax
  362.         push    edx                                                                             ; Push pointer to fragment onto stack
  363.         mov     edx, [edx + FRAGMENT_entry.NextPtr]                                             ; Set edx to the next pointer
  364.         call    kernel_free                                                                     ; free the previous fragment buffer (this uses the value from stack)
  365.         pop     eax
  366.         cmp     edx, -1                                                                         ; Check if it is last fragment in chain
  367.         jne     .rebuild_packet_loop
  368.  
  369.         pop     ecx                                                                             ;
  370.         xchg    cl, ch
  371.         mov     edx, eax
  372.         mov     word [edx + IPv4_Packet.TotalLength], cx
  373.         add     esp, 8
  374.  
  375.         xchg    cl, ch             ;  This prints the IP packet to the debug board (usefull when using serial output debug..)
  376.         push    ecx  ;;;;
  377.         push    eax     ;;;;
  378. ;        mov     esi, edx           ;
  379. ;                                   ;
  380. ;       @@:                         ;
  381. ;        lodsb                      ;
  382. ;        DEBUGF  1,"%x ", eax:2     ;
  383. ;        loop    @r                 ;
  384.  
  385.         movzx   eax, byte [edx + IPv4_Packet.VersionAndIHL]     ; Calculate Header length by using IHL field
  386.         and     ax, 0x000F                                      ;
  387.         shl     ax, 2                                           ;
  388.         sub     ecx, eax                                        ;
  389.         add     eax, edx
  390.         push    eax
  391.         mov     al , [edx + IPv4_Packet.Protocol]
  392.         pop     edx                                             ; Offset to data (tcp/udp/icmp/.. Packet)
  393.  
  394. ;        cmp     al , IP_PROTO_TCP
  395. ;        je      TCP_Handler
  396.  
  397.         cmp     al , IP_PROTO_UDP
  398.         je      UDP_Handler
  399.  
  400.         cmp     al , IP_PROTO_ICMP
  401.         je      ICMP_Handler_fragments
  402.  
  403.         DEBUGF  1,"IP_Handler - unknown protocol:%u\n",al
  404.  
  405.         call    kernel_free
  406.         add     esp, 8                                          ; pop (balance stack)
  407.  
  408.         ret
  409.  
  410.  
  411.   .destroy_slot_pop:
  412.         add     esp, 4
  413.   .destroy_slot:
  414.         DEBUGF  1,"Destroy fragment slot!\n"
  415.         ; TODO!
  416.         jmp     .dump
  417.  
  418.  
  419.  
  420. ;-----------------------------------------------------------------
  421. ;
  422. ; find fragment slot
  423. ;
  424. ; IN: pointer to fragmented packet in edx         ; TODO: the RFC says we should check protocol too
  425. ; OUT: pointer to slot in edi, -1 on error
  426. ;
  427. ;-----------------------------------------------------------------
  428.  
  429.   .find_fragment_slot:
  430.  
  431.         push    eax ebx ecx edx
  432.         mov     ax , word [edx + IPv4_Packet.Identification]
  433.         mov     ecx, MAX_FRAGMENTS
  434.         mov     esi, FRAGMENT_LIST
  435.         mov     ebx, dword [edx + IPv4_Packet.SourceAddress]
  436.         mov     edx, dword [edx + IPv4_Packet.DestinationAddress]
  437.   .find_slot:
  438.         cmp     word [esi + FRAGMENT_slot.id], ax
  439.         jne     .try_next
  440.         cmp     dword [esi + FRAGMENT_slot.SrcIP], ebx
  441.         jne     .try_next
  442.         cmp     dword [esi + FRAGMENT_slot.DstIP], edx
  443.         je      .found_slot
  444.   .try_next:
  445.         add     esi, FRAGMENT_slot.size
  446.         loop    .find_slot
  447.  ;       pop     edx ebx
  448.         or      esi, -1
  449. ;        ret
  450.  
  451.   .found_slot:
  452.         pop     edx ecx ebx eax
  453.         ret
  454.  
  455.  
  456. ;-----------------------------------------------------------------
  457. ;
  458. ; Decrease TimeToLive of all fragment slots
  459. ;
  460. ; IN: /
  461. ; OUT: /
  462. ;
  463. ;-----------------------------------------------------------------
  464.  
  465. align 4
  466. IPv4_decrease_fragment_ttls:
  467.  
  468.         mov     esi, FRAGMENT_LIST
  469.         mov     ecx, MAX_FRAGMENTS
  470.   .loop:
  471.         cmp     [esi + FRAGMENT_slot.ttl], 0
  472.         je      .try_next
  473.         dec     [esi + FRAGMENT_slot.ttl]
  474.         jnz     .try_next
  475.         DEBUGF 1,"Fragment slot timed-out!\n"
  476.         ; TODO: clear all entry's of timed-out slot
  477.   .try_next:
  478.         add     esi, 4
  479.         loop    .loop
  480.         ret
  481.  
  482.  
  483.  
  484.  
  485.  
  486. ;-----------------------------------------------------------------
  487. ;
  488. ; Create_IPv4_Packet
  489. ;
  490. ; IN: eax = dest ip
  491. ;     ebx = source ip
  492. ;     ecx = data length
  493. ;     dx  = fragment id
  494. ;     di  = protocol
  495. ;
  496. ; OUT: eax points to buffer start
  497. ;      ebx is size of complete buffer
  498. ;      edi = pointer to start of data (-1 on error)
  499. ;      ecx = unchanged (packet size of embedded data)
  500. ;      edx = pointer to device struct (needed for sending procedure)
  501. ;      esi = pointer to sending procedure
  502. ;
  503. ;-----------------------------------------------------------------
  504.  
  505. ;;; TODO: create fragmented packets
  506.  
  507. align 4
  508. IPv4_create_Packet:
  509.  
  510.         DEBUGF 1,"Create IPv4 Packet\n"
  511.  
  512.         cmp     ecx, 1514
  513.         jg      .exit_
  514.  
  515.         cmp     eax, -1
  516.         je      .broadcast                ; If it is broadcast, just send
  517.  
  518.         push    eax
  519.         stdcall arp_table_manager, ARP_TABLE_IP_TO_MAC, eax, temp_dstmac        ;opcode,IP,MAC_ptr - Get the MAC address.
  520.         cmp     eax, ARP_NO_ENTRY
  521.         pop     eax
  522.         jne     .send
  523.  
  524.         DEBUGF 1,"Create IPv4 Packet - ARP entry not found!\n"
  525.  
  526.         ; TODO: QUEUE!
  527.         or      edi, -1
  528.  
  529.         ret
  530.  
  531.   .broadcast:
  532.         mov     dword [temp_dstmac], -1
  533.         mov     word [temp_dstmac+4], -1
  534.  
  535.  
  536.   .send:
  537.         push    ecx eax ebx dx di
  538.         call    IPv4_dest_to_dev
  539.         inc     [IP_PACKETS_TX+4*edi]
  540.         mov     edi, [ETH_DRV_LIST + 4*edi]
  541.         lea     eax, [edi + ETH_DEVICE.mac]
  542.         mov     ebx, temp_dstmac
  543.         mov     ecx, [esp+12]
  544.         add     ecx, IPv4_Packet.DataOrOptional
  545.         mov     di , ETHER_IPv4
  546.         call    ETH_create_Packet                  ; TODO: figure out a way to make this work with other protocols too
  547.         cmp     edi, -1
  548.         je      .exit
  549.  
  550.         mov     [edi + IPv4_Packet.VersionAndIHL], 0x45   ; IPv4, normal length (no Optional header)
  551.         mov     [edi + IPv4_Packet.TypeOfService], 0
  552.         xchg    ch, cl
  553.         mov     [edi + IPv4_Packet.TotalLength], cx
  554.         mov     [edi + IPv4_Packet.FlagsAndFragmentOffset], 0x0000
  555.         mov     [edi + IPv4_Packet.TimeToLive], 128
  556.         mov     [edi + IPv4_Packet.HeaderChecksum], 0
  557.         pop     cx
  558.         mov     [edi + IPv4_Packet.Protocol], cl
  559.         pop     cx
  560.         mov     [edi + IPv4_Packet.Identification], cx
  561.         pop     ecx
  562.         mov     [edi + IPv4_Packet.SourceAddress], ecx
  563.         pop     ecx
  564.         mov     [edi + IPv4_Packet.DestinationAddress], ecx
  565.  
  566.         push    eax
  567.         stdcall checksum_jb, edi, IPv4_Packet.DataOrOptional ; buf_ptr, buf_size
  568.         xchg    al, ah
  569.         mov     [edi + IPv4_Packet.HeaderChecksum], ax
  570.         pop     eax ecx
  571.         add     edi, IPv4_Packet.DataOrOptional
  572.  
  573.         DEBUGF 1,"IPv4 Packet for device %x created successfully\n", edx
  574.  
  575.         ret
  576.  
  577.   .exit:
  578.         add     esp, 16
  579.   .exit_:
  580.         DEBUGF 1,"Create IPv4 Packet - failed\n"
  581.         or      edi, -1
  582.         ret
  583.  
  584.  
  585. uglobal
  586.         temp_dstmac dp ?    ; TODO: place this in stack instead!
  587. endg
  588.  
  589.  
  590. ;---------------------------------------------------------------------------
  591. ;
  592. ; IPv4_dest_to_dev
  593. ;
  594. ; IN: Destination IP in eax
  595. ; OUT: device id in edi
  596. ;
  597. ;---------------------------------------------------------------------------
  598.  
  599. align 4
  600. IPv4_dest_to_dev:
  601.  
  602.         DEBUGF 1,"IPv4 destination to device: "
  603.  
  604.         xor     edi, edi
  605.         mov     ecx, MAX_IP
  606.  
  607.   .loop:
  608.         mov     ebx, [IP_LIST+edi]              ; we dont need to worry about non exisiting ip interfaces
  609.         and     ebx, [SUBNET_LIST+edi]          ; they have IP and SUBNET set to all one's, so they will have no match except 255.255.255.255
  610.                                                 ; (only a moron would insert that ip into this function..)
  611.         mov     edx, eax
  612.         and     edx, [SUBNET_LIST+edi]
  613.  
  614.         cmp     ebx, edx
  615.         je      .found_it
  616.  
  617.         add     edi, 4
  618.         loop    .loop
  619.  
  620.         xor     edi, edi        ; if none found, use device 0 as default device
  621.  
  622.   .found_it:
  623.         shr     edi, 2
  624.  
  625.         DEBUGF 1,"%u\n",edi
  626.  
  627.         ret
  628.  
  629.  
  630.  
  631. ;---------------------------------------------------------------------------
  632. ;
  633. ; IPv4_get_frgmnt_num
  634. ;
  635. ; IN: /
  636. ; OUT: fragment number in ax
  637. ;
  638. ;---------------------------------------------------------------------------
  639.  
  640. align 4
  641. IPv4_get_frgmnt_num:
  642.         xor     ax, ax  ;;; TODO: replace this with real code
  643.  
  644.         ret
  645.  
  646.  
  647. ;---------------------------------------------------------------------------
  648. ;
  649. ; IPv4_API
  650. ;
  651. ; This function is called by system function 75
  652. ;
  653. ; IN:  subfunction number in bl
  654. ;      device number in bh
  655. ;      ecx, edx, .. depends on subfunction
  656. ;
  657. ; OUT:
  658. ;
  659. ;---------------------------------------------------------------------------
  660.  
  661. align 4
  662. IPv4_API:
  663.  
  664.         movzx   eax, bh
  665.         shl     eax, 2
  666.  
  667.         test    bl, bl
  668.         jz      .packets_tx     ; 0
  669.         dec     bl
  670.         jz      .packets_rx     ; 1
  671.         dec     bl
  672.         jz      .read_ip        ; 2
  673.         dec     bl
  674.         jz      .write_ip       ; 3
  675.         dec     bl
  676.         jz      .read_dns       ; 4
  677.         dec     bl
  678.         jz      .write_dns      ; 5
  679.         dec     bl
  680.         jz      .read_subnet    ; 6
  681.         dec     bl
  682.         jz      .write_subnet   ; 7
  683.         dec     bl
  684.         jz      .read_gateway   ; 8
  685.         dec     bl
  686.         jz      .write_gateway  ; 9
  687.  
  688. .error:
  689.         mov     eax, -1
  690.         ret
  691.  
  692. .packets_tx:
  693.         add     eax, IP_PACKETS_TX
  694.         mov     eax, [eax]
  695.         ret
  696.  
  697. .packets_rx:
  698.         add     eax, IP_PACKETS_RX
  699.         mov     eax, [eax]
  700.         ret
  701.  
  702. .read_ip:
  703.         add     eax, IP_LIST
  704.         mov     eax, [eax]
  705.         ret
  706.  
  707. .write_ip:
  708.         add     eax, IP_LIST
  709.         mov     [eax], ecx
  710.         xor     eax, eax
  711.         ret
  712.  
  713. .read_dns:
  714.         add     eax, DNS_LIST
  715.         mov     eax, [eax]
  716.         ret
  717.  
  718. .write_dns:
  719.         add     eax, DNS_LIST
  720.         mov     [eax], ecx
  721.         xor     eax, eax
  722.         ret
  723.  
  724. .read_subnet:
  725.         add     eax, SUBNET_LIST
  726.         mov     eax, [eax]
  727.         ret
  728.  
  729. .write_subnet:
  730.         add     eax, SUBNET_LIST
  731.         mov     [eax], ecx
  732.         xor     eax, eax
  733.         ret
  734.  
  735. .read_gateway:
  736.         add     eax, GATEWAY_LIST
  737.         mov     eax, [eax]
  738.         ret
  739.  
  740. .write_gateway:
  741.         add     eax, GATEWAY_LIST
  742.         mov     [eax], ecx
  743.         xor     eax, eax
  744.         ret
  745.  
  746.  
  747.  
  748.  
  749.