Subversion Repositories Kolibri OS

Rev

Rev 5984 | 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: 6078 $
261 hidnplayr 20
 
3555 Serge 21
; ICMP types & codes
593 mikedld 22
 
6078 serge 23
ICMP_ECHOREPLY                  = 0             ; echo reply message
261 hidnplayr 24
 
3555 Serge 25
ICMP_UNREACH                    = 3
6078 serge 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
261 hidnplayr 42
 
6078 serge 43
ICMP_SOURCEQUENCH               = 4             ; Packet lost, slow down
261 hidnplayr 44
 
6078 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
3555 Serge 50
 
6078 serge 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
3555 Serge 56
 
6078 serge 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
3555 Serge 61
 
6078 serge 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
3555 Serge 66
 
6078 serge 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
3555 Serge 81
 
6078 serge 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
3555 Serge 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
 
3725 Serge 99
uglobal
3555 Serge 100
align 4
3725 Serge 101
 
3626 Serge 102
        ICMP_PACKETS_TX         rd NET_DEVICES_MAX
103
        ICMP_PACKETS_RX         rd NET_DEVICES_MAX
3725 Serge 104
 
3555 Serge 105
endg
106
 
107
 
108
 
6078 serge 109
;-----------------------------------------------------------------;
110
;                                                                 ;
111
; ICMP_init                                                       ;
112
;                                                                 ;
113
;-----------------------------------------------------------------;
261 hidnplayr 114
 
6078 serge 115
macro icmp_init {
3555 Serge 116
 
117
        xor     eax, eax
118
        mov     edi, ICMP_PACKETS_TX
3626 Serge 119
        mov     ecx, 2*NET_DEVICES_MAX
3725 Serge 120
        rep stosd
3555 Serge 121
 
122
}
123
 
124
 
6078 serge 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
;-----------------------------------------------------------------;
3555 Serge 140
align 4
6078 serge 141
icmp_input:
261 hidnplayr 142
 
5565 serge 143
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input\n"
261 hidnplayr 144
 
5984 serge 145
; Dump all multicasts and broadcasts
146
        mov     eax, [IP_LIST + edi]
147
        cmp     eax, [edx + IPv4_header.DestinationAddress]
148
        jne     .dump
149
 
5565 serge 150
; Check the checksum
5984 serge 151
        push    esi ecx edx
3555 Serge 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
5984 serge 159
        pop     edx ecx esi
3555 Serge 160
        jne     .checksum_mismatch
261 hidnplayr 161
 
5565 serge 162
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input: Checksum OK\n"
3725 Serge 163
 
5565 serge 164
; Update stats
3725 Serge 165
        inc     [ICMP_PACKETS_RX + edi]
166
 
5565 serge 167
; Is this an echo request?
168
        cmp     [esi + ICMP_header.Type], ICMP_ECHO
169
        je      .echo_request
261 hidnplayr 170
 
5565 serge 171
; Look for an open ICMP socket
3725 Serge 172
        pusha
173
        mov     ecx, socket_mutex
174
        call    mutex_lock
175
        popa
176
 
5984 serge 177
        add     ecx, esi
178
        sub     ecx, edx
179
        mov     esi, edx
3555 Serge 180
        mov     eax, net_sockets
181
  .next_socket:
182
        mov     eax, [eax + SOCKET.NextPtr]
183
        or      eax, eax
3725 Serge 184
        jz      .dump_
3555 Serge 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
 
3725 Serge 192
        pusha
193
        mov     ecx, socket_mutex
194
        call    mutex_unlock
195
        popa
196
 
3589 Serge 197
        DEBUGF  DEBUG_NETWORK_VERBOSE, "socket=%x\n", eax
3555 Serge 198
 
199
        pusha
200
        lea     ecx, [eax + SOCKET.mutex]
201
        call    mutex_lock
202
        popa
203
 
6078 serge 204
        jmp     socket_input
3555 Serge 205
 
5565 serge 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]
217
        lea     esi, [eax + NET_BUFF.data]
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"
6078 serge 274
        call    net_ptr_to_num4
5565 serge 275
        inc     [ICMP_PACKETS_TX + edi]
276
       @@:
277
        ret
278
 
3725 Serge 279
  .dump_:
280
        pusha
281
        mov     ecx, socket_mutex
282
        call    mutex_unlock
283
        popa
284
 
5201 serge 285
        DEBUGF  DEBUG_NETWORK_ERROR, "ICMP_input: no socket found\n"
3725 Serge 286
        jmp     .dump
287
 
3555 Serge 288
  .checksum_mismatch:
5201 serge 289
        DEBUGF  DEBUG_NETWORK_ERROR, "ICMP_input: checksum mismatch\n"
3555 Serge 290
 
291
  .dump:
3589 Serge 292
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input: dumping\n"
6078 serge 293
        call    net_buff_free
3555 Serge 294
        ret
295
 
296
 
4265 Serge 297
if 0
6078 serge 298
;-----------------------------------------------------------------;
299
;                                                                 ;
300
; icmp_output                                                     ;
301
;                                                                 ;
302
; IN:   eax = dest ip                                             ;
303
;       bh  = type                                                ;
304
;       bl  = code                                                ;
305
;       ecx = data length                                         ;
306
;       edx = source ip                                           ;
307
;       esi = data offset                                         ;
308
;       edi = identifier shl 16 + sequence number                 ;
309
;                                                                 ;
310
;-----------------------------------------------------------------;
3555 Serge 311
align 4
6078 serge 312
icmp_output:
3555 Serge 313
 
3589 Serge 314
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet\n"
3555 Serge 315
 
4265 Serge 316
        push    esi edi bx
3555 Serge 317
        add     ecx, sizeof.ICMP_header
318
        mov     di, IP_PROTO_ICMP SHL 8 + 128           ; TTL
319
        call    IPv4_output
320
        jz      .exit
321
 
3589 Serge 322
        DEBUGF  DEBUG_NETWORK_VERBOSE, "full icmp packet size: %u\n", edx
3555 Serge 323
 
324
        pop     word [edi + ICMP_header.Type]           ; Write both type and code bytes at once
325
        pop     dword [edi + ICMP_header.Identifier]    ; identifier and sequence number
326
        mov     [edi + ICMP_header.Checksum], 0
327
 
328
        push    ebx ecx edx
329
        mov     esi, edi
330
        xor     edx, edx
331
        call    checksum_1
332
        call    checksum_2
333
        mov     [edi + ICMP_header.Checksum], dx
334
        pop     edx ecx ebx esi
335
 
336
        sub     ecx, sizeof.ICMP_header
337
        add     edi, sizeof.ICMP_header
338
        push    cx
339
        shr     cx, 2
3725 Serge 340
        rep movsd
3555 Serge 341
        pop     cx
342
        and     cx, 3
3725 Serge 343
        rep movsb
3555 Serge 344
 
345
        sub     edi, edx                                ;;; TODO: find a better way to remember start of packet
346
        push    edx edi
3589 Serge 347
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n"
3555 Serge 348
        call    [ebx + NET_DEVICE.transmit]
3725 Serge 349
        test    eax, eax
350
        jnz     @f
351
        call    NET_ptr_to_num4
352
        inc     [ICMP_PACKETS_TX + edi]
353
       @@:
3555 Serge 354
        ret
355
  .exit:
3589 Serge 356
        DEBUGF  DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n"
3555 Serge 357
        add     esp, 2*4 + 2
358
        ret
4265 Serge 359
end if
3555 Serge 360
 
361
 
362
 
363
 
6078 serge 364
;-----------------------------------------------------------------;
365
;                                                                 ;
366
; icmp_output_raw                                                 ;
367
;                                                                 ;
368
;  IN:  eax = socket ptr                                          ;
369
;       ecx = data length                                         ;
370
;       edx = data pointer                                        ;
371
;                                                                 ;
372
;-----------------------------------------------------------------;
3555 Serge 373
align 4
6078 serge 374
icmp_output_raw:
261 hidnplayr 375
 
3589 Serge 376
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet for socket %x, data ptr=%x\n", eax, edx
261 hidnplayr 377
 
3555 Serge 378
        push    edx
5984 serge 379
        mov     ebx, [eax + IP_SOCKET.device]
3555 Serge 380
        mov     edx, [eax + IP_SOCKET.LocalIP]
5984 serge 381
        mov     edi, [eax + IP_SOCKET.RemoteIP]
382
        mov     al, [eax + IP_SOCKET.ttl]
383
        mov     ah, IP_PROTO_ICMP
6078 serge 384
        call    ipv4_output
5984 serge 385
        jz      .fail
261 hidnplayr 386
 
3555 Serge 387
        pop     esi
388
        push    eax
261 hidnplayr 389
 
3555 Serge 390
        push    edi ecx
3589 Serge 391
        DEBUGF  DEBUG_NETWORK_VERBOSE, "copying %u bytes from %x to %x\n", ecx, esi, edi
3725 Serge 392
        rep movsb
3555 Serge 393
        pop     ecx edi
261 hidnplayr 394
 
3555 Serge 395
        mov     [edi + ICMP_header.Checksum], 0
261 hidnplayr 396
 
3555 Serge 397
        mov     esi, edi
398
        xor     edx, edx
399
        call    checksum_1
400
        call    checksum_2
401
        mov     [edi + ICMP_header.Checksum], dx
261 hidnplayr 402
 
3589 Serge 403
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n"
3555 Serge 404
        call    [ebx + NET_DEVICE.transmit]
3725 Serge 405
        test    eax, eax
406
        jnz     @f
6078 serge 407
        call    net_ptr_to_num4
3725 Serge 408
        inc     [ICMP_PACKETS_TX + edi]
5984 serge 409
  @@:
3555 Serge 410
        ret
5984 serge 411
 
412
  .fail:
413
        pop     edx
3589 Serge 414
        DEBUGF  DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n"
5984 serge 415
        or      eax, -1
416
        mov     ebx, EMSGSIZE           ;;; FIXME
3555 Serge 417
        ret
261 hidnplayr 418
 
419
 
420
 
421
 
6078 serge 422
;-----------------------------------------------------------------;
423
;                                                                 ;
424
; icmp_api: Part of system function 76.                           ;
425
;                                                                 ;
426
;  IN:  bl = subfunction number                                   ;
427
;       bh = device number                                        ;
428
;       ecx, edx, .. depends on subfunction                       ;
429
;                                                                 ;
430
; OUT:  depends on subfunction                                    ;
431
;                                                                 ;
432
;-----------------------------------------------------------------;
3555 Serge 433
align 4
6078 serge 434
icmp_api:
261 hidnplayr 435
 
3555 Serge 436
        movzx   eax, bh
437
        shl     eax, 2
438
 
439
        test    bl, bl
440
        jz      .packets_tx     ; 0
441
        dec     bl
442
        jz      .packets_rx     ; 1
443
 
444
  .error:
445
        mov     eax, -1
2434 Serge 446
        ret
3555 Serge 447
 
448
  .packets_tx:
449
        mov     eax, [ICMP_PACKETS_TX + eax]
450
        ret
451
 
452
  .packets_rx:
453
        mov     eax, [ICMP_PACKETS_RX + eax]
454
        ret