Subversion Repositories Kolibri OS

Rev

Rev 7679 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2019. 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: 7682 $
  18.  
  19.  
  20. struct  UDP_header
  21.  
  22.         SourcePort              dw  ?
  23.         DestinationPort         dw  ?
  24.         Length                  dw  ?  ; Length of (UDP Header + Data)
  25.         Checksum                dw  ?
  26.  
  27. ends
  28.  
  29.  
  30. uglobal
  31. align 4
  32.  
  33.         UDP_packets_tx          rd  NET_DEVICES_MAX
  34.         UDP_packets_rx          rd  NET_DEVICES_MAX
  35.  
  36. endg
  37.  
  38.  
  39. ;-----------------------------------------------------------------;
  40. ;                                                                 ;
  41. ; udp_init: 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*NET_DEVICES_MAX
  49.         rep stosd
  50. }
  51.  
  52.  
  53. macro   udp_checksum    IP1, IP2  { ; esi = ptr to udp packet, ecx = packet size, destroys: ecx, edx
  54.  
  55. ; Pseudoheader
  56.         mov     edx, IP_PROTO_UDP
  57.  
  58.         add     dl, byte[IP1+1]
  59.         adc     dh, byte[IP1+0]
  60.         adc     dl, byte[IP1+3]
  61.         adc     dh, byte[IP1+2]
  62.  
  63.         adc     dl, byte[IP2+1]
  64.         adc     dh, byte[IP2+0]
  65.         adc     dl, byte[IP2+3]
  66.         adc     dh, byte[IP2+2]
  67.  
  68.         adc     dl, cl ; byte[esi+UDP_header.Length+1]
  69.         adc     dh, ch ; byte[esi+UDP_header.Length+0]
  70.  
  71. ; Done with pseudoheader, now do real header
  72.         adc     dl, byte[esi+UDP_header.SourcePort+1]
  73.         adc     dh, byte[esi+UDP_header.SourcePort+0]
  74.  
  75.         adc     dl, byte[esi+UDP_header.DestinationPort+1]
  76.         adc     dh, byte[esi+UDP_header.DestinationPort+0]
  77.  
  78.         adc     dl, byte[esi+UDP_header.Length+1]
  79.         adc     dh, byte[esi+UDP_header.Length+0]
  80.  
  81.         adc     edx, 0
  82.  
  83. ; Done with header, now do data
  84.         push    esi
  85.         movzx   ecx, [esi+UDP_header.Length]
  86.         rol     cx , 8
  87.         sub     cx , sizeof.UDP_header
  88.         add     esi, sizeof.UDP_header
  89.  
  90.         call    checksum_1
  91.         call    checksum_2
  92.         pop     esi
  93.  
  94.         add     [esi+UDP_header.Checksum], dx   ; this final instruction will set or clear ZF :)
  95.  
  96. }
  97.  
  98.  
  99. ;-----------------------------------------------------------------;
  100. ;                                                                 ;
  101. ; udp_input: Inject the UDP data in the application sockets.      ;
  102. ;                                                                 ;
  103. ;   IN: [esp] = ptr to buffer                                     ;
  104. ;       ebx = ptr to device struct                                ;
  105. ;       ecx = UDP packet size                                     ;
  106. ;       edx = ptr to IPv4 header                                  ;
  107. ;       esi = ptr to UDP packet data                              ;
  108. ;       edi = interface number*4                                  ;
  109. ;                                                                 ;
  110. ;  OUT: /                                                         ;
  111. ;                                                                 ;
  112. ;-----------------------------------------------------------------;
  113. align 4
  114. udp_input:
  115.  
  116.         DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_input: size=%u\n", ecx
  117.  
  118.         ; First validate, checksum
  119.  
  120.         neg     [esi + UDP_header.Checksum]     ; substract checksum from 0
  121.         jz      .no_checksum                    ; if checksum is zero, it is considered valid
  122.  
  123.         ; otherwise, we will re-calculate the checksum and add it to this value, thus creating 0 when it is correct
  124.  
  125.         mov     eax, edx
  126.         udp_checksum (eax+IPv4_header.SourceAddress), (eax+IPv4_header.DestinationAddress)
  127.         jnz     .checksum_mismatch
  128.  
  129.   .no_checksum:
  130.         DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_input: checksum ok\n"
  131.  
  132.         ; Convert length to little endian
  133.  
  134.         rol     [esi + UDP_header.Length], 8
  135.  
  136.         ; Look for a socket where
  137.         ; IP Packet UDP Destination Port = local Port
  138.         ; IP Packet SA = Remote IP
  139.  
  140.         pusha
  141.         mov     ecx, socket_mutex
  142.         call    mutex_lock
  143.         popa
  144.  
  145.         mov     cx, [esi + UDP_header.SourcePort]
  146.         mov     dx, [esi + UDP_header.DestinationPort]
  147.         mov     eax, net_sockets
  148.   .next_socket:
  149.         mov     eax, [eax + SOCKET.NextPtr]
  150.         or      eax, eax
  151.         jz      .unlock_dump
  152.  
  153.         cmp     [eax + SOCKET.Domain], AF_INET4
  154.         jne     .next_socket
  155.  
  156.         cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
  157.         jne     .next_socket
  158.  
  159.         cmp     [eax + UDP_SOCKET.LocalPort], dx
  160.         jne     .next_socket
  161.  
  162.         DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_input: socket=%x\n", eax
  163.  
  164.         pusha
  165.         mov     ecx, socket_mutex
  166.         call    mutex_unlock
  167.         popa
  168.  
  169.         ;;; TODO: when packet is processed, check more sockets?!
  170.  
  171. ; FIXME: check remote IP if possible
  172. ;
  173. ;        cmp     [eax + IP_SOCKET.RemoteIP], 0xffffffff
  174. ;        je      @f
  175. ;        cmp     [eax + IP_SOCKET.RemoteIP],
  176. ;        jne     .next_socket
  177. ;       @@:
  178.  
  179.         cmp     [eax + UDP_SOCKET.RemotePort], 0
  180.         je      .updateport
  181.  
  182.         cmp     [eax + UDP_SOCKET.RemotePort], cx
  183.         jne     .dump
  184.  
  185.         pusha
  186.         lea     ecx, [eax + SOCKET.mutex]
  187.         call    mutex_lock
  188.         popa
  189.  
  190.   .updatesock:
  191.         inc     [UDP_packets_rx + edi]
  192.  
  193.         movzx   ecx, [esi + UDP_header.Length]
  194.         sub     ecx, sizeof.UDP_header
  195.         add     esi, sizeof.UDP_header
  196.  
  197.         jmp     socket_input
  198.  
  199.   .updateport:
  200.         pusha
  201.         lea     ecx, [eax + SOCKET.mutex]
  202.         call    mutex_lock
  203.         popa
  204.  
  205.         DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_input: new remote port=%x\n", cx ; FIXME: find a way to print big endian values with debugf
  206.         mov     [eax + UDP_SOCKET.RemotePort], cx
  207.         jmp     .updatesock
  208.  
  209.   .unlock_dump:
  210.         pusha
  211.         mov     ecx, socket_mutex
  212.         call    mutex_unlock
  213.         popa
  214.  
  215.         DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_input: no socket found\n"
  216.         jmp     .dump
  217.  
  218.   .checksum_mismatch:
  219.         DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_input: checksum mismatch\n"
  220.  
  221.   .dump:
  222.         DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_input: dumping\n"
  223.         call    net_buff_free
  224.         ret
  225.  
  226.  
  227.  
  228. ;-----------------------------------------------------------------;
  229. ;                                                                 ;
  230. ; udp_output: Create an UDP packet.                               ;
  231. ;                                                                 ;
  232. ;  IN:  eax = socket pointer                                      ;
  233. ;       ecx = number of bytes to send                             ;
  234. ;       esi = pointer to data                                     ;
  235. ;                                                                 ;
  236. ; OUT:  eax = -1 on error                                         ;
  237. ;                                                                 ;
  238. ;-----------------------------------------------------------------;
  239.  
  240. align 4
  241. udp_output:
  242.  
  243.         DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_output: socket=%x bytes=%u data_ptr=%x\n", eax, ecx, esi
  244.  
  245.         mov     dx, [eax + UDP_SOCKET.RemotePort]
  246.         DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_output: remote port=%x, ", dx    ; FIXME: find a way to print big endian values with debugf
  247.         rol     edx, 16
  248.         mov     dx, [eax + UDP_SOCKET.LocalPort]
  249.         DEBUGF  DEBUG_NETWORK_VERBOSE, "local port=%x\n", dx
  250.  
  251.         sub     esp, 4                                          ; Data ptr will be placed here
  252.         push    edx esi
  253.         mov     ebx, [eax + IP_SOCKET.device]
  254.         mov     edx, [eax + IP_SOCKET.LocalIP]
  255.         mov     edi, [eax + IP_SOCKET.RemoteIP]
  256.         mov     al, [eax + IP_SOCKET.ttl]
  257.         mov     ah, IP_PROTO_UDP
  258.         add     ecx, sizeof.UDP_header
  259.         call    ipv4_output
  260.         jz      .fail
  261.         mov     [esp + 8], eax                                  ; pointer to buffer start
  262.  
  263.         mov     [edi + UDP_header.Length], cx
  264.         rol     [edi + UDP_header.Length], 8
  265.  
  266.         pop     esi
  267.         push    edi ecx
  268.         sub     ecx, sizeof.UDP_header
  269.         add     edi, sizeof.UDP_header
  270.         shr     ecx, 2
  271.         rep movsd
  272.         mov     ecx, [esp]
  273.         and     ecx, 3
  274.         rep movsb
  275.         pop     ecx edi
  276.  
  277.         pop     dword [edi + UDP_header.SourcePort]
  278.  
  279. ; Checksum
  280.         mov     esi, edi
  281.         mov     [edi + UDP_header.Checksum], 0
  282.         udp_checksum (edi-4), (edi-8)                           ; FIXME: IPv4 packet could have options..
  283.  
  284.         DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_output: sending with device %x\n", ebx
  285.         call    [ebx + NET_DEVICE.transmit]
  286.         test    eax, eax
  287.         jnz     @f
  288.         call    net_ptr_to_num4
  289.         inc     [UDP_packets_tx + edi]
  290.        @@:
  291.  
  292.         ret
  293.  
  294.   .fail:
  295.         DEBUGF  DEBUG_NETWORK_ERROR, "UDP_output: failed\n"
  296.         add     esp, 4+4+8
  297.         or      eax, -1
  298.         ret
  299.  
  300.  
  301.  
  302.  
  303. ;-----------------------------------------------------------------;
  304. ;                                                                 ;
  305. ; udp_connect                                                     ;
  306. ;                                                                 ;
  307. ;   IN: eax = socket pointer                                      ;
  308. ;                                                                 ;
  309. ;  OUT: eax = 0 on success                                        ;
  310. ;       eax = -1 on error                                         ;
  311. ;       ebx = error code on error                                 ;
  312. ;                                                                 ;
  313. ;-----------------------------------------------------------------;
  314. align 4
  315. udp_connect:
  316.  
  317.         test    [eax + SOCKET.state], SS_ISCONNECTED
  318.         jz      @f
  319.         call    udp_disconnect
  320.   @@:
  321.  
  322.         push    eax edx
  323.         lea     ecx, [eax + SOCKET.mutex]
  324.         call    mutex_lock
  325.         pop     edx eax
  326.  
  327. ; Fill in remote port and IP
  328.         pushw   [edx + 2]
  329.         pop     [eax + UDP_SOCKET.RemotePort]
  330.  
  331.         pushd   [edx + 4]
  332.         pop     [eax + UDP_SOCKET.RemoteIP]
  333.  
  334. ; Find route to host
  335.         pusha
  336.         push    eax
  337.         mov     ebx, [eax + UDP_SOCKET.device]
  338.         mov     edx, [eax + UDP_SOCKET.LocalIP]
  339.         mov     eax, [eax + UDP_SOCKET.RemoteIP]
  340.         call    ipv4_route
  341.         test    eax, eax
  342.         jz      .enoroute
  343.         pop     eax
  344.         mov     ebx, [net_device_list + edi]
  345.         mov     [eax + UDP_SOCKET.device], ebx
  346.         mov     [eax + UDP_SOCKET.LocalIP], edx
  347.         popa
  348.  
  349. ; Find a local port, if user didnt define one
  350.         cmp     [eax + UDP_SOCKET.LocalPort], 0
  351.         jne     @f
  352.         call    socket_find_port
  353.        @@:
  354.  
  355.         push    eax
  356.         lea     ecx, [eax + SOCKET.mutex]
  357.         call    mutex_unlock
  358.         pop     eax
  359.  
  360.         call    socket_is_connected
  361.  
  362.         xor     eax, eax
  363.         ret
  364.  
  365.   .enoroute:
  366.         pop     eax
  367.  
  368.         push    eax
  369.         lea     ecx, [eax + SOCKET.mutex]
  370.         call    mutex_unlock
  371.         pop     eax
  372.  
  373.         popa
  374.         xor     eax, eax
  375.         dec     eax
  376.         mov     ebx, EADDRNOTAVAIL
  377.         ret
  378.  
  379.  
  380. ;-----------------------------------------------------------------;
  381. ;                                                                 ;
  382. ; UDP_disconnect                                                  ;
  383. ;                                                                 ;
  384. ;   IN: eax = socket pointer                                      ;
  385. ;                                                                 ;
  386. ;  OUT: eax = socket pointer                                      ;
  387. ;                                                                 ;
  388. ;-----------------------------------------------------------------;
  389. align 4
  390. udp_disconnect:
  391.  
  392.         ; TODO: remove the pending received data
  393.  
  394.         call    socket_is_disconnected
  395.  
  396.         ret
  397.  
  398.  
  399.  
  400.  
  401.  
  402. ;-----------------------------------------------------------------;
  403. ;                                                                 ;
  404. ; UDP_api: Part of system function 76                             ;
  405. ;                                                                 ;
  406. ;  IN: bl = subfunction number in bl                              ;
  407. ;      bh = device number in bh                                   ;
  408. ;      ecx, edx, .. depends on subfunction                        ;
  409. ;                                                                 ;
  410. ; OUT: depends on subfunction                                     ;
  411. ;                                                                 ;
  412. ;-----------------------------------------------------------------;
  413. align 4
  414. udp_api:
  415.  
  416.         movzx   eax, bh
  417.         shl     eax, 2
  418.  
  419.         test    bl, bl
  420.         jz      .packets_tx     ; 0
  421.         dec     bl
  422.         jz      .packets_rx     ; 1
  423.  
  424.   .error:
  425.         mov     eax, -1
  426.         ret
  427.  
  428.   .packets_tx:
  429.         mov     eax, [UDP_packets_tx + eax]
  430.         ret
  431.  
  432.   .packets_rx:
  433.         mov     eax, [UDP_packets_rx + eax]
  434.         ret
  435.