Subversion Repositories Kolibri OS

Rev

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