Subversion Repositories Kolibri OS

Rev

Rev 9816 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
10051 ace_dent 3
;; Copyright (C) KolibriOS team 2004-2024. 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
 
19
 
20
; ICMP types & codes
21
 
6011 hidnplayr 22
ICMP_ECHOREPLY                  = 0             ; echo reply message
3545 hidnplayr 23
 
24
ICMP_UNREACH                    = 3
6011 hidnplayr 25
ICMP_UNREACH_NET                = 0             ; bad net
26
ICMP_UNREACH_HOST               = 1             ; bad host
27
ICMP_UNREACH_PROTOCOL           = 2             ; bad protocol
28
ICMP_UNREACH_PORT               = 3             ; bad port
29
ICMP_UNREACH_NEEDFRAG           = 4             ; IP_DF caused drop
30
ICMP_UNREACH_SRCFAIL            = 5             ; src route failed
31
ICMP_UNREACH_NET_UNKNOWN        = 6             ; unknown net
32
ICMP_UNREACH_HOST_UNKNOWN       = 7             ; unknown host
33
ICMP_UNREACH_ISOLATED           = 8             ; src host isolated
34
ICMP_UNREACH_NET_PROHIB         = 9             ; prohibited access
35
ICMP_UNREACH_HOST_PROHIB        = 10            ; ditto
36
ICMP_UNREACH_TOSNET             = 11            ; bad tos for net
37
ICMP_UNREACH_TOSHOST            = 12            ; bad tos for host
38
ICMP_UNREACH_FILTER_PROHIB      = 13            ; admin prohib
39
ICMP_UNREACH_HOST_PRECEDENCE    = 14            ; host prec vio.
40
ICMP_UNREACH_PRECEDENCE_CUTOFF  = 15            ; prec cutoff
3545 hidnplayr 41
 
6011 hidnplayr 42
ICMP_SOURCEQUENCH               = 4             ; Packet lost, slow down
3545 hidnplayr 43
 
6011 hidnplayr 44
ICMP_REDIRECT                   = 5             ; shorter route, codes:
45
ICMP_REDIRECT_NET               = 0             ; for network
46
ICMP_REDIRECT_HOST              = 1             ; for host
47
ICMP_REDIRECT_TOSNET            = 2             ; for tos and net
48
ICMP_REDIRECT_TOSHOST           = 3             ; for tos and host
3545 hidnplayr 49
 
6011 hidnplayr 50
ICMP_ALTHOSTADDR                = 6             ; alternate host address
51
ICMP_ECHO                       = 8             ; echo service
52
ICMP_ROUTERADVERT               = 9             ; router advertisement
53
ICMP_ROUTERADVERT_NORMAL        = 0             ; normal advertisement
54
ICMP_ROUTERADVERT_NOROUTE_COMMON= 16            ; selective routing
3545 hidnplayr 55
 
6011 hidnplayr 56
ICMP_ROUTERSOLICIT              = 10            ; router solicitation
57
ICMP_TIMXCEED                   = 11            ; time exceeded, code:
58
ICMP_TIMXCEED_INTRANS           = 0             ; ttl==0 in transit
59
ICMP_TIMXCEED_REASS             = 1             ; ttl==0 in reass
3545 hidnplayr 60
 
6011 hidnplayr 61
ICMP_PARAMPROB                  = 12            ; ip header bad
62
ICMP_PARAMPROB_ERRATPTR         = 0             ; error at param ptr
63
ICMP_PARAMPROB_OPTABSENT        = 1             ; req. opt. absent
64
ICMP_PARAMPROB_LENGTH           = 2             ; bad length
3545 hidnplayr 65
 
6011 hidnplayr 66
ICMP_TSTAMP                     = 13            ; timestamp request
67
ICMP_TSTAMPREPLY                = 14            ; timestamp reply
68
ICMP_IREQ                       = 15            ; information request
69
ICMP_IREQREPLY                  = 16            ; information reply
70
ICMP_MASKREQ                    = 17            ; address mask request
71
ICMP_MASKREPLY                  = 18            ; address mask reply
72
ICMP_TRACEROUTE                 = 30            ; traceroute
73
ICMP_DATACONVERR                = 31            ; data conversion error
74
ICMP_MOBILE_REDIRECT            = 32            ; mobile host redirect
75
ICMP_IPV6_WHEREAREYOU           = 33            ; IPv6 where-are-you
76
ICMP_IPV6_IAMHERE               = 34            ; IPv6 i-am-here
77
ICMP_MOBILE_REGREQUEST          = 35            ; mobile registration req
78
ICMP_MOBILE_REGREPLY            = 36            ; mobile registreation reply
79
ICMP_SKIP                       = 39            ; SKIP
3545 hidnplayr 80
 
6011 hidnplayr 81
ICMP_PHOTURIS                   = 40            ; Photuris
82
ICMP_PHOTURIS_UNKNOWN_INDEX     = 1             ; unknown sec index
83
ICMP_PHOTURIS_AUTH_FAILED       = 2             ; auth failed
84
ICMP_PHOTURIS_DECRYPT_FAILED    = 3             ; decrypt failed
3545 hidnplayr 85
 
86
 
87
struct  ICMP_header
88
 
89
        Type                    db ?
90
        Code                    db ?
91
        Checksum                dw ?
92
        Identifier              dw ?
93
        SequenceNumber          dw ?
94
 
95
ends
96
 
97
 
3698 hidnplayr 98
uglobal
3545 hidnplayr 99
align 4
3698 hidnplayr 100
 
7678 hidnplayr 101
        ICMP_packets_tx         rd NET_DEVICES_MAX
102
        ICMP_packets_rx         rd NET_DEVICES_MAX
3698 hidnplayr 103
 
3545 hidnplayr 104
endg
105
 
106
 
107
 
6011 hidnplayr 108
;-----------------------------------------------------------------;
109
;                                                                 ;
110
; ICMP_init                                                       ;
111
;                                                                 ;
112
;-----------------------------------------------------------------;
3545 hidnplayr 113
 
6011 hidnplayr 114
macro icmp_init {
3545 hidnplayr 115
 
116
        xor     eax, eax
7678 hidnplayr 117
        mov     edi, ICMP_packets_tx
3600 hidnplayr 118
        mov     ecx, 2*NET_DEVICES_MAX
3711 clevermous 119
        rep stosd
3545 hidnplayr 120
 
121
}
122
 
123
 
6011 hidnplayr 124
;-----------------------------------------------------------------;
125
;                                                                 ;
126
; icmp_input: Send a reply's to an ICMP echo or insert packets    ;
127
; into socket.                                                    ;
128
;                                                                 ;
129
;  IN:  [esp] = ptr to buffer                                     ;
130
;       ebx = ptr to device struct                                ;
131
;       ecx = ICMP Packet size                                    ;
132
;       edx = ptr to IPv4 header                                  ;
133
;       esi = ptr to ICMP Packet data                             ;
134
;       edi = interface number*4                                  ;
135
;                                                                 ;
136
;  OUT: /                                                         ;
137
;                                                                 ;
138
;-----------------------------------------------------------------;
3545 hidnplayr 139
align 4
6011 hidnplayr 140
icmp_input:
3545 hidnplayr 141
 
5522 hidnplayr 142
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input\n"
3545 hidnplayr 143
 
5842 hidnplayr 144
; Dump all multicasts and broadcasts
7678 hidnplayr 145
        mov     eax, [IPv4_address + edi]
5842 hidnplayr 146
        cmp     eax, [edx + IPv4_header.DestinationAddress]
147
        jne     .dump
148
 
5522 hidnplayr 149
; Check the checksum
5842 hidnplayr 150
        push    esi ecx edx
3545 hidnplayr 151
        push    [esi + ICMP_header.Checksum]
152
        mov     [esi + ICMP_header.Checksum], 0
153
        xor     edx, edx
154
        call    checksum_1
155
        call    checksum_2
156
        pop     si
157
        cmp     dx, si
5842 hidnplayr 158
        pop     edx ecx esi
3545 hidnplayr 159
        jne     .checksum_mismatch
160
 
5522 hidnplayr 161
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input: Checksum OK\n"
3643 hidnplayr 162
 
5522 hidnplayr 163
; Update stats
7678 hidnplayr 164
        inc     [ICMP_packets_rx + edi]
3643 hidnplayr 165
 
5522 hidnplayr 166
; Is this an echo request?
167
        cmp     [esi + ICMP_header.Type], ICMP_ECHO
168
        je      .echo_request
3545 hidnplayr 169
 
5522 hidnplayr 170
; Look for an open ICMP socket
3647 hidnplayr 171
        pusha
172
        mov     ecx, socket_mutex
173
        call    mutex_lock
174
        popa
175
 
5842 hidnplayr 176
        add     ecx, esi
177
        sub     ecx, edx
178
        mov     esi, edx
3545 hidnplayr 179
        mov     eax, net_sockets
180
  .next_socket:
181
        mov     eax, [eax + SOCKET.NextPtr]
182
        or      eax, eax
3647 hidnplayr 183
        jz      .dump_
3545 hidnplayr 184
 
185
        cmp     [eax + SOCKET.Domain], AF_INET4
186
        jne     .next_socket
187
 
188
        cmp     [eax + SOCKET.Protocol], IP_PROTO_ICMP
189
        jne     .next_socket
190
 
3647 hidnplayr 191
        pusha
192
        mov     ecx, socket_mutex
193
        call    mutex_unlock
194
        popa
195
 
3556 hidnplayr 196
        DEBUGF  DEBUG_NETWORK_VERBOSE, "socket=%x\n", eax
3545 hidnplayr 197
 
198
        pusha
199
        lea     ecx, [eax + SOCKET.mutex]
200
        call    mutex_lock
201
        popa
202
 
6011 hidnplayr 203
        jmp     socket_input
3545 hidnplayr 204
 
5522 hidnplayr 205
 
206
 
207
  .echo_request:
208
 
209
; We'll reuse the packet so we can create the response as fast as possible
210
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP echo request\n"
211
 
212
; Change Packet type to reply
213
        mov     [esi + ICMP_header.Type], ICMP_ECHOREPLY
214
 
215
        mov     eax, [esp]
7536 hidnplayr 216
        mov     esi, [eax + NET_BUFF.offset]
217
        add     esi, eax
5522 hidnplayr 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"
6011 hidnplayr 274
        call    net_ptr_to_num4
7678 hidnplayr 275
        inc     [ICMP_packets_tx + edi]
276
        inc     [IPv4_packets_tx + edi]
5522 hidnplayr 277
       @@:
278
        ret
279
 
3647 hidnplayr 280
  .dump_:
281
        pusha
282
        mov     ecx, socket_mutex
283
        call    mutex_unlock
284
        popa
285
 
4892 hidnplayr 286
        DEBUGF  DEBUG_NETWORK_ERROR, "ICMP_input: no socket found\n"
3647 hidnplayr 287
        jmp     .dump
288
 
3545 hidnplayr 289
  .checksum_mismatch:
4892 hidnplayr 290
        DEBUGF  DEBUG_NETWORK_ERROR, "ICMP_input: checksum mismatch\n"
3545 hidnplayr 291
 
292
  .dump:
3556 hidnplayr 293
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input: dumping\n"
6011 hidnplayr 294
        call    net_buff_free
3545 hidnplayr 295
        ret
296
 
297
 
4052 hidnplayr 298
if 0
6011 hidnplayr 299
;-----------------------------------------------------------------;
300
;                                                                 ;
301
; icmp_output                                                     ;
302
;                                                                 ;
303
; IN:   eax = dest ip                                             ;
304
;       bh  = type                                                ;
305
;       bl  = code                                                ;
306
;       ecx = data length                                         ;
307
;       edx = source ip                                           ;
308
;       esi = data offset                                         ;
309
;       edi = identifier shl 16 + sequence number                 ;
310
;                                                                 ;
311
;-----------------------------------------------------------------;
3545 hidnplayr 312
align 4
6011 hidnplayr 313
icmp_output:
3545 hidnplayr 314
 
3556 hidnplayr 315
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet\n"
3545 hidnplayr 316
 
4052 hidnplayr 317
        push    esi edi bx
3545 hidnplayr 318
        add     ecx, sizeof.ICMP_header
319
        mov     di, IP_PROTO_ICMP SHL 8 + 128           ; TTL
320
        call    IPv4_output
321
        jz      .exit
322
 
3556 hidnplayr 323
        DEBUGF  DEBUG_NETWORK_VERBOSE, "full icmp packet size: %u\n", edx
3545 hidnplayr 324
 
325
        pop     word [edi + ICMP_header.Type]           ; Write both type and code bytes at once
326
        pop     dword [edi + ICMP_header.Identifier]    ; identifier and sequence number
327
        mov     [edi + ICMP_header.Checksum], 0
328
 
329
        push    ebx ecx edx
330
        mov     esi, edi
331
        xor     edx, edx
332
        call    checksum_1
333
        call    checksum_2
334
        mov     [edi + ICMP_header.Checksum], dx
335
        pop     edx ecx ebx esi
336
 
337
        sub     ecx, sizeof.ICMP_header
338
        add     edi, sizeof.ICMP_header
339
        push    cx
340
        shr     cx, 2
3711 clevermous 341
        rep movsd
3545 hidnplayr 342
        pop     cx
343
        and     cx, 3
3711 clevermous 344
        rep movsb
3545 hidnplayr 345
 
346
        sub     edi, edx                                ;;; TODO: find a better way to remember start of packet
347
        push    edx edi
3556 hidnplayr 348
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n"
3545 hidnplayr 349
        call    [ebx + NET_DEVICE.transmit]
3643 hidnplayr 350
        test    eax, eax
351
        jnz     @f
352
        call    NET_ptr_to_num4
353
        inc     [ICMP_PACKETS_TX + edi]
354
       @@:
3545 hidnplayr 355
        ret
356
  .exit:
3556 hidnplayr 357
        DEBUGF  DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n"
3545 hidnplayr 358
        add     esp, 2*4 + 2
359
        ret
4052 hidnplayr 360
end if
3545 hidnplayr 361
 
362
 
363
 
364
 
6011 hidnplayr 365
;-----------------------------------------------------------------;
366
;                                                                 ;
367
; icmp_output_raw                                                 ;
368
;                                                                 ;
369
;  IN:  eax = socket ptr                                          ;
370
;       ecx = data length                                         ;
371
;       edx = data pointer                                        ;
372
;                                                                 ;
373
;-----------------------------------------------------------------;
3545 hidnplayr 374
align 4
6011 hidnplayr 375
icmp_output_raw:
3545 hidnplayr 376
 
3556 hidnplayr 377
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet for socket %x, data ptr=%x\n", eax, edx
3545 hidnplayr 378
 
379
        push    edx
5842 hidnplayr 380
        mov     ebx, [eax + IP_SOCKET.device]
3545 hidnplayr 381
        mov     edx, [eax + IP_SOCKET.LocalIP]
5842 hidnplayr 382
        mov     edi, [eax + IP_SOCKET.RemoteIP]
383
        mov     al, [eax + IP_SOCKET.ttl]
384
        mov     ah, IP_PROTO_ICMP
6011 hidnplayr 385
        call    ipv4_output
5842 hidnplayr 386
        jz      .fail
3545 hidnplayr 387
 
388
        pop     esi
389
        push    eax
390
 
391
        push    edi ecx
3556 hidnplayr 392
        DEBUGF  DEBUG_NETWORK_VERBOSE, "copying %u bytes from %x to %x\n", ecx, esi, edi
3711 clevermous 393
        rep movsb
3545 hidnplayr 394
        pop     ecx edi
395
 
396
        mov     [edi + ICMP_header.Checksum], 0
397
 
398
        mov     esi, edi
399
        xor     edx, edx
400
        call    checksum_1
401
        call    checksum_2
402
        mov     [edi + ICMP_header.Checksum], dx
403
 
3556 hidnplayr 404
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n"
3545 hidnplayr 405
        call    [ebx + NET_DEVICE.transmit]
3643 hidnplayr 406
        test    eax, eax
407
        jnz     @f
6011 hidnplayr 408
        call    net_ptr_to_num4
7678 hidnplayr 409
        inc     [ICMP_packets_tx + edi]
5842 hidnplayr 410
  @@:
3545 hidnplayr 411
        ret
5842 hidnplayr 412
 
413
  .fail:
414
        pop     edx
3556 hidnplayr 415
        DEBUGF  DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n"
5842 hidnplayr 416
        or      eax, -1
417
        mov     ebx, EMSGSIZE           ;;; FIXME
3545 hidnplayr 418
        ret
419
 
420
 
421
 
422
 
6011 hidnplayr 423
;-----------------------------------------------------------------;
424
;                                                                 ;
425
; icmp_api: Part of system function 76.                           ;
426
;                                                                 ;
427
;  IN:  bl = subfunction number                                   ;
428
;       bh = device number                                        ;
429
;       ecx, edx, .. depends on subfunction                       ;
430
;                                                                 ;
431
; OUT:  depends on subfunction                                    ;
432
;                                                                 ;
433
;-----------------------------------------------------------------;
3545 hidnplayr 434
align 4
6011 hidnplayr 435
icmp_api:
3545 hidnplayr 436
 
437
        movzx   eax, bh
438
        shl     eax, 2
439
 
440
        test    bl, bl
441
        jz      .packets_tx     ; 0
442
        dec     bl
443
        jz      .packets_rx     ; 1
444
 
445
  .error:
446
        mov     eax, -1
447
        ret
448
 
449
  .packets_tx:
7678 hidnplayr 450
        mov     eax, [ICMP_packets_tx + eax]
3545 hidnplayr 451
        ret
452
 
453
  .packets_rx:
7678 hidnplayr 454
        mov     eax, [ICMP_packets_rx + eax]
3545 hidnplayr 455
        ret