Subversion Repositories Kolibri OS

Rev

Rev 1337 | 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: 1473 $
  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 data in edx
  71. ;  OUT: /
  72. ;
  73. ;-----------------------------------------------------------------
  74. align 4
  75. UDP_handler:
  76.  
  77.         DEBUGF  1,"UDP_Handler\n"
  78.  
  79.         cmp     [edx + UDP_Packet.Checksum], 0
  80.         jz      .no_checksum
  81.         ; First validate, checksum:
  82.  
  83.         pusha
  84.  
  85.         push    cx
  86.         rol     word [esp], 8
  87.         push    word IP_PROTO_UDP shl 8
  88.         push    edi
  89.         push    esi
  90.  
  91.         mov     di, [edx + UDP_Packet.Checksum]
  92.         mov     [edx + UDP_Packet.Checksum], 0
  93.  
  94.         mov     esi, edx
  95.         xor     edx, edx
  96.         call    checksum_1
  97.         call    checksum_pseudoheader
  98.         call    checksum_2
  99.  
  100.         cmp     di, dx
  101.         popa
  102.         jne     .checksum_mismatch ;dump
  103.  
  104.  
  105.   .no_checksum:
  106.  
  107.         DEBUGF  1,"UDP Checksum is correct\n"
  108.  
  109.         ; Look for a socket where
  110.         ; IP Packet UDP Destination Port = local Port
  111.         ; IP Packet SA = Remote IP
  112.  
  113.         mov     eax, net_sockets
  114.   .try_more:
  115.         mov     si , [edx + UDP_Packet.DestinationPort]   ; get the local port from the IP Packet's UDP header
  116.   .next_socket:
  117.         mov     eax, [eax + SOCKET_head.NextPtr]
  118.         or      eax, eax
  119.         jz      .dump
  120.         cmp     [eax + SOCKET_head.Domain], AF_INET4
  121.         jne     .next_socket
  122.         cmp     [eax + SOCKET_head.Type], IP_PROTO_UDP
  123.         jne     .next_socket
  124.         cmp     [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], si
  125.         jne     .next_socket
  126.  
  127.         DEBUGF  1,"found socket with matching domain, type and localport\n"
  128.  
  129.         ; For dhcp, we must allow any remote server to respond.
  130.         ; I will accept the first incoming response to be the one
  131.         ; I bind to, if the socket is opened with a destination IP address of
  132.         ; 255.255.255.255
  133.         cmp     [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], 0xffffffff
  134.         je      .ok1
  135.  
  136.         mov     esi, [esp]
  137.         mov     esi, [ebx + ETH_FRAME.Data + IPv4_Packet.SourceAddress] ; get the Source address from the IP Packet   FIXME
  138.         cmp     [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], esi
  139.         jne     .try_more                                             ; Quit if the source IP is not valid, check for more sockets with this IP/PORT combination
  140.  
  141.  
  142.         DEBUGF  1,"Remote Ip matches\n"
  143.   .ok1:
  144.  
  145.         cmp     [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.firstpacket], 0
  146.         jz      .updateport
  147.  
  148.         mov     si, [edx + UDP_Packet.SourcePort]
  149.         cmp     [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], si
  150.         jne     .dump
  151.  
  152.         push    ebx
  153.         lea     ebx, [eax + SOCKET_head.lock]
  154.         call    wait_mutex
  155.         pop     ebx
  156.  
  157.   .ok2:
  158.  
  159.         DEBUGF  1,"Found valid UDP packet for socket %x\n", eax
  160.         lea     esi, [edx + UDP_Packet.Data]
  161.         movzx   ecx, [edx + UDP_Packet.Length]
  162.         rol     cx , 8
  163.         sub     cx , UDP_Packet.Data
  164.  
  165.         inc     [UDP_PACKETS_RX]
  166.  
  167.         pop     edi
  168.         add     esp, 4
  169.  
  170.         sub     esi, edi
  171.         xchg    esi, edi
  172.         jmp     socket_internal_receiver
  173.  
  174.  
  175.   .updateport:
  176.  
  177.         push    ebx
  178.         lea     ebx, [eax + SOCKET_head.lock]
  179.         call    wait_mutex
  180.         pop     ebx
  181.  
  182.         mov     si, [edx + UDP_Packet.SourcePort]
  183.         DEBUGF  1,"Changing remote port to: %x\n", si
  184.         mov     [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], si
  185.         inc     [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.firstpacket]
  186.  
  187.         jmp     .ok2
  188.  
  189.   .checksum_mismatch:
  190.  
  191.         DEBUGF  2,"UDP_Handler - checksum mismatch\n"
  192.  
  193.         mov     esi, [esp]
  194.         mov     ecx, [esp + 4]
  195.        @@:                         ;
  196.         lodsb                      ;
  197.         DEBUGF  2,"%x ", eax:2     ;
  198.         loop    @r                 ;
  199.  
  200.   .dump:
  201.         call    kernel_free
  202.         add     esp, 4 ; pop (balance stack)
  203.         DEBUGF  2,"UDP_Handler - dumping\n"
  204.  
  205.         ret
  206.  
  207.  
  208.  
  209.  
  210. ;-----------------------------------------------------------------
  211. ;
  212. ; UDP_socket_send
  213. ;
  214. ; IN: eax = socket pointer
  215. ;     ecx = number of bytes to send
  216. ;     esi = pointer to data
  217. ;
  218. ;-----------------------------------------------------------------
  219.  
  220. align 4
  221. UDP_socket_send:
  222.  
  223.         mov     edx, dword [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort] ; load local port and remote port at once
  224.         DEBUGF  1,"local port: %x, remote port: %x\n",\
  225.         [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort]:4,\
  226.         [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort]:4
  227.         mov     ebx, [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP]
  228.         mov     eax, [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
  229.  
  230.         DEBUGF  1,"Create UDP Packet (size=%u)\n",ecx
  231.  
  232.         mov     di , IP_PROTO_UDP
  233.         sub     esp, 8                                          ; reserve some place in stack for later
  234.                                                                 ; Create a part of the pseudoheader in stack,
  235.         push    dword IP_PROTO_UDP shl 8
  236.         add     ecx, UDP_Packet.Data
  237.  
  238. ; TODO: fill in:   dx  = fragment id
  239.  
  240.         push    edx esi
  241.         call    IPv4_create_packet                              ; TODO: figure out a way to choose between IPv4 and IPv6
  242.         cmp     edi, -1
  243.         je      .fail
  244.  
  245.         mov     [esp + 8 + 4], eax                              ; pointer to buffer start
  246.         mov     [esp + 8 + 4 + 4], edx                          ; buffer size
  247.  
  248.         rol     cx, 8
  249.         mov     [edi + UDP_Packet.Length], cx
  250.         mov     [esp + 8 + 2], cx
  251.         ror     cx, 8
  252.  
  253.         pop     esi
  254.         push    edi ecx
  255.         sub     ecx, UDP_Packet.Data
  256.         add     edi, UDP_Packet.Data
  257.         shr     ecx, 2
  258.         rep     movsd
  259.         mov     ecx, [esp]
  260.         and     ecx, 3
  261.         rep     movsb
  262.         pop     ecx edi
  263.  
  264.         pop     dword [edi + UDP_Packet.SourcePort]             ; fill in both portnumbers
  265.         mov     [edi + UDP_Packet.Checksum], 0                  ; set it to zero, to calculate checksum
  266.  
  267. ; Checksum for UDP header + data
  268.         xor     edx, edx
  269.         mov     esi, edi
  270.         call    checksum_1
  271. ; Checksum for pseudoheader
  272.         pushd   [edi-4] ; destination address           ; TODO: fix this, IPv4 packet could have options..
  273.         pushd   [edi-8] ; source address
  274.         call    checksum_pseudoheader
  275. ; Now create the final checksum and store it in UDP header
  276.         call    checksum_2
  277.         mov     [edi + UDP_Packet.Checksum], dx
  278.  
  279.         inc     [UDP_PACKETS_TX]
  280.  
  281.         DEBUGF  1,"Sending UDP Packet to device %x\n", ebx      ;
  282.         jmp     ETH_sender                                     ;
  283.  
  284.   .fail:
  285.         ; todo: queue the packet
  286.         add     esp, 8+12+8
  287.         ret
  288.  
  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.         add     eax, UDP_PACKETS_TX
  323.         mov     eax, [eax]
  324.         ret
  325.  
  326. .packets_rx:
  327.         add     eax, UDP_PACKETS_RX
  328.         mov     eax, [eax]
  329.         ret
  330.