Subversion Repositories Kolibri OS

Rev

Rev 1482 | Go to most recent revision | 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. ;;  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: 1483 $
  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. ;  IN:  /
  44. ;  OUT: /
  45. ;
  46. ;-----------------------------------------------------------------
  47. align 4
  48. UDP_init:
  49.  
  50.         xor     eax, eax
  51.         mov     edi, UDP_PACKETS_TX
  52.         mov     ecx, 2*MAX_IP
  53.         rep     stosd
  54.  
  55.         ret
  56.  
  57.  
  58.  
  59. ;-----------------------------------------------------------------
  60. ;
  61. ; UDP_Handler:
  62. ;
  63. ;  Called by IPv4_handler,
  64. ;  this procedure will inject the udp data diagrams in the application sockets.
  65. ;
  66. ;  IN:  Pointer to buffer in [esp]
  67. ;       size of buffer in [esp+4]
  68. ;       pointer to device struct in ebx
  69. ;       UDP Packet size in ecx
  70. ;       pointer to UDP Packet in edx
  71. ;  OUT: /
  72. ;
  73. ;-----------------------------------------------------------------
  74. align 4
  75. UDP_handler:
  76.  
  77.         DEBUGF  1,"UDP_Handler, checksum:%x, size:%u\n", [edx+UDP_Packet.Checksum]:4, ecx
  78.  
  79. ; First validate, checksum:
  80.         cmp    [edx + UDP_Packet.Checksum], 0
  81.         jz     .no_checksum
  82.  
  83.         push    edx
  84.  
  85.         push    esi
  86.         push    edi
  87.         mov     esi, edx
  88.         call    UDP_checksum
  89.  
  90.         pop     edx
  91.  
  92.         cmp    [edx + UDP_Packet.Checksum], 0
  93.         jnz    .checksum_mismatch
  94.  
  95.   .no_checksum:
  96.         DEBUGF  1,"UDP Checksum is correct\n"
  97.  
  98.         ; Look for a socket where
  99.         ; IP Packet UDP Destination Port = local Port
  100.         ; IP Packet SA = Remote IP
  101.  
  102.         mov     eax, net_sockets
  103.   .try_more:
  104.         mov     si , [edx + UDP_Packet.DestinationPort]   ; get the local port from the IP Packet's UDP header
  105.   .next_socket:
  106.         mov     eax, [eax + SOCKET_head.NextPtr]
  107.         or      eax, eax
  108.         jz      .dump
  109.         cmp     [eax + SOCKET_head.Domain], AF_INET4
  110.         jne     .next_socket
  111.         cmp     [eax + SOCKET_head.Type], IP_PROTO_UDP
  112.         jne     .next_socket
  113.         cmp     [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], si
  114.         jne     .next_socket
  115.  
  116.         DEBUGF  1,"found socket with matching domain, type and localport\n"
  117.  
  118.         ; For dhcp, we must allow any remote server to respond.
  119.         ; I will accept the first incoming response to be the one
  120.         ; I bind to, if the socket is opened with a destination IP address of
  121.         ; 255.255.255.255
  122.         cmp     [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], 0xffffffff
  123.         je      .ok1
  124.  
  125. ;        mov     esi, [esp] ; start of data (ethernet header)
  126. ;        mov     esi, [esi + ETH_FRAME.Data + IPv4_Packet.SourceAddress] ; get the Source address from the IP Packet   FIXME
  127.         cmp     [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], edi ;esi
  128.         jne     .try_more                                             ; Quit if the source IP is not valid, check for more sockets with this IP/PORT combination
  129.  
  130.  
  131.         DEBUGF  1,"Remote Ip matches\n"
  132.   .ok1:
  133.  
  134.         cmp     [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.firstpacket], 0
  135.         jz      .updateport
  136.  
  137.         mov     si, [edx + UDP_Packet.SourcePort]
  138.         cmp     [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], si
  139.         jne     .dump
  140.  
  141.         push    ebx
  142.         lea     ebx, [eax + SOCKET_head.lock]
  143.         call    wait_mutex
  144.         pop     ebx
  145.  
  146.   .ok2:
  147.  
  148.         DEBUGF  1,"Found valid UDP packet for socket %x\n", eax
  149.         lea     esi, [edx + UDP_Packet.Data]
  150.         movzx   ecx, [edx + UDP_Packet.Length]
  151.         rol     cx , 8
  152.         sub     cx , UDP_Packet.Data
  153.  
  154.         inc     [UDP_PACKETS_RX]
  155.  
  156.         pop     edi
  157.         add     esp, 4
  158.  
  159.         sub     esi, edi
  160.         xchg    esi, edi
  161.         jmp     socket_internal_receiver
  162.  
  163.  
  164.   .updateport:
  165.  
  166.         push    ebx
  167.         lea     ebx, [eax + SOCKET_head.lock]
  168.         call    wait_mutex
  169.         pop     ebx
  170.  
  171.         mov     si, [edx + UDP_Packet.SourcePort]
  172.         DEBUGF  1,"Changing remote port to: %x\n", si
  173.         mov     [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], si
  174.         inc     [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.firstpacket]
  175.  
  176.         jmp     .ok2
  177.  
  178.  
  179.   .checksum_mismatch:
  180.  
  181.         DEBUGF  2,"UDP_Handler - checksum mismatch\n"
  182.  
  183. ;        mov     esi, edx
  184. ;       @@:                         ;
  185. ;        lodsb                      ;
  186. ;        DEBUGF  2,"%x ", eax:2     ;
  187. ;        loop    @r                 ;
  188.  
  189.   .dump:
  190.         call    kernel_free
  191.         add     esp, 4 ; pop (balance stack)
  192.         DEBUGF  2,"UDP_Handler - dumping\n"
  193.  
  194.         ret
  195.  
  196.  
  197.  
  198.  
  199. ;-----------------------------------------------------------------
  200. ;
  201. ; UDP_socket_send
  202. ;
  203. ; IN: eax = socket pointer
  204. ;     ecx = number of bytes to send
  205. ;     esi = pointer to data
  206. ;
  207. ;-----------------------------------------------------------------
  208.  
  209. align 4
  210. UDP_socket_send:
  211.  
  212.         mov     edx, dword [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort] ; load local port and remote port at once
  213.         DEBUGF  1,"local port: %x, remote port: %x\n",\
  214.         [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort]:4,\
  215.         [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort]:4
  216.         mov     ebx, [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP]
  217.         mov     eax, [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
  218.  
  219.         DEBUGF  1,"Create UDP Packet (size=%u)\n",ecx
  220.  
  221.         mov     di , IP_PROTO_UDP
  222.         sub     esp, 8                                          ; Data ptr and data size will be placed here
  223.         add     ecx, UDP_Packet.Data
  224.  
  225. ; TODO: fill in:   dx  = fragment id
  226.  
  227.         push    edx esi
  228.         call    IPv4_create_packet                              ; TODO: figure out a way to choose between IPv4 and IPv6
  229.         cmp     edi, -1
  230.         je      .fail
  231.  
  232.         mov     [esp + 8], eax                                  ; pointer to buffer start
  233.         mov     [esp + 8 + 4], edx                              ; buffer size
  234.  
  235.         rol     cx, 8
  236.         mov     [edi + UDP_Packet.Length], cx
  237.         ror     cx, 8
  238.  
  239.         pop     esi
  240.         push    edi ecx
  241.         sub     ecx, UDP_Packet.Data
  242.         add     edi, UDP_Packet.Data
  243.         shr     ecx, 2
  244.         rep     movsd
  245.         mov     ecx, [esp]
  246.         and     ecx, 3
  247.         rep     movsb
  248.         pop     ecx edi
  249.  
  250.         pop     dword [edi + UDP_Packet.SourcePort]             ; fill in both portnumbers
  251.         mov     [edi + UDP_Packet.Checksum], 0                  ; set it to zero, to calculate checksum
  252.  
  253. ; Checksum
  254.         mov     esi, edi
  255.         pushd   [edi-4] ; destination address           ; TODO: fix this, IPv4 packet could have options..
  256.         pushd   [edi-8] ; source address
  257.         call    UDP_checksum
  258.  
  259.         inc     [UDP_PACKETS_TX]
  260.  
  261.         DEBUGF  1,"Sending UDP Packet to device %x\n", ebx
  262.         jmp     ETH_sender
  263.  
  264.   .fail:
  265.         ; todo: queue the packet
  266.         add     esp, 8+12+8
  267.         ret
  268.  
  269.  
  270.  
  271.  
  272. ;-----------------------------------------------------------------
  273. ;
  274. ; checksum_udp
  275. ;
  276. ; This is the fast procedure to create or check a UDP header
  277. ;  - To create a new checksum, the checksum field must be set to 0 before computation
  278. ;  - To check an existing checksum, leave the checksum as is,
  279. ;     and it will be 0 after this procedure, if it was correct
  280. ;
  281. ;  IN:  push source ip
  282. ;       push dest ip
  283. ;       esi = packet ptr
  284. ;
  285. ;  OUT: checksum is filled in in packet! (but also in dx)
  286. ;
  287. ;-----------------------------------------------------------------
  288.  
  289. align 4
  290. UDP_checksum:
  291.  
  292. ; Pseudoheader
  293.         mov     edx, IP_PROTO_UDP               ; NO shl 8 here ! (it took me ages to figure this one out)
  294.  
  295.         add     dl, [esp+1+4]
  296.         adc     dh, [esp+0+4]
  297.         adc     dl, [esp+3+4]
  298.         adc     dh, [esp+2+4]
  299.  
  300.         adc     dl, [esp+1+8]
  301.         adc     dh, [esp+0+8]
  302.         adc     dl, [esp+3+8]
  303.         adc     dh, [esp+2+8]
  304.  
  305.  
  306.         adc     dl, cl ; byte[esi+UDP_Packet.Length+1]
  307.         adc     dh, ch ; byte[esi+UDP_Packet.Length+0]
  308.  
  309. ; Done with pseudoheader, now do real header
  310.         adc     dl, byte[esi+UDP_Packet.SourcePort+1]
  311.         adc     dh, byte[esi+UDP_Packet.SourcePort+0]
  312.  
  313.         adc     dl, byte[esi+UDP_Packet.DestinationPort+1]
  314.         adc     dh, byte[esi+UDP_Packet.DestinationPort+0]
  315.  
  316.         adc     dl, byte[esi+UDP_Packet.Length+1]
  317.         adc     dh, byte[esi+UDP_Packet.Length+0]
  318.  
  319.         adc     edx, 0
  320.  
  321. ; Done with header, now do data
  322.         push    esi
  323.         movzx   ecx, [esi+UDP_Packet.Length]
  324.         rol     cx , 8
  325.         sub     cx , UDP_Packet.Data
  326.         add     esi, UDP_Packet.Data
  327.  
  328.         call    checksum_1
  329.         call    checksum_2
  330.         pop     esi
  331.  
  332.         neg     [esi+UDP_Packet.Checksum]           ; zero will stay zero so we just get the checksum
  333.         add     [esi+UDP_Packet.Checksum], dx       ;  , else we will get (new checksum - old checksum) in the end, wich should be 0 :)
  334.  
  335.         ret     8
  336.  
  337.  
  338.  
  339.  
  340. ;---------------------------------------------------------------------------
  341. ;
  342. ; UDP_API
  343. ;
  344. ; This function is called by system function 75
  345. ;
  346. ; IN:  subfunction number in bl
  347. ;      device number in bh
  348. ;      ecx, edx, .. depends on subfunction
  349. ;
  350. ; OUT:
  351. ;
  352. ;---------------------------------------------------------------------------
  353.  
  354. align 4
  355. UDP_API:
  356.  
  357.         movzx   eax, bh
  358.         shl     eax, 2
  359.  
  360.         test    bl, bl
  361.         jz      .packets_tx     ; 0
  362.         dec     bl
  363.         jz      .packets_rx     ; 1
  364.  
  365. .error:
  366.         mov     eax, -1
  367.         ret
  368.  
  369. .packets_tx:
  370.         add     eax, UDP_PACKETS_TX
  371.         mov     eax, [eax]
  372.         ret
  373.  
  374. .packets_rx:
  375.         add     eax, UDP_PACKETS_RX
  376.         mov     eax, [eax]
  377.         ret
  378.