Subversion Repositories Kolibri OS

Rev

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

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