Subversion Repositories Kolibri OS

Rev

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

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