Subversion Repositories Kolibri OS

Rev

Rev 6011 | Rev 7678 | 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: 7536 $
3545 hidnplayr 20
 
21
; ICMP types & codes
22
 
6011 hidnplayr 23
ICMP_ECHOREPLY                  = 0             ; echo reply message
3545 hidnplayr 24
 
25
ICMP_UNREACH                    = 3
6011 hidnplayr 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
3545 hidnplayr 42
 
6011 hidnplayr 43
ICMP_SOURCEQUENCH               = 4             ; Packet lost, slow down
3545 hidnplayr 44
 
6011 hidnplayr 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
3545 hidnplayr 50
 
6011 hidnplayr 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
3545 hidnplayr 56
 
6011 hidnplayr 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
3545 hidnplayr 61
 
6011 hidnplayr 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
3545 hidnplayr 66
 
6011 hidnplayr 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
3545 hidnplayr 81
 
6011 hidnplayr 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
3545 hidnplayr 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
 
3698 hidnplayr 99
uglobal
3545 hidnplayr 100
align 4
3698 hidnplayr 101
 
3600 hidnplayr 102
        ICMP_PACKETS_TX         rd NET_DEVICES_MAX
103
        ICMP_PACKETS_RX         rd NET_DEVICES_MAX
3698 hidnplayr 104
 
3545 hidnplayr 105
endg
106
 
107
 
108
 
6011 hidnplayr 109
;-----------------------------------------------------------------;
110
;                                                                 ;
111
; ICMP_init                                                       ;
112
;                                                                 ;
113
;-----------------------------------------------------------------;
3545 hidnplayr 114
 
6011 hidnplayr 115
macro icmp_init {
3545 hidnplayr 116
 
117
        xor     eax, eax
118
        mov     edi, ICMP_PACKETS_TX
3600 hidnplayr 119
        mov     ecx, 2*NET_DEVICES_MAX
3711 clevermous 120
        rep stosd
3545 hidnplayr 121
 
122
}
123
 
124
 
6011 hidnplayr 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
;-----------------------------------------------------------------;
3545 hidnplayr 140
align 4
6011 hidnplayr 141
icmp_input:
3545 hidnplayr 142
 
5522 hidnplayr 143
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input\n"
3545 hidnplayr 144
 
5842 hidnplayr 145
; Dump all multicasts and broadcasts
146
        mov     eax, [IP_LIST + edi]
147
        cmp     eax, [edx + IPv4_header.DestinationAddress]
148
        jne     .dump
149
 
5522 hidnplayr 150
; Check the checksum
5842 hidnplayr 151
        push    esi ecx edx
3545 hidnplayr 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
5842 hidnplayr 159
        pop     edx ecx esi
3545 hidnplayr 160
        jne     .checksum_mismatch
161
 
5522 hidnplayr 162
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input: Checksum OK\n"
3643 hidnplayr 163
 
5522 hidnplayr 164
; Update stats
3643 hidnplayr 165
        inc     [ICMP_PACKETS_RX + edi]
166
 
5522 hidnplayr 167
; Is this an echo request?
168
        cmp     [esi + ICMP_header.Type], ICMP_ECHO
169
        je      .echo_request
3545 hidnplayr 170
 
5522 hidnplayr 171
; Look for an open ICMP socket
3647 hidnplayr 172
        pusha
173
        mov     ecx, socket_mutex
174
        call    mutex_lock
175
        popa
176
 
5842 hidnplayr 177
        add     ecx, esi
178
        sub     ecx, edx
179
        mov     esi, edx
3545 hidnplayr 180
        mov     eax, net_sockets
181
  .next_socket:
182
        mov     eax, [eax + SOCKET.NextPtr]
183
        or      eax, eax
3647 hidnplayr 184
        jz      .dump_
3545 hidnplayr 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
 
3647 hidnplayr 192
        pusha
193
        mov     ecx, socket_mutex
194
        call    mutex_unlock
195
        popa
196
 
3556 hidnplayr 197
        DEBUGF  DEBUG_NETWORK_VERBOSE, "socket=%x\n", eax
3545 hidnplayr 198
 
199
        pusha
200
        lea     ecx, [eax + SOCKET.mutex]
201
        call    mutex_lock
202
        popa
203
 
6011 hidnplayr 204
        jmp     socket_input
3545 hidnplayr 205
 
5522 hidnplayr 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]
7536 hidnplayr 217
        mov     esi, [eax + NET_BUFF.offset]
218
        add     esi, eax
5522 hidnplayr 219
 
220
; Check frame type
221
        cmp     [eax + NET_BUFF.type], NET_BUFF_ETH
222
        jne     .not_ethernet
223
 
224
; exchange dest and source MAC in ETH header
225
        push    dword [esi + ETH_header.DstMAC]
226
        push    dword [esi + ETH_header.SrcMAC]
227
        pop     dword [esi + ETH_header.DstMAC]
228
        pop     dword [esi + ETH_header.SrcMAC]
229
        push    word [esi + ETH_header.DstMAC + 4]
230
        push    word [esi + ETH_header.SrcMAC + 4]
231
        pop     word [esi + ETH_header.DstMAC + 4]
232
        pop     word [esi + ETH_header.SrcMAC + 4]
233
        add     esi, sizeof.ETH_header
234
 
235
  .not_ethernet:
236
; Exchange dest and source address in IP header
237
        push    [esi + IPv4_header.SourceAddress]
238
        push    [esi + IPv4_header.DestinationAddress]
239
        pop     [esi + IPv4_header.SourceAddress]
240
        pop     [esi + IPv4_header.DestinationAddress]
241
 
242
; Calculate IP header length
243
        movzx   ecx, [esi + IPv4_header.VersionAndIHL]
244
        and     ecx, 0x0f
245
        shl     cx, 2
246
        mov     edi, ecx                        ; put it in edi for later
247
 
248
; Calculate IP checksum
249
        mov     eax, esi
250
        mov     [eax + IPv4_header.HeaderChecksum], 0
251
        xor     edx, edx
252
        call    checksum_1
253
        call    checksum_2
254
        mov     [eax + IPv4_header.HeaderChecksum], dx
255
 
256
; Calculate ICMP packet length
257
        movzx   ecx, [eax + IPv4_header.TotalLength]
258
        xchg    ch, cl
259
        sub     ecx, edi                        ; IP packet length - IP header length = ICMP packet length
260
 
261
; Calculate ICMP checkSum
262
        mov     eax, esi
263
        mov     [esi + ICMP_header.Checksum], 0
264
        xor     edx, edx
265
        call    checksum_1
266
        call    checksum_2
267
        mov     [eax + ICMP_header.Checksum], dx
268
 
269
; Transmit the frame
270
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP transmitting reply\n"
271
        call    [ebx + NET_DEVICE.transmit]
272
        test    eax, eax
273
        jnz     @f
274
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP transmit failed\n"
6011 hidnplayr 275
        call    net_ptr_to_num4
5522 hidnplayr 276
        inc     [ICMP_PACKETS_TX + edi]
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
3643 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:
450
        mov     eax, [ICMP_PACKETS_TX + eax]
451
        ret
452
 
453
  .packets_rx:
454
        mov     eax, [ICMP_PACKETS_RX + eax]
455
        ret