Subversion Repositories Kolibri OS

Rev

Rev 1473 | 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: 1482 $
  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\n", [edx+UDP_Packet.Checksum]:4
  78.  
  79. ; First validate, checksum:
  80.         cmp    [edx + UDP_Packet.Checksum], 0
  81.         jz     .no_checksum
  82.  
  83.         push    ecx edx
  84.  
  85.         push    esi
  86.         push    edi
  87.         mov     esi, edx
  88.         call    UDP_checksum
  89.  
  90.         pop     edx ecx
  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]
  126.         mov     esi, [ebx + ETH_FRAME.Data + IPv4_Packet.SourceAddress] ; get the Source address from the IP Packet   FIXME
  127.         cmp     [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], 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.   .checksum_mismatch:
  179.  
  180.         DEBUGF  2,"UDP_Handler - checksum mismatch\n"
  181.  
  182. ;        mov     esi, edx
  183. ;       @@:                         ;
  184. ;        lodsb                      ;
  185. ;        DEBUGF  2,"%x ", eax:2     ;
  186. ;        loop    @r                 ;
  187.  
  188.   .dump:
  189.         call    kernel_free
  190.         add     esp, 4 ; pop (balance stack)
  191.         DEBUGF  2,"UDP_Handler - dumping\n"
  192.  
  193.         ret
  194.  
  195.  
  196.  
  197.  
  198. ;-----------------------------------------------------------------
  199. ;
  200. ; UDP_socket_send
  201. ;
  202. ; IN: eax = socket pointer
  203. ;     ecx = number of bytes to send
  204. ;     esi = pointer to data
  205. ;
  206. ;-----------------------------------------------------------------
  207.  
  208. align 4
  209. UDP_socket_send:
  210.  
  211.         mov     edx, dword [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort] ; load local port and remote port at once
  212.         DEBUGF  1,"local port: %x, remote port: %x\n",\
  213.         [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort]:4,\
  214.         [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort]:4
  215.         mov     ebx, [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP]
  216.         mov     eax, [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
  217.  
  218.         DEBUGF  1,"Create UDP Packet (size=%u)\n",ecx
  219.  
  220.         mov     di , IP_PROTO_UDP
  221.         sub     esp, 8                                          ; Data ptr and data size will be placed here
  222.         add     ecx, UDP_Packet.Data
  223.  
  224. ; TODO: fill in:   dx  = fragment id
  225.  
  226.         push    edx esi
  227.         call    IPv4_create_packet                              ; TODO: figure out a way to choose between IPv4 and IPv6
  228.         cmp     edi, -1
  229.         je      .fail
  230.  
  231.         mov     [esp + 8], eax                                  ; pointer to buffer start
  232.         mov     [esp + 8 + 4], edx                              ; buffer size
  233.  
  234.         rol     cx, 8
  235.         mov     [edi + UDP_Packet.Length], cx
  236.         ror     cx, 8
  237.  
  238.         pop     esi
  239.         push    edi ecx
  240.         sub     ecx, UDP_Packet.Data
  241.         add     edi, UDP_Packet.Data
  242.         shr     ecx, 2
  243.         rep     movsd
  244.         mov     ecx, [esp]
  245.         and     ecx, 3
  246.         rep     movsb
  247.         pop     ecx edi
  248.  
  249.         pop     dword [edi + UDP_Packet.SourcePort]             ; fill in both portnumbers
  250.         mov     [edi + UDP_Packet.Checksum], 0                  ; set it to zero, to calculate checksum
  251.  
  252. ; Checksum
  253.         mov     esi, edi
  254.         pushd   [edi-4] ; destination address           ; TODO: fix this, IPv4 packet could have options..
  255.         pushd   [edi-8] ; source address
  256.         call    UDP_checksum
  257.  
  258.         inc     [UDP_PACKETS_TX]
  259.  
  260.         DEBUGF  1,"Sending UDP Packet to device %x\n", ebx
  261.         jmp     ETH_sender
  262.  
  263.   .fail:
  264.         ; todo: queue the packet
  265.         add     esp, 8+12+8
  266.         ret
  267.  
  268.  
  269.  
  270.  
  271. ;-----------------------------------------------------------------
  272. ;
  273. ; checksum_udp
  274. ;
  275. ; This is the fast procedure to create or check a UDP header
  276. ;  - To create a new checksum, the checksum field must be set to 0 before computation
  277. ;  - To check an existing checksum, leave the checksum as is,
  278. ;     and it will be 0 after this procedure, if it was correct
  279. ;
  280. ;  IN:  push source ip
  281. ;       push dest ip
  282. ;       esi = packet ptr
  283. ;
  284. ;  OUT: checksum is filled in in packet! (but also in dx)
  285. ;
  286. ;-----------------------------------------------------------------
  287.  
  288. align 4
  289. UDP_checksum:
  290.  
  291. ; Pseudoheader
  292.         mov     edx, IP_PROTO_UDP               ; NO shl 8 here ! (it took me ages to figure this one out)
  293.  
  294.         add     dl, [esp+1+4]
  295.         adc     dh, [esp+0+4]
  296.         adc     dl, [esp+3+4]
  297.         adc     dh, [esp+2+4]
  298.  
  299.         adc     dl, [esp+1+8]
  300.         adc     dh, [esp+0+8]
  301.         adc     dl, [esp+3+8]
  302.         adc     dh, [esp+2+8]
  303.  
  304.         adc     dl, byte[esi+UDP_Packet.Length+1]
  305.         adc     dh, byte[esi+UDP_Packet.Length+0]
  306.  
  307. ; Done with pseudoheader, now do real header
  308.         adc     dl, byte[esi+UDP_Packet.SourcePort+1]
  309.         adc     dh, byte[esi+UDP_Packet.SourcePort+0]
  310.  
  311.         adc     dl, byte[esi+UDP_Packet.DestinationPort+1]
  312.         adc     dh, byte[esi+UDP_Packet.DestinationPort+0]
  313.  
  314.         adc     dl, byte[esi+UDP_Packet.Length+1]
  315.         adc     dh, byte[esi+UDP_Packet.Length+0]
  316.  
  317.         adc     edx, 0
  318.  
  319. ; Done with header, now do data
  320.         push    esi
  321.         movzx   ecx, [esi+UDP_Packet.Length]
  322.         rol     cx , 8
  323.         sub     cx , UDP_Packet.Data
  324.         add     esi, UDP_Packet.Data
  325.  
  326.         call    checksum_1
  327.         call    checksum_2
  328.         pop     esi
  329.  
  330.         neg     [esi+UDP_Packet.Checksum]           ; zero will stay zero so we just get the checksum
  331.         add     [esi+UDP_Packet.Checksum], dx       ;  , else we will get (new checksum - old checksum) in the end, wich should be 0 :)
  332.  
  333.         ret     8
  334.  
  335.  
  336.  
  337.  
  338. ;---------------------------------------------------------------------------
  339. ;
  340. ; UDP_API
  341. ;
  342. ; This function is called by system function 75
  343. ;
  344. ; IN:  subfunction number in bl
  345. ;      device number in bh
  346. ;      ecx, edx, .. depends on subfunction
  347. ;
  348. ; OUT:
  349. ;
  350. ;---------------------------------------------------------------------------
  351.  
  352. align 4
  353. UDP_API:
  354.  
  355.         movzx   eax, bh
  356.         shl     eax, 2
  357.  
  358.         test    bl, bl
  359.         jz      .packets_tx     ; 0
  360.         dec     bl
  361.         jz      .packets_rx     ; 1
  362.  
  363. .error:
  364.         mov     eax, -1
  365.         ret
  366.  
  367. .packets_tx:
  368.         add     eax, UDP_PACKETS_TX
  369.         mov     eax, [eax]
  370.         ret
  371.  
  372. .packets_rx:
  373.         add     eax, UDP_PACKETS_RX
  374.         mov     eax, [eax]
  375.         ret
  376.