Subversion Repositories Kolibri OS

Rev

Rev 1254 | Blame | Last modification | View Log | Download | RSS feed

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