Subversion Repositories Kolibri OS

Rev

Rev 5565 | Rev 5984 | 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: 5594 $
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
136
;       esi = ptr to ICMP Packet data
137
;       edi = ptr to ipv4 source and dest address
138
;
139
;  OUT: /
140
;
141
;-----------------------------------------------------------------
142
align 4
143
ICMP_input:
261 hidnplayr 144
 
5565 serge 145
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input\n"
261 hidnplayr 146
 
5565 serge 147
; Check the checksum
3555 Serge 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
5565 serge 156
        pop     ecx esi
3555 Serge 157
        jne     .checksum_mismatch
261 hidnplayr 158
 
5565 serge 159
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input: Checksum OK\n"
3725 Serge 160
 
5565 serge 161
; Ualidate device ptr
162
        mov     eax, edi
3725 Serge 163
        call    NET_ptr_to_num4
164
        cmp     edi, -1
165
        je      .dump
5565 serge 166
 
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
 
5565 serge 180
        mov     edx, [eax]              ; ipv4 source address
3555 Serge 181
        mov     eax, net_sockets
182
  .try_more:
5565 serge 183
;        mov      , [esi + ICMP_header.Identifier]
3555 Serge 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
 
5565 serge 195
        cmp     [eax + IP_SOCKET.RemoteIP], edx
3555 Serge 196
        jne     .next_socket
197
 
198
;        cmp     [eax + ICMP_SOCKET.Identifier],
199
;        jne     .next_socket
200
 
3725 Serge 201
        pusha
202
        mov     ecx, socket_mutex
203
        call    mutex_unlock
204
        popa
205
 
3589 Serge 206
        DEBUGF  DEBUG_NETWORK_VERBOSE, "socket=%x\n", eax
3555 Serge 207
 
208
        pusha
209
        lea     ecx, [eax + SOCKET.mutex]
210
        call    mutex_lock
211
        popa
212
 
213
        jmp     SOCKET_input
214
 
5565 serge 215
 
216
 
217
  .echo_request:
218
 
219
; We'll reuse the packet so we can create the response as fast as possible
220
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP echo request\n"
221
 
222
; Change Packet type to reply
223
        mov     [esi + ICMP_header.Type], ICMP_ECHOREPLY
224
 
225
        mov     eax, [esp]
226
        lea     esi, [eax + NET_BUFF.data]
227
 
228
; Check frame type
229
        cmp     [eax + NET_BUFF.type], NET_BUFF_ETH
230
        jne     .not_ethernet
231
 
232
; exchange dest and source MAC in ETH header
233
        push    dword [esi + ETH_header.DstMAC]
234
        push    dword [esi + ETH_header.SrcMAC]
235
        pop     dword [esi + ETH_header.DstMAC]
236
        pop     dword [esi + ETH_header.SrcMAC]
237
        push    word [esi + ETH_header.DstMAC + 4]
238
        push    word [esi + ETH_header.SrcMAC + 4]
239
        pop     word [esi + ETH_header.DstMAC + 4]
240
        pop     word [esi + ETH_header.SrcMAC + 4]
241
        add     esi, sizeof.ETH_header
242
 
243
  .not_ethernet:
244
; Exchange dest and source address in IP header
245
        push    [esi + IPv4_header.SourceAddress]
246
        push    [esi + IPv4_header.DestinationAddress]
247
        pop     [esi + IPv4_header.SourceAddress]
248
        pop     [esi + IPv4_header.DestinationAddress]
249
 
250
; Calculate IP header length
251
        movzx   ecx, [esi + IPv4_header.VersionAndIHL]
252
        and     ecx, 0x0f
253
        shl     cx, 2
254
        mov     edi, ecx                        ; put it in edi for later
255
 
256
; Calculate IP checksum
257
        mov     eax, esi
258
        mov     [eax + IPv4_header.HeaderChecksum], 0
259
        xor     edx, edx
260
        call    checksum_1
261
        call    checksum_2
262
        mov     [eax + IPv4_header.HeaderChecksum], dx
263
 
264
; Calculate ICMP packet length
265
        movzx   ecx, [eax + IPv4_header.TotalLength]
266
        xchg    ch, cl
267
        sub     ecx, edi                        ; IP packet length - IP header length = ICMP packet length
268
 
269
; Calculate ICMP checkSum
270
        mov     eax, esi
271
        mov     [esi + ICMP_header.Checksum], 0
272
        xor     edx, edx
273
        call    checksum_1
274
        call    checksum_2
275
        mov     [eax + ICMP_header.Checksum], dx
276
 
277
; Transmit the frame
278
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP transmitting reply\n"
279
        call    [ebx + NET_DEVICE.transmit]
280
        test    eax, eax
281
        jnz     @f
282
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP transmit failed\n"
283
        call    NET_ptr_to_num4
284
        inc     [ICMP_PACKETS_TX + edi]
285
       @@:
286
        ret
287
 
3725 Serge 288
  .dump_:
289
        pusha
290
        mov     ecx, socket_mutex
291
        call    mutex_unlock
292
        popa
293
 
5201 serge 294
        DEBUGF  DEBUG_NETWORK_ERROR, "ICMP_input: no socket found\n"
3725 Serge 295
        jmp     .dump
296
 
3555 Serge 297
  .checksum_mismatch:
5201 serge 298
        DEBUGF  DEBUG_NETWORK_ERROR, "ICMP_input: checksum mismatch\n"
3555 Serge 299
 
300
  .dump:
3589 Serge 301
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input: dumping\n"
5565 serge 302
        call    NET_BUFF_free
3555 Serge 303
        ret
304
 
305
 
4265 Serge 306
if 0
3555 Serge 307
;-----------------------------------------------------------------
261 hidnplayr 308
;
3555 Serge 309
; ICMP_output
261 hidnplayr 310
;
3555 Serge 311
; IN:  eax = dest ip
4265 Serge 312
;      bh  = type
313
;      bl  = code
3555 Serge 314
;      ecx = data length
4265 Serge 315
;      edx = source ip
3555 Serge 316
;      esi = data offset
317
;      edi = identifier shl 16 + sequence number
261 hidnplayr 318
;
3555 Serge 319
;-----------------------------------------------------------------
320
align 4
321
ICMP_output:
322
 
3589 Serge 323
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet\n"
3555 Serge 324
 
4265 Serge 325
        push    esi edi bx
3555 Serge 326
        add     ecx, sizeof.ICMP_header
327
        mov     di, IP_PROTO_ICMP SHL 8 + 128           ; TTL
328
        call    IPv4_output
329
        jz      .exit
330
 
3589 Serge 331
        DEBUGF  DEBUG_NETWORK_VERBOSE, "full icmp packet size: %u\n", edx
3555 Serge 332
 
333
        pop     word [edi + ICMP_header.Type]           ; Write both type and code bytes at once
334
        pop     dword [edi + ICMP_header.Identifier]    ; identifier and sequence number
335
        mov     [edi + ICMP_header.Checksum], 0
336
 
337
        push    ebx ecx edx
338
        mov     esi, edi
339
        xor     edx, edx
340
        call    checksum_1
341
        call    checksum_2
342
        mov     [edi + ICMP_header.Checksum], dx
343
        pop     edx ecx ebx esi
344
 
345
        sub     ecx, sizeof.ICMP_header
346
        add     edi, sizeof.ICMP_header
347
        push    cx
348
        shr     cx, 2
3725 Serge 349
        rep movsd
3555 Serge 350
        pop     cx
351
        and     cx, 3
3725 Serge 352
        rep movsb
3555 Serge 353
 
354
        sub     edi, edx                                ;;; TODO: find a better way to remember start of packet
355
        push    edx edi
3589 Serge 356
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n"
3555 Serge 357
        call    [ebx + NET_DEVICE.transmit]
3725 Serge 358
        test    eax, eax
359
        jnz     @f
360
        call    NET_ptr_to_num4
361
        inc     [ICMP_PACKETS_TX + edi]
362
       @@:
3555 Serge 363
        ret
364
  .exit:
3589 Serge 365
        DEBUGF  DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n"
3555 Serge 366
        add     esp, 2*4 + 2
367
        ret
4265 Serge 368
end if
3555 Serge 369
 
370
 
371
 
372
 
373
;-----------------------------------------------------------------
261 hidnplayr 374
;
4265 Serge 375
; ICMP_output_raw
261 hidnplayr 376
;
3555 Serge 377
; IN:  eax = socket ptr
378
;      ecx = data length
379
;      esi = data offset
380
;
381
;-----------------------------------------------------------------
382
align 4
383
ICMP_output_raw:
261 hidnplayr 384
 
3589 Serge 385
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet for socket %x, data ptr=%x\n", eax, edx
261 hidnplayr 386
 
3555 Serge 387
        push    edx
261 hidnplayr 388
 
3555 Serge 389
        mov     di, IP_PROTO_ICMP SHL 8 + 128  ; TTL
390
        mov     edx, [eax + IP_SOCKET.LocalIP]
5594 serge 391
        mov     ebx, [eax + IP_SOCKET.device]
3555 Serge 392
        mov     eax, [eax + IP_SOCKET.RemoteIP]
393
        call    IPv4_output
394
        jz      .exit
261 hidnplayr 395
 
3555 Serge 396
        pop     esi
397
        push    eax
261 hidnplayr 398
 
3555 Serge 399
        push    edi ecx
3589 Serge 400
        DEBUGF  DEBUG_NETWORK_VERBOSE, "copying %u bytes from %x to %x\n", ecx, esi, edi
3725 Serge 401
        rep movsb
3555 Serge 402
        pop     ecx edi
261 hidnplayr 403
 
3555 Serge 404
        mov     [edi + ICMP_header.Checksum], 0
261 hidnplayr 405
 
3555 Serge 406
        mov     esi, edi
407
        xor     edx, edx
408
        call    checksum_1
409
        call    checksum_2
410
        mov     [edi + ICMP_header.Checksum], dx
261 hidnplayr 411
 
3589 Serge 412
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n"
3555 Serge 413
        call    [ebx + NET_DEVICE.transmit]
3725 Serge 414
        test    eax, eax
415
        jnz     @f
416
        call    NET_ptr_to_num4
417
        inc     [ICMP_PACKETS_TX + edi]
418
       @@:
3555 Serge 419
        ret
420
  .exit:
3589 Serge 421
        DEBUGF  DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n"
3555 Serge 422
        ret
261 hidnplayr 423
 
424
 
425
 
426
 
3555 Serge 427
;-----------------------------------------------------------------
428
;
429
; ICMP_API
430
;
431
; This function is called by system function 75
432
;
433
; IN:  subfunction number in bl
434
;      device number in bh
435
;      ecx, edx, .. depends on subfunction
436
;
437
; OUT:
438
;
439
;-----------------------------------------------------------------
440
align 4
441
ICMP_api:
261 hidnplayr 442
 
3555 Serge 443
        movzx   eax, bh
444
        shl     eax, 2
445
 
446
        test    bl, bl
447
        jz      .packets_tx     ; 0
448
        dec     bl
449
        jz      .packets_rx     ; 1
450
 
451
  .error:
452
        mov     eax, -1
2434 Serge 453
        ret
3555 Serge 454
 
455
  .packets_tx:
456
        mov     eax, [ICMP_PACKETS_TX + eax]
457
        ret
458
 
459
  .packets_rx:
460
        mov     eax, [ICMP_PACKETS_RX + eax]
461
        ret