Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2015. 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: 6011 $
  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. struct  ICMP_header
  89.  
  90.         Type                    db ?
  91.         Code                    db ?
  92.         Checksum                dw ?
  93.         Identifier              dw ?
  94.         SequenceNumber          dw ?
  95.  
  96. ends
  97.  
  98.  
  99. uglobal
  100. align 4
  101.  
  102.         ICMP_PACKETS_TX         rd NET_DEVICES_MAX
  103.         ICMP_PACKETS_RX         rd NET_DEVICES_MAX
  104.  
  105. endg
  106.  
  107.  
  108.  
  109. ;-----------------------------------------------------------------;
  110. ;                                                                 ;
  111. ; ICMP_init                                                       ;
  112. ;                                                                 ;
  113. ;-----------------------------------------------------------------;
  114.  
  115. macro icmp_init {
  116.  
  117.         xor     eax, eax
  118.         mov     edi, ICMP_PACKETS_TX
  119.         mov     ecx, 2*NET_DEVICES_MAX
  120.         rep stosd
  121.  
  122. }
  123.  
  124.  
  125. ;-----------------------------------------------------------------;
  126. ;                                                                 ;
  127. ; icmp_input: Send a reply's to an ICMP echo or insert packets    ;
  128. ; into socket.                                                    ;
  129. ;                                                                 ;
  130. ;  IN:  [esp] = ptr to buffer                                     ;
  131. ;       ebx = ptr to device struct                                ;
  132. ;       ecx = ICMP Packet size                                    ;
  133. ;       edx = ptr to IPv4 header                                  ;
  134. ;       esi = ptr to ICMP Packet data                             ;
  135. ;       edi = interface number*4                                  ;
  136. ;                                                                 ;
  137. ;  OUT: /                                                         ;
  138. ;                                                                 ;
  139. ;-----------------------------------------------------------------;
  140. align 4
  141. icmp_input:
  142.  
  143.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input\n"
  144.  
  145. ; Dump all multicasts and broadcasts
  146.         mov     eax, [IP_LIST + edi]
  147.         cmp     eax, [edx + IPv4_header.DestinationAddress]
  148.         jne     .dump
  149.  
  150. ; Check the checksum
  151.         push    esi ecx edx
  152.         push    [esi + ICMP_header.Checksum]
  153.         mov     [esi + ICMP_header.Checksum], 0
  154.         xor     edx, edx
  155.         call    checksum_1
  156.         call    checksum_2
  157.         pop     si
  158.         cmp     dx, si
  159.         pop     edx ecx esi
  160.         jne     .checksum_mismatch
  161.  
  162.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input: Checksum OK\n"
  163.  
  164. ; Update stats
  165.         inc     [ICMP_PACKETS_RX + edi]
  166.  
  167. ; Is this an echo request?
  168.         cmp     [esi + ICMP_header.Type], ICMP_ECHO
  169.         je      .echo_request
  170.  
  171. ; Look for an open ICMP socket
  172.         pusha
  173.         mov     ecx, socket_mutex
  174.         call    mutex_lock
  175.         popa
  176.  
  177.         add     ecx, esi
  178.         sub     ecx, edx
  179.         mov     esi, edx
  180.         mov     eax, net_sockets
  181.   .next_socket:
  182.         mov     eax, [eax + SOCKET.NextPtr]
  183.         or      eax, eax
  184.         jz      .dump_
  185.  
  186.         cmp     [eax + SOCKET.Domain], AF_INET4
  187.         jne     .next_socket
  188.  
  189.         cmp     [eax + SOCKET.Protocol], IP_PROTO_ICMP
  190.         jne     .next_socket
  191.  
  192.         pusha
  193.         mov     ecx, socket_mutex
  194.         call    mutex_unlock
  195.         popa
  196.  
  197.         DEBUGF  DEBUG_NETWORK_VERBOSE, "socket=%x\n", eax
  198.  
  199.         pusha
  200.         lea     ecx, [eax + SOCKET.mutex]
  201.         call    mutex_lock
  202.         popa
  203.  
  204.         jmp     socket_input
  205.  
  206.  
  207.  
  208.   .echo_request:
  209.  
  210. ; We'll reuse the packet so we can create the response as fast as possible
  211.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP echo request\n"
  212.  
  213. ; Change Packet type to reply
  214.         mov     [esi + ICMP_header.Type], ICMP_ECHOREPLY
  215.  
  216.         mov     eax, [esp]
  217.         lea     esi, [eax + NET_BUFF.data]
  218.  
  219. ; Check frame type
  220.         cmp     [eax + NET_BUFF.type], NET_BUFF_ETH
  221.         jne     .not_ethernet
  222.  
  223. ; exchange dest and source MAC in ETH header
  224.         push    dword [esi + ETH_header.DstMAC]
  225.         push    dword [esi + ETH_header.SrcMAC]
  226.         pop     dword [esi + ETH_header.DstMAC]
  227.         pop     dword [esi + ETH_header.SrcMAC]
  228.         push    word [esi + ETH_header.DstMAC + 4]
  229.         push    word [esi + ETH_header.SrcMAC + 4]
  230.         pop     word [esi + ETH_header.DstMAC + 4]
  231.         pop     word [esi + ETH_header.SrcMAC + 4]
  232.         add     esi, sizeof.ETH_header
  233.  
  234.   .not_ethernet:
  235. ; Exchange dest and source address in IP header
  236.         push    [esi + IPv4_header.SourceAddress]
  237.         push    [esi + IPv4_header.DestinationAddress]
  238.         pop     [esi + IPv4_header.SourceAddress]
  239.         pop     [esi + IPv4_header.DestinationAddress]
  240.  
  241. ; Calculate IP header length
  242.         movzx   ecx, [esi + IPv4_header.VersionAndIHL]
  243.         and     ecx, 0x0f
  244.         shl     cx, 2
  245.         mov     edi, ecx                        ; put it in edi for later
  246.  
  247. ; Calculate IP checksum
  248.         mov     eax, esi
  249.         mov     [eax + IPv4_header.HeaderChecksum], 0
  250.         xor     edx, edx
  251.         call    checksum_1
  252.         call    checksum_2
  253.         mov     [eax + IPv4_header.HeaderChecksum], dx
  254.  
  255. ; Calculate ICMP packet length
  256.         movzx   ecx, [eax + IPv4_header.TotalLength]
  257.         xchg    ch, cl
  258.         sub     ecx, edi                        ; IP packet length - IP header length = ICMP packet length
  259.  
  260. ; Calculate ICMP checkSum
  261.         mov     eax, esi
  262.         mov     [esi + ICMP_header.Checksum], 0
  263.         xor     edx, edx
  264.         call    checksum_1
  265.         call    checksum_2
  266.         mov     [eax + ICMP_header.Checksum], dx
  267.  
  268. ; Transmit the frame
  269.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP transmitting reply\n"
  270.         call    [ebx + NET_DEVICE.transmit]
  271.         test    eax, eax
  272.         jnz     @f
  273.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP transmit failed\n"
  274.         call    net_ptr_to_num4
  275.         inc     [ICMP_PACKETS_TX + edi]
  276.        @@:
  277.         ret
  278.  
  279.   .dump_:
  280.         pusha
  281.         mov     ecx, socket_mutex
  282.         call    mutex_unlock
  283.         popa
  284.  
  285.         DEBUGF  DEBUG_NETWORK_ERROR, "ICMP_input: no socket found\n"
  286.         jmp     .dump
  287.  
  288.   .checksum_mismatch:
  289.         DEBUGF  DEBUG_NETWORK_ERROR, "ICMP_input: checksum mismatch\n"
  290.  
  291.   .dump:
  292.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input: dumping\n"
  293.         call    net_buff_free
  294.         ret
  295.  
  296.  
  297. if 0
  298. ;-----------------------------------------------------------------;
  299. ;                                                                 ;
  300. ; icmp_output                                                     ;
  301. ;                                                                 ;
  302. ; IN:   eax = dest ip                                             ;
  303. ;       bh  = type                                                ;
  304. ;       bl  = code                                                ;
  305. ;       ecx = data length                                         ;
  306. ;       edx = source ip                                           ;
  307. ;       esi = data offset                                         ;
  308. ;       edi = identifier shl 16 + sequence number                 ;
  309. ;                                                                 ;
  310. ;-----------------------------------------------------------------;
  311. align 4
  312. icmp_output:
  313.  
  314.         DEBUGF  DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet\n"
  315.  
  316.         push    esi edi bx
  317.         add     ecx, sizeof.ICMP_header
  318.         mov     di, IP_PROTO_ICMP SHL 8 + 128           ; TTL
  319.         call    IPv4_output
  320.         jz      .exit
  321.  
  322.         DEBUGF  DEBUG_NETWORK_VERBOSE, "full icmp packet size: %u\n", edx
  323.  
  324.         pop     word [edi + ICMP_header.Type]           ; Write both type and code bytes at once
  325.         pop     dword [edi + ICMP_header.Identifier]    ; identifier and sequence number
  326.         mov     [edi + ICMP_header.Checksum], 0
  327.  
  328.         push    ebx ecx edx
  329.         mov     esi, edi
  330.         xor     edx, edx
  331.         call    checksum_1
  332.         call    checksum_2
  333.         mov     [edi + ICMP_header.Checksum], dx
  334.         pop     edx ecx ebx esi
  335.  
  336.         sub     ecx, sizeof.ICMP_header
  337.         add     edi, sizeof.ICMP_header
  338.         push    cx
  339.         shr     cx, 2
  340.         rep movsd
  341.         pop     cx
  342.         and     cx, 3
  343.         rep movsb
  344.  
  345.         sub     edi, edx                                ;;; TODO: find a better way to remember start of packet
  346.         push    edx edi
  347.         DEBUGF  DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n"
  348.         call    [ebx + NET_DEVICE.transmit]
  349.         test    eax, eax
  350.         jnz     @f
  351.         call    NET_ptr_to_num4
  352.         inc     [ICMP_PACKETS_TX + edi]
  353.        @@:
  354.         ret
  355.   .exit:
  356.         DEBUGF  DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n"
  357.         add     esp, 2*4 + 2
  358.         ret
  359. end if
  360.  
  361.  
  362.  
  363.  
  364. ;-----------------------------------------------------------------;
  365. ;                                                                 ;
  366. ; icmp_output_raw                                                 ;
  367. ;                                                                 ;
  368. ;  IN:  eax = socket ptr                                          ;
  369. ;       ecx = data length                                         ;
  370. ;       edx = data pointer                                        ;
  371. ;                                                                 ;
  372. ;-----------------------------------------------------------------;
  373. align 4
  374. icmp_output_raw:
  375.  
  376.         DEBUGF  DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet for socket %x, data ptr=%x\n", eax, edx
  377.  
  378.         push    edx
  379.         mov     ebx, [eax + IP_SOCKET.device]
  380.         mov     edx, [eax + IP_SOCKET.LocalIP]
  381.         mov     edi, [eax + IP_SOCKET.RemoteIP]
  382.         mov     al, [eax + IP_SOCKET.ttl]
  383.         mov     ah, IP_PROTO_ICMP
  384.         call    ipv4_output
  385.         jz      .fail
  386.  
  387.         pop     esi
  388.         push    eax
  389.  
  390.         push    edi ecx
  391.         DEBUGF  DEBUG_NETWORK_VERBOSE, "copying %u bytes from %x to %x\n", ecx, esi, edi
  392.         rep movsb
  393.         pop     ecx edi
  394.  
  395.         mov     [edi + ICMP_header.Checksum], 0
  396.  
  397.         mov     esi, edi
  398.         xor     edx, edx
  399.         call    checksum_1
  400.         call    checksum_2
  401.         mov     [edi + ICMP_header.Checksum], dx
  402.  
  403.         DEBUGF  DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n"
  404.         call    [ebx + NET_DEVICE.transmit]
  405.         test    eax, eax
  406.         jnz     @f
  407.         call    net_ptr_to_num4
  408.         inc     [ICMP_PACKETS_TX + edi]
  409.   @@:
  410.         ret
  411.  
  412.   .fail:
  413.         pop     edx
  414.         DEBUGF  DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n"
  415.         or      eax, -1
  416.         mov     ebx, EMSGSIZE           ;;; FIXME
  417.         ret
  418.  
  419.  
  420.  
  421.  
  422. ;-----------------------------------------------------------------;
  423. ;                                                                 ;
  424. ; icmp_api: Part of system function 76.                           ;
  425. ;                                                                 ;
  426. ;  IN:  bl = subfunction number                                   ;
  427. ;       bh = device number                                        ;
  428. ;       ecx, edx, .. depends on subfunction                       ;
  429. ;                                                                 ;
  430. ; OUT:  depends on subfunction                                    ;
  431. ;                                                                 ;
  432. ;-----------------------------------------------------------------;
  433. align 4
  434. icmp_api:
  435.  
  436.         movzx   eax, bh
  437.         shl     eax, 2
  438.  
  439.         test    bl, bl
  440.         jz      .packets_tx     ; 0
  441.         dec     bl
  442.         jz      .packets_rx     ; 1
  443.  
  444.   .error:
  445.         mov     eax, -1
  446.         ret
  447.  
  448.   .packets_tx:
  449.         mov     eax, [ICMP_PACKETS_TX + eax]
  450.         ret
  451.  
  452.   .packets_rx:
  453.         mov     eax, [ICMP_PACKETS_RX + eax]
  454.         ret
  455.