Subversion Repositories Kolibri OS

Rev

Rev 7536 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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