Subversion Repositories Kolibri OS

Rev

Rev 3601 | Rev 3647 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2010. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;  ICMP.INC                                                       ;;
  7. ;;                                                                 ;;
  8. ;;  Part of the tcp/ip network stack for KolibriOS                 ;;
  9. ;;                                                                 ;;
  10. ;;  Based on the work of [Johnny_B] and [smb]                      ;;
  11. ;;                                                                 ;;
  12. ;;    Written by hidnplayr@kolibrios.org                           ;;
  13. ;;                                                                 ;;
  14. ;;          GNU GENERAL PUBLIC LICENSE                             ;;
  15. ;;             Version 2, June 1991                                ;;
  16. ;;                                                                 ;;
  17. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  18.  
  19. $Revision: 2924 $
  20.  
  21. ; ICMP types & codes
  22.  
  23. ICMP_ECHOREPLY                  = 0               ; echo reply message
  24.  
  25. ICMP_UNREACH                    = 3
  26. ICMP_UNREACH_NET                = 0               ; bad net
  27. ICMP_UNREACH_HOST               = 1               ; bad host
  28. ICMP_UNREACH_PROTOCOL           = 2               ; bad protocol
  29. ICMP_UNREACH_PORT               = 3               ; bad port
  30. ICMP_UNREACH_NEEDFRAG           = 4               ; IP_DF caused drop
  31. ICMP_UNREACH_SRCFAIL            = 5               ; src route failed
  32. ICMP_UNREACH_NET_UNKNOWN        = 6               ; unknown net
  33. ICMP_UNREACH_HOST_UNKNOWN       = 7               ; unknown host
  34. ICMP_UNREACH_ISOLATED           = 8               ; src host isolated
  35. ICMP_UNREACH_NET_PROHIB         = 9               ; prohibited access
  36. ICMP_UNREACH_HOST_PROHIB        = 10              ; ditto
  37. ICMP_UNREACH_TOSNET             = 11              ; bad tos for net
  38. ICMP_UNREACH_TOSHOST            = 12              ; bad tos for host
  39. ICMP_UNREACH_FILTER_PROHIB      = 13              ; admin prohib
  40. ICMP_UNREACH_HOST_PRECEDENCE    = 14              ; host prec vio.
  41. ICMP_UNREACH_PRECEDENCE_CUTOFF  = 15              ; prec cutoff
  42.  
  43. ICMP_SOURCEQUENCH               = 4               ; Packet lost, slow down
  44.  
  45. ICMP_REDIRECT                   = 5               ; shorter route, codes:
  46. ICMP_REDIRECT_NET               = 0               ; for network
  47. ICMP_REDIRECT_HOST              = 1               ; for host
  48. ICMP_REDIRECT_TOSNET            = 2               ; for tos and net
  49. ICMP_REDIRECT_TOSHOST           = 3               ; for tos and host
  50.  
  51. ICMP_ALTHOSTADDR                = 6               ; alternate host address
  52. ICMP_ECHO                       = 8               ; echo service
  53. ICMP_ROUTERADVERT               = 9               ; router advertisement
  54. ICMP_ROUTERADVERT_NORMAL        = 0                  ; normal advertisement
  55. ICMP_ROUTERADVERT_NOROUTE_COMMON= 16         ; selective routing
  56.  
  57. ICMP_ROUTERSOLICIT              = 10              ; router solicitation
  58. ICMP_TIMXCEED                   = 11              ; time exceeded, code:
  59. ICMP_TIMXCEED_INTRANS           = 0               ; ttl==0 in transit
  60. ICMP_TIMXCEED_REASS             = 1               ; ttl==0 in reass
  61.  
  62. ICMP_PARAMPROB                  = 12               ; ip header bad
  63. ICMP_PARAMPROB_ERRATPTR         = 0            ; error at param ptr
  64. ICMP_PARAMPROB_OPTABSENT        = 1            ; req. opt. absent
  65. ICMP_PARAMPROB_LENGTH           = 2            ; bad length
  66.  
  67. ICMP_TSTAMP                     = 13              ; timestamp request
  68. ICMP_TSTAMPREPLY                = 14              ; timestamp reply
  69. ICMP_IREQ                       = 15              ; information request
  70. ICMP_IREQREPLY                  = 16              ; information reply
  71. ICMP_MASKREQ                    = 17              ; address mask request
  72. ICMP_MASKREPLY                  = 18              ; address mask reply
  73. ICMP_TRACEROUTE                 = 30              ; traceroute
  74. ICMP_DATACONVERR                = 31              ; data conversion error
  75. ICMP_MOBILE_REDIRECT            = 32              ; mobile host redirect
  76. ICMP_IPV6_WHEREAREYOU           = 33              ; IPv6 where-are-you
  77. ICMP_IPV6_IAMHERE               = 34              ; IPv6 i-am-here
  78. ICMP_MOBILE_REGREQUEST          = 35              ; mobile registration req
  79. ICMP_MOBILE_REGREPLY            = 36              ; mobile registreation reply
  80. ICMP_SKIP                       = 39              ; SKIP
  81.  
  82. ICMP_PHOTURIS                   = 40              ; Photuris
  83. ICMP_PHOTURIS_UNKNOWN_INDEX     = 1                ; unknown sec index
  84. ICMP_PHOTURIS_AUTH_FAILED       = 2                ; auth failed
  85. ICMP_PHOTURIS_DECRYPT_FAILED    = 3                ; decrypt failed
  86.  
  87.  
  88.  
  89. struct  ICMP_header
  90.  
  91.         Type                    db ?
  92.         Code                    db ?
  93.         Checksum                dw ?
  94.         Identifier              dw ?
  95.         SequenceNumber          dw ?
  96.  
  97. ends
  98.  
  99.  
  100. align 4
  101. uglobal
  102.         ICMP_PACKETS_TX         rd NET_DEVICES_MAX
  103.         ICMP_PACKETS_RX         rd NET_DEVICES_MAX
  104. endg
  105.  
  106.  
  107.  
  108. ;-----------------------------------------------------------------
  109. ;
  110. ; ICMP_init
  111. ;
  112. ;-----------------------------------------------------------------
  113.  
  114. macro ICMP_init {
  115.  
  116.         xor     eax, eax
  117.         mov     edi, ICMP_PACKETS_TX
  118.         mov     ecx, 2*NET_DEVICES_MAX
  119.         rep     stosd
  120.  
  121. }
  122.  
  123.  
  124. ;-----------------------------------------------------------------
  125. ;
  126. ; ICMP_input:
  127. ;
  128. ;  This procedure will send reply's to ICMP echo's
  129. ;   and insert packets into sockets when needed
  130. ;
  131. ;  IN:  Pointer to buffer in [esp]
  132. ;       size of buffer in [esp+4]
  133. ;       ebx = pointer to device struct
  134. ;       ecx = ICMP Packet size
  135. ;       esi = ptr to ICMP Packet data
  136. ;       edi = ptr to ipv4 source and dest address
  137. ;
  138. ;  OUT: /
  139. ;
  140. ;-----------------------------------------------------------------
  141. align 4
  142. ICMP_input:
  143.  
  144.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input:\n"
  145.  
  146. ; First, check the checksum (altough some implementations ignore it)
  147.  
  148.         push    esi ecx
  149.         push    [esi + ICMP_header.Checksum]
  150.         mov     [esi + ICMP_header.Checksum], 0
  151.         xor     edx, edx
  152.         call    checksum_1
  153.         call    checksum_2
  154.         pop     si
  155.         cmp     dx, si
  156.         pop     ecx edx
  157.         jne     .checksum_mismatch
  158.  
  159. ; Check packet type
  160.  
  161.         cmp     [edx + ICMP_header.Type], ICMP_ECHO             ; Is this an echo request?
  162.         jne     .check_sockets
  163.  
  164. ; Update stats (and validate device ptr)
  165.         call    NET_ptr_to_num4
  166.         cmp     edi, -1
  167.         je      .dump
  168.         inc     [ICMP_PACKETS_RX + edi]
  169.  
  170. ; We well re-use the packet so we can create the response as fast as possible
  171. ; Notice: this only works on pure ethernet
  172.  
  173.         DEBUGF  DEBUG_NETWORK_VERBOSE, "got echo request\n"
  174.         mov     [edx + ICMP_header.Type], ICMP_ECHOREPLY        ; Change Packet type to reply
  175.  
  176.         mov     esi, [esp]                                      ; Start of buffer
  177.         cmp     ebx, LOOPBACK_DEVICE
  178.         je      .loopback
  179.  
  180. ; FIXME: dont assume device is an ethernet device!
  181.  
  182. ; exchange dest and source address in IP header
  183. ; exchange dest and source MAC in ETH header
  184.         push    dword [esi + ETH_header.DstMAC]
  185.         push    dword [esi + ETH_header.SrcMAC]
  186.         pop     dword [esi + ETH_header.DstMAC]
  187.         pop     dword [esi + ETH_header.SrcMAC]
  188.         push    word [esi + ETH_header.DstMAC + 4]
  189.         push    word [esi + ETH_header.SrcMAC + 4]
  190.         pop     word [esi + ETH_header.DstMAC + 4]
  191.         pop     word [esi + ETH_header.SrcMAC + 4]
  192.         add     esi, sizeof.ETH_header-4
  193.  
  194.   .loopback:
  195.         add     esi, 4
  196.         push    [esi + IPv4_header.SourceAddress]
  197.         push    [esi + IPv4_header.DestinationAddress]
  198.         pop     [esi + IPv4_header.SourceAddress]
  199.         pop     [esi + IPv4_header.DestinationAddress]
  200.  
  201. ; Recalculate ip header checksum
  202.         movzx   ecx, [esi + IPv4_header.VersionAndIHL]          ; Calculate IP Header length by using IHL field
  203.         and     ecx, 0x0f
  204.         shl     cx, 2
  205.         mov     edi, ecx                                        ; IP header length
  206.         mov     eax, edx                                        ; ICMP packet start addr
  207.  
  208.         push    esi                                             ; Calculate the IP checksum
  209.         xor     edx, edx                                        ;
  210.         call    checksum_1                                      ;
  211.         call    checksum_2                                      ;
  212.         pop     esi                                             ;
  213.         mov     [esi + IPv4_header.HeaderChecksum], dx          ;
  214.  
  215. ; Recalculate ICMP CheckSum
  216.         movzx   ecx, [esi + IPv4_header.TotalLength]            ; Find length of IP Packet
  217.         xchg    ch, cl                                          ;
  218.         sub     ecx, edi                                        ; IP packet length - IP header length = ICMP packet length
  219.  
  220.         mov     esi, eax                                        ; Calculate ICMP checksum
  221.         xor     edx, edx                                        ;
  222.         call    checksum_1                                      ;
  223.         call    checksum_2                                      ;
  224.         mov     [eax + ICMP_header.Checksum], dx                ;
  225.  
  226. ; Transmit the packet (notice that packet ptr and packet size have been on stack since start of the procedure!)
  227.         call    [ebx + NET_DEVICE.transmit]
  228.         test    eax, eax
  229.         jnz     @f
  230.         call    NET_ptr_to_num4
  231.         inc     [UDP_PACKETS_TX + edi]
  232.        @@:
  233.         ret
  234.  
  235.  
  236.  
  237.  
  238.        .check_sockets:
  239.         ; Look for an open ICMP socket
  240.  
  241.         mov     esi, [edi]              ; ipv4 source address
  242.         mov     eax, net_sockets
  243.   .try_more:
  244. ;        mov      , [edx + ICMP_header.Identifier]
  245.   .next_socket:
  246.         mov     eax, [eax + SOCKET.NextPtr]
  247.         or      eax, eax
  248.         jz      .dump
  249.  
  250.         cmp     [eax + SOCKET.Domain], AF_INET4
  251.         jne     .next_socket
  252.  
  253.         cmp     [eax + SOCKET.Protocol], IP_PROTO_ICMP
  254.         jne     .next_socket
  255.  
  256.         cmp     [eax + IP_SOCKET.RemoteIP], esi
  257.         jne     .next_socket
  258.  
  259. ;        cmp     [eax + ICMP_SOCKET.Identifier],
  260. ;        jne     .next_socket
  261.  
  262. ; Update stats (and validate device ptr)
  263.         call    NET_ptr_to_num4
  264.         cmp     edi, -1
  265.         je      .dump
  266.         inc     [ICMP_PACKETS_RX + edi]
  267.  
  268.         DEBUGF  DEBUG_NETWORK_VERBOSE, "socket=%x\n", eax
  269.  
  270.         pusha
  271.         lea     ecx, [eax + SOCKET.mutex]
  272.         call    mutex_lock
  273.         popa
  274.  
  275.         mov     esi, edx
  276.         jmp     SOCKET_input
  277.  
  278.  
  279.   .checksum_mismatch:
  280.         DEBUGF  DEBUG_NETWORK_VERBOSE, "checksum mismatch\n"
  281.  
  282.   .dump:
  283.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input: dumping\n"
  284.  
  285.         call    kernel_free
  286.         add     esp, 4 ; pop (balance stack)
  287.  
  288.         ret
  289.  
  290.  
  291. ;-----------------------------------------------------------------
  292. ;
  293. ; ICMP_output
  294. ;
  295. ; IN:  eax = dest ip
  296. ;      ebx = source ip
  297. ;      ecx = data length
  298. ;      dh  = type
  299. ;      dl  = code
  300. ;      esi = data offset
  301. ;      edi = identifier shl 16 + sequence number
  302. ;
  303. ;-----------------------------------------------------------------
  304. align 4
  305. ICMP_output:
  306.  
  307.         DEBUGF  DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet\n"
  308.  
  309.         push    esi edi dx
  310.  
  311.         mov     edx, [eax + IP_SOCKET.LocalIP]
  312.         mov     eax, [eax + IP_SOCKET.RemoteIP]
  313.         add     ecx, sizeof.ICMP_header
  314.         mov     di, IP_PROTO_ICMP SHL 8 + 128           ; TTL
  315.         call    IPv4_output
  316.         jz      .exit
  317.  
  318.         DEBUGF  DEBUG_NETWORK_VERBOSE, "full icmp packet size: %u\n", edx
  319.  
  320.         pop     word [edi + ICMP_header.Type]           ; Write both type and code bytes at once
  321.         pop     dword [edi + ICMP_header.Identifier]    ; identifier and sequence number
  322.         mov     [edi + ICMP_header.Checksum], 0
  323.  
  324.         push    ebx ecx edx
  325.         mov     esi, edi
  326.         xor     edx, edx
  327.         call    checksum_1
  328.         call    checksum_2
  329.         mov     [edi + ICMP_header.Checksum], dx
  330.         pop     edx ecx ebx esi
  331.  
  332.         sub     ecx, sizeof.ICMP_header
  333.         add     edi, sizeof.ICMP_header
  334.         push    cx
  335.         shr     cx, 2
  336.         rep     movsd
  337.         pop     cx
  338.         and     cx, 3
  339.         rep     movsb
  340.  
  341.         sub     edi, edx                                ;;; TODO: find a better way to remember start of packet
  342.         push    edx edi
  343.         DEBUGF  DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n"
  344.         call    [ebx + NET_DEVICE.transmit]
  345.         test    eax, eax
  346.         jnz     @f
  347.         call    NET_ptr_to_num4
  348.         inc     [ICMP_PACKETS_TX + edi]
  349.        @@:
  350.         ret
  351.   .exit:
  352.         DEBUGF  DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n"
  353.         add     esp, 2*4 + 2
  354.         ret
  355.  
  356.  
  357.  
  358.  
  359. ;-----------------------------------------------------------------
  360. ;
  361. ; ICMP_output
  362. ;
  363. ; IN:  eax = socket ptr
  364. ;      ecx = data length
  365. ;      esi = data offset
  366. ;
  367. ;-----------------------------------------------------------------
  368. align 4
  369. ICMP_output_raw:
  370.  
  371.         DEBUGF  DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet for socket %x, data ptr=%x\n", eax, edx
  372.  
  373.         push    edx
  374.  
  375.         mov     di, IP_PROTO_ICMP SHL 8 + 128  ; TTL
  376.         mov     edx, [eax + IP_SOCKET.LocalIP]
  377.         mov     eax, [eax + IP_SOCKET.RemoteIP]
  378.         call    IPv4_output
  379.         jz      .exit
  380.  
  381.         pop     esi
  382.         push    edx
  383.         push    eax
  384.  
  385.         push    edi ecx
  386.         DEBUGF  DEBUG_NETWORK_VERBOSE, "copying %u bytes from %x to %x\n", ecx, esi, edi
  387.         rep     movsb
  388.         pop     ecx edi
  389.  
  390.         mov     [edi + ICMP_header.Checksum], 0
  391.  
  392.         mov     esi, edi
  393.         xor     edx, edx
  394.         call    checksum_1
  395.         call    checksum_2
  396.         mov     [edi + ICMP_header.Checksum], dx
  397.  
  398.         DEBUGF  DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n"
  399.         call    [ebx + NET_DEVICE.transmit]
  400.         test    eax, eax
  401.         jnz     @f
  402.         call    NET_ptr_to_num4
  403.         inc     [ICMP_PACKETS_TX + edi]
  404.        @@:
  405.         ret
  406.   .exit:
  407.         DEBUGF  DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n"
  408.         add     esp, 4
  409.         ret
  410.  
  411.  
  412.  
  413.  
  414. ;-----------------------------------------------------------------
  415. ;
  416. ; ICMP_API
  417. ;
  418. ; This function is called by system function 75
  419. ;
  420. ; IN:  subfunction number in bl
  421. ;      device number in bh
  422. ;      ecx, edx, .. depends on subfunction
  423. ;
  424. ; OUT:
  425. ;
  426. ;-----------------------------------------------------------------
  427. align 4
  428. ICMP_api:
  429.  
  430.         movzx   eax, bh
  431.         shl     eax, 2
  432.  
  433.         test    bl, bl
  434.         jz      .packets_tx     ; 0
  435.         dec     bl
  436.         jz      .packets_rx     ; 1
  437.  
  438.   .error:
  439.         mov     eax, -1
  440.         ret
  441.  
  442.   .packets_tx:
  443.         mov     eax, [ICMP_PACKETS_TX + eax]
  444.         ret
  445.  
  446.   .packets_rx:
  447.         mov     eax, [ICMP_PACKETS_RX + eax]
  448.         ret
  449.