Subversion Repositories Kolibri OS

Rev

Rev 3600 | Rev 3647 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;  UDP.INC                                                        ;;
  7. ;;                                                                 ;;
  8. ;;  Part of the tcp/ip network stack for KolibriOS                 ;;
  9. ;;                                                                 ;;
  10. ;;    Written by hidnplayr@kolibrios.org                           ;;
  11. ;;                                                                 ;;
  12. ;;          GNU GENERAL PUBLIC LICENSE                             ;;
  13. ;;             Version 2, June 1991                                ;;
  14. ;;                                                                 ;;
  15. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  16.  
  17. $Revision: 2995 $
  18.  
  19.  
  20. struct  UDP_header
  21.  
  22.         SourcePort              dw  ?
  23.         DestinationPort         dw  ?
  24.         Length                  dw  ?  ; Length of (UDP Header + Data)
  25.         Checksum                dw  ?
  26.  
  27. ends
  28.  
  29.  
  30. align 4
  31. uglobal
  32.         UDP_PACKETS_TX          rd  NET_DEVICES_MAX
  33.         UDP_PACKETS_RX          rd  NET_DEVICES_MAX
  34. endg
  35.  
  36.  
  37. ;-----------------------------------------------------------------
  38. ;
  39. ; UDP_init
  40. ;
  41. ;  This function resets all UDP variables
  42. ;
  43. ;-----------------------------------------------------------------
  44. macro   UDP_init {
  45.  
  46.         xor     eax, eax
  47.         mov     edi, UDP_PACKETS_TX
  48.         mov     ecx, 2*NET_DEVICES_MAX
  49.         rep     stosd
  50. }
  51.  
  52.  
  53. macro   UDP_checksum    IP1, IP2  { ; esi = ptr to udp packet, ecx = packet size, destroys: ecx, edx
  54.  
  55. ; Pseudoheader
  56.         mov     edx, IP_PROTO_UDP
  57.  
  58.         add     dl, [IP1+1]
  59.         adc     dh, [IP1+0]
  60.         adc     dl, [IP1+3]
  61.         adc     dh, [IP1+2]
  62.  
  63.         adc     dl, [IP2+1]
  64.         adc     dh, [IP2+0]
  65.         adc     dl, [IP2+3]
  66.         adc     dh, [IP2+2]
  67.  
  68.         adc     dl, cl ; byte[esi+UDP_header.Length+1]
  69.         adc     dh, ch ; byte[esi+UDP_header.Length+0]
  70.  
  71. ; Done with pseudoheader, now do real header
  72.         adc     dl, byte[esi+UDP_header.SourcePort+1]
  73.         adc     dh, byte[esi+UDP_header.SourcePort+0]
  74.  
  75.         adc     dl, byte[esi+UDP_header.DestinationPort+1]
  76.         adc     dh, byte[esi+UDP_header.DestinationPort+0]
  77.  
  78.         adc     dl, byte[esi+UDP_header.Length+1]
  79.         adc     dh, byte[esi+UDP_header.Length+0]
  80.  
  81.         adc     edx, 0
  82.  
  83. ; Done with header, now do data
  84.         push    esi
  85.         movzx   ecx, [esi+UDP_header.Length]
  86.         rol     cx , 8
  87.         sub     cx , sizeof.UDP_header
  88.         add     esi, sizeof.UDP_header
  89.  
  90.         call    checksum_1
  91.         call    checksum_2
  92.         pop     esi
  93.  
  94.         add     [esi+UDP_header.Checksum], dx   ; this final instruction will set or clear ZF :)
  95.  
  96. }
  97.  
  98.  
  99. ;-----------------------------------------------------------------
  100. ;
  101. ; UDP_input:
  102. ;
  103. ;  Called by IPv4_input,
  104. ;  this procedure will inject the udp data diagrams in the application sockets.
  105. ;
  106. ;  IN:   [esp]  = Pointer to buffer
  107. ;       [esp+4] = size of buffer
  108. ;       ebx = ptr to device struct
  109. ;       ecx = UDP Packet size
  110. ;       esi = ptr to UDP header
  111. ;       edi = ptr to ipv4 source and dest address
  112. ;
  113. ;  OUT: /
  114. ;
  115. ;-----------------------------------------------------------------
  116. align 4
  117. UDP_input:
  118.  
  119.         DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_input: size=%u\n", ecx
  120.  
  121.         ; First validate, checksum
  122.  
  123.         neg     [esi + UDP_header.Checksum]     ; substract checksum from 0
  124.         jz      .no_checksum                    ; if checksum is zero, it is considered valid
  125.  
  126.         ; otherwise, we will re-calculate the checksum and add it to this value, thus creating 0 when it is correct
  127.  
  128.         UDP_checksum (edi), (edi+4)
  129.         jnz     .checksum_mismatch
  130.  
  131.   .no_checksum:
  132.         DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_input: checksum ok\n"
  133.  
  134.         ; Convert length to little endian
  135.  
  136.         rol     [esi + UDP_header.Length], 8
  137.  
  138.         ; Look for a socket where
  139.         ; IP Packet UDP Destination Port = local Port
  140.         ; IP Packet SA = Remote IP
  141.  
  142.         mov     cx, [esi + UDP_header.SourcePort]
  143.         mov     dx, [esi + UDP_header.DestinationPort]
  144.         mov     edi, [edi + 4]                          ; ipv4 source address
  145.         mov     eax, net_sockets
  146.  
  147.   .next_socket:
  148.         mov     eax, [eax + SOCKET.NextPtr]
  149.         or      eax, eax
  150.         jz      .dump
  151.  
  152.         cmp     [eax + SOCKET.Domain], AF_INET4
  153.         jne     .next_socket
  154.  
  155.         cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
  156.         jne     .next_socket
  157.  
  158.         cmp     [eax + UDP_SOCKET.LocalPort], dx
  159.         jne     .next_socket
  160.  
  161.         DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_input: socket=%x\n", eax
  162.  
  163.         ;;; TODO: when packet is processed, check more sockets!
  164.  
  165. ;        cmp     [eax + IP_SOCKET.RemoteIP], 0xffffffff
  166. ;        je      @f
  167. ;        cmp     [eax + IP_SOCKET.RemoteIP], edi
  168. ;        jne     .next_socket
  169. ;       @@:
  170. ;
  171. ; FIXME: UDP should check remote IP, but not under all circumstances!
  172.  
  173.         cmp     [eax + UDP_SOCKET.firstpacket], 0
  174.         je      .updateport
  175.  
  176.         cmp     [eax + UDP_SOCKET.RemotePort], cx
  177.         jne     .dump
  178.  
  179.         pusha
  180.         lea     ecx, [eax + SOCKET.mutex]
  181.         call    mutex_lock
  182.         popa
  183.  
  184.   .updatesock:
  185.         call    NET_ptr_to_num4
  186.         inc     [UDP_PACKETS_RX + edi]
  187.  
  188.         movzx   ecx, [esi + UDP_header.Length]
  189.         sub     ecx, sizeof.UDP_header
  190.         add     esi, sizeof.UDP_header
  191.  
  192.         jmp     SOCKET_input
  193.  
  194.   .updateport:
  195.         pusha
  196.         lea     ecx, [eax + SOCKET.mutex]
  197.         call    mutex_lock
  198.         popa
  199.  
  200.         DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_input: new remote port=%x\n", cx ; FIXME: find a way to print big endian values with debugf
  201.         mov     [eax + UDP_SOCKET.RemotePort], cx
  202.         inc     [eax + UDP_SOCKET.firstpacket]
  203.  
  204.         jmp     .updatesock
  205.  
  206.  
  207.   .checksum_mismatch:
  208.         DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_input: checksum mismatch\n"
  209.  
  210.   .dump:
  211.         call    kernel_free
  212.         add     esp, 4 ; pop (balance stack)
  213.         DEBUGF  DEBUG_NETWORK_VERBOSE,"UDP_input: dumping\n"
  214.  
  215.         ret
  216.  
  217.  
  218.  
  219.  
  220. ;-----------------------------------------------------------------
  221. ;
  222. ; UDP_output
  223. ;
  224. ; IN: eax = socket pointer
  225. ;     ecx = number of bytes to send
  226. ;     esi = pointer to data
  227. ;
  228. ;-----------------------------------------------------------------
  229.  
  230. align 4
  231. UDP_output:
  232.  
  233.         DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_output: socket=%x bytes=%u data_ptr=%x\n", eax, ecx, esi
  234.  
  235.         mov     dx, [eax + UDP_SOCKET.RemotePort]
  236.         DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_output: remote port=%x, ", dx    ; FIXME: find a way to print big endian values with debugf
  237.         rol     edx, 16
  238.         mov     dx, [eax + UDP_SOCKET.LocalPort]
  239.         DEBUGF  DEBUG_NETWORK_VERBOSE, "local port=%x\n", dx
  240.  
  241.         sub     esp, 8                                          ; Data ptr and data size will be placed here
  242.         push    edx esi
  243.         mov     ebx, [eax + SOCKET.device]
  244.         mov     edx, [eax + IP_SOCKET.LocalIP]
  245.         mov     eax, [eax + IP_SOCKET.RemoteIP]
  246.         mov     di, IP_PROTO_UDP shl 8 + 128
  247.         add     ecx, sizeof.UDP_header
  248.         call    IPv4_output
  249.         jz      .fail
  250.         mov     [esp + 8], eax                                  ; pointer to buffer start
  251.         mov     [esp + 8 + 4], edx                              ; buffer size
  252.  
  253.         mov     [edi + UDP_header.Length], cx
  254.         rol     [edi + UDP_header.Length], 8
  255.  
  256.         pop     esi
  257.         push    edi ecx
  258.         sub     ecx, sizeof.UDP_header
  259.         add     edi, sizeof.UDP_header
  260.         shr     ecx, 2
  261.         rep     movsd
  262.         mov     ecx, [esp]
  263.         and     ecx, 3
  264.         rep     movsb
  265.         pop     ecx edi
  266.  
  267.         pop     dword [edi + UDP_header.SourcePort]
  268.  
  269. ; Checksum
  270.         mov     esi, edi
  271.         mov     [edi + UDP_header.Checksum], 0
  272.         UDP_checksum (edi-4), (edi-8)                           ; FIXME: IPv4 packet could have options..
  273.  
  274.         DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_output: sending with device %x\n", ebx
  275.         call    [ebx + NET_DEVICE.transmit]
  276.         test    eax, eax
  277.         jnz     @f
  278.         call    NET_ptr_to_num4
  279.         inc     [UDP_PACKETS_TX + edi]
  280.        @@:
  281.  
  282.         ret
  283.  
  284.   .fail:
  285.         DEBUGF  DEBUG_NETWORK_ERROR, "UDP_output: failed\n"
  286.         add     esp, 4+4+8
  287.         or      eax, -1
  288.         ret
  289.  
  290.  
  291.  
  292. ;---------------------------------------------------------------------------
  293. ;
  294. ; UDP_API
  295. ;
  296. ; This function is called by system function 75
  297. ;
  298. ; IN:  subfunction number in bl
  299. ;      device number in bh
  300. ;      ecx, edx, .. depends on subfunction
  301. ;
  302. ; OUT:
  303. ;
  304. ;---------------------------------------------------------------------------
  305.  
  306. align 4
  307. UDP_api:
  308.  
  309.         movzx   eax, bh
  310.         shl     eax, 2
  311.  
  312.         test    bl, bl
  313.         jz      .packets_tx     ; 0
  314.         dec     bl
  315.         jz      .packets_rx     ; 1
  316.  
  317.   .error:
  318.         mov     eax, -1
  319.         ret
  320.  
  321.   .packets_tx:
  322.         mov     eax, [UDP_PACKETS_TX + eax]
  323.         ret
  324.  
  325.   .packets_rx:
  326.         mov     eax, [UDP_PACKETS_RX + eax]
  327.         ret
  328.