Subversion Repositories Kolibri OS

Rev

Rev 5584 | 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
;;                                                                 ;;
5363 yogev_ezra 3
;; Copyright (C) KolibriOS team 2004-2015. 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: 5842 $
3545 hidnplayr 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
3556 hidnplayr 40
ICMP_UNREACH_HOST_PRECEDENCE    = 14              ; host prec vio.
41
ICMP_UNREACH_PRECEDENCE_CUTOFF  = 15              ; prec cutoff
3545 hidnplayr 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
 
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
 
3698 hidnplayr 100
uglobal
3545 hidnplayr 101
align 4
3698 hidnplayr 102
 
3600 hidnplayr 103
        ICMP_PACKETS_TX         rd NET_DEVICES_MAX
104
        ICMP_PACKETS_RX         rd NET_DEVICES_MAX
3698 hidnplayr 105
 
3545 hidnplayr 106
endg
107
 
108
 
109
 
110
;-----------------------------------------------------------------
111
;
112
; ICMP_init
113
;
114
;-----------------------------------------------------------------
115
 
116
macro ICMP_init {
117
 
118
        xor     eax, eax
119
        mov     edi, ICMP_PACKETS_TX
3600 hidnplayr 120
        mov     ecx, 2*NET_DEVICES_MAX
3711 clevermous 121
        rep stosd
3545 hidnplayr 122
 
123
}
124
 
125
 
126
;-----------------------------------------------------------------
127
;
128
; ICMP_input:
129
;
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
5842 hidnplayr 136
;       edx = ptr to IPv4 header
3545 hidnplayr 137
;       esi = ptr to ICMP Packet data
5842 hidnplayr 138
;       edi = interface number*4
3545 hidnplayr 139
;
140
;  OUT: /
141
;
142
;-----------------------------------------------------------------
143
align 4
144
ICMP_input:
145
 
5522 hidnplayr 146
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input\n"
3545 hidnplayr 147
 
5842 hidnplayr 148
; Dump all multicasts and broadcasts
149
        mov     eax, [IP_LIST + edi]
150
        cmp     eax, [edx + IPv4_header.DestinationAddress]
151
        jne     .dump
152
 
5522 hidnplayr 153
; Check the checksum
5842 hidnplayr 154
        push    esi ecx edx
3545 hidnplayr 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
5842 hidnplayr 162
        pop     edx ecx esi
3545 hidnplayr 163
        jne     .checksum_mismatch
164
 
5522 hidnplayr 165
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input: Checksum OK\n"
3643 hidnplayr 166
 
5522 hidnplayr 167
; Update stats
3643 hidnplayr 168
        inc     [ICMP_PACKETS_RX + edi]
169
 
5522 hidnplayr 170
; Is this an echo request?
171
        cmp     [esi + ICMP_header.Type], ICMP_ECHO
172
        je      .echo_request
3545 hidnplayr 173
 
5522 hidnplayr 174
; Look for an open ICMP socket
3647 hidnplayr 175
        pusha
176
        mov     ecx, socket_mutex
177
        call    mutex_lock
178
        popa
179
 
5842 hidnplayr 180
        add     ecx, esi
181
        sub     ecx, edx
182
        mov     esi, edx
3545 hidnplayr 183
        mov     eax, net_sockets
184
  .next_socket:
185
        mov     eax, [eax + SOCKET.NextPtr]
186
        or      eax, eax
3647 hidnplayr 187
        jz      .dump_
3545 hidnplayr 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
 
3647 hidnplayr 195
        pusha
196
        mov     ecx, socket_mutex
197
        call    mutex_unlock
198
        popa
199
 
3556 hidnplayr 200
        DEBUGF  DEBUG_NETWORK_VERBOSE, "socket=%x\n", eax
3545 hidnplayr 201
 
202
        pusha
203
        lea     ecx, [eax + SOCKET.mutex]
204
        call    mutex_lock
205
        popa
206
 
207
        jmp     SOCKET_input
208
 
5522 hidnplayr 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
 
3647 hidnplayr 282
  .dump_:
283
        pusha
284
        mov     ecx, socket_mutex
285
        call    mutex_unlock
286
        popa
287
 
4892 hidnplayr 288
        DEBUGF  DEBUG_NETWORK_ERROR, "ICMP_input: no socket found\n"
3647 hidnplayr 289
        jmp     .dump
290
 
3545 hidnplayr 291
  .checksum_mismatch:
4892 hidnplayr 292
        DEBUGF  DEBUG_NETWORK_ERROR, "ICMP_input: checksum mismatch\n"
3545 hidnplayr 293
 
294
  .dump:
3556 hidnplayr 295
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input: dumping\n"
5522 hidnplayr 296
        call    NET_BUFF_free
3545 hidnplayr 297
        ret
298
 
299
 
4052 hidnplayr 300
if 0
3545 hidnplayr 301
;-----------------------------------------------------------------
302
;
303
; ICMP_output
304
;
305
; IN:  eax = dest ip
4052 hidnplayr 306
;      bh  = type
307
;      bl  = code
3545 hidnplayr 308
;      ecx = data length
4052 hidnplayr 309
;      edx = source ip
3545 hidnplayr 310
;      esi = data offset
311
;      edi = identifier shl 16 + sequence number
312
;
313
;-----------------------------------------------------------------
314
align 4
315
ICMP_output:
316
 
3556 hidnplayr 317
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet\n"
3545 hidnplayr 318
 
4052 hidnplayr 319
        push    esi edi bx
3545 hidnplayr 320
        add     ecx, sizeof.ICMP_header
321
        mov     di, IP_PROTO_ICMP SHL 8 + 128           ; TTL
322
        call    IPv4_output
323
        jz      .exit
324
 
3556 hidnplayr 325
        DEBUGF  DEBUG_NETWORK_VERBOSE, "full icmp packet size: %u\n", edx
3545 hidnplayr 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
3711 clevermous 343
        rep movsd
3545 hidnplayr 344
        pop     cx
345
        and     cx, 3
3711 clevermous 346
        rep movsb
3545 hidnplayr 347
 
348
        sub     edi, edx                                ;;; TODO: find a better way to remember start of packet
349
        push    edx edi
3556 hidnplayr 350
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n"
3545 hidnplayr 351
        call    [ebx + NET_DEVICE.transmit]
3643 hidnplayr 352
        test    eax, eax
353
        jnz     @f
354
        call    NET_ptr_to_num4
355
        inc     [ICMP_PACKETS_TX + edi]
356
       @@:
3545 hidnplayr 357
        ret
358
  .exit:
3556 hidnplayr 359
        DEBUGF  DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n"
3545 hidnplayr 360
        add     esp, 2*4 + 2
361
        ret
4052 hidnplayr 362
end if
3545 hidnplayr 363
 
364
 
365
 
366
 
367
;-----------------------------------------------------------------
368
;
4052 hidnplayr 369
; ICMP_output_raw
3545 hidnplayr 370
;
371
; IN:  eax = socket ptr
372
;      ecx = data length
5842 hidnplayr 373
;      edx = data pointer
3545 hidnplayr 374
;
375
;-----------------------------------------------------------------
376
align 4
377
ICMP_output_raw:
378
 
3556 hidnplayr 379
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet for socket %x, data ptr=%x\n", eax, edx
3545 hidnplayr 380
 
381
        push    edx
5842 hidnplayr 382
        mov     ebx, [eax + IP_SOCKET.device]
3545 hidnplayr 383
        mov     edx, [eax + IP_SOCKET.LocalIP]
5842 hidnplayr 384
        mov     edi, [eax + IP_SOCKET.RemoteIP]
385
        mov     al, [eax + IP_SOCKET.ttl]
386
        mov     ah, IP_PROTO_ICMP
3545 hidnplayr 387
        call    IPv4_output
5842 hidnplayr 388
        jz      .fail
3545 hidnplayr 389
 
390
        pop     esi
391
        push    eax
392
 
393
        push    edi ecx
3556 hidnplayr 394
        DEBUGF  DEBUG_NETWORK_VERBOSE, "copying %u bytes from %x to %x\n", ecx, esi, edi
3711 clevermous 395
        rep movsb
3545 hidnplayr 396
        pop     ecx edi
397
 
398
        mov     [edi + ICMP_header.Checksum], 0
399
 
400
        mov     esi, edi
401
        xor     edx, edx
402
        call    checksum_1
403
        call    checksum_2
404
        mov     [edi + ICMP_header.Checksum], dx
405
 
3556 hidnplayr 406
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n"
3545 hidnplayr 407
        call    [ebx + NET_DEVICE.transmit]
3643 hidnplayr 408
        test    eax, eax
409
        jnz     @f
410
        call    NET_ptr_to_num4
411
        inc     [ICMP_PACKETS_TX + edi]
5842 hidnplayr 412
  @@:
3545 hidnplayr 413
        ret
5842 hidnplayr 414
 
415
  .fail:
416
        pop     edx
3556 hidnplayr 417
        DEBUGF  DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n"
5842 hidnplayr 418
        or      eax, -1
419
        mov     ebx, EMSGSIZE           ;;; FIXME
3545 hidnplayr 420
        ret
421
 
422
 
423
 
424
 
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:
440
 
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
451
        ret
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