Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
1159 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved.    ;;
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
 
19
 
20
$Revision: 593 $
21
 
22
; ICMP types & codes
23
 
24
ICMP_ECHOREPLY		equ	0		; echo reply message
25
 
26
ICMP_UNREACH		equ	3
27
	ICMP_UNREACH_NET	equ	0		; bad net
28
	ICMP_UNREACH_HOST	equ	1		; bad host
29
	ICMP_UNREACH_PROTOCOL	equ	2		; bad protocol
30
	ICMP_UNREACH_PORT	equ	3		; bad port
31
	ICMP_UNREACH_NEEDFRAG	equ	4		; IP_DF caused drop
32
	ICMP_UNREACH_SRCFAIL	equ	5		; src route failed
33
	ICMP_UNREACH_NET_UNKNOWN equ	6		; unknown net
34
	ICMP_UNREACH_HOST_UNKNOWN equ	7		; unknown host
35
	ICMP_UNREACH_ISOLATED	equ	8		; src host isolated
36
	ICMP_UNREACH_NET_PROHIB equ	9		; prohibited access
37
	ICMP_UNREACH_HOST_PROHIB equ	10		; ditto
38
	ICMP_UNREACH_TOSNET	equ	11		; bad tos for net
39
	ICMP_UNREACH_TOSHOST	equ	12		; bad tos for host
40
	ICMP_UNREACH_FILTER_PROHIB equ	13		; admin prohib
41
	ICMP_UNREACH_HOST_PRECEDENCE equ 14		; host prec vio.
42
	ICMP_UNREACH_PRECEDENCE_CUTOFF equ 15		; prec cutoff
43
 
44
ICMP_SOURCEQUENCH	equ	4		; Packet lost, slow down
45
 
46
ICMP_REDIRECT		equ	5		; shorter route, codes:
47
	ICMP_REDIRECT_NET	equ	0		; for network
48
	ICMP_REDIRECT_HOST	equ	1		; for host
49
	ICMP_REDIRECT_TOSNET	equ	2		; for tos and net
50
	ICMP_REDIRECT_TOSHOST	equ	3		; for tos and host
51
 
52
ICMP_ALTHOSTADDR	equ	6		; alternate host address
53
ICMP_ECHO		equ	8		; echo service
54
ICMP_ROUTERADVERT	equ	9		; router advertisement
55
	ICMP_ROUTERADVERT_NORMAL equ 0			; normal advertisement
56
	ICMP_ROUTERADVERT_NOROUTE_COMMON equ 16 	; selective routing
57
 
58
ICMP_ROUTERSOLICIT	equ	10		; router solicitation
59
ICMP_TIMXCEED		equ	11		; time exceeded, code:
60
    ICMP_TIMXCEED_INTRANS	equ	0		; ttl==0 in transit
61
    ICMP_TIMXCEED_REASS equ	1		; ttl==0 in reass
62
 
63
ICMP_PARAMPROB		  equ  12		; ip header bad
64
    ICMP_PARAMPROB_ERRATPTR   equ  0		; error at param ptr
65
    ICMP_PARAMPROB_OPTABSENT  equ  1		; req. opt. absent
66
    ICMP_PARAMPROB_LENGTH     equ  2		; bad length
67
 
68
ICMP_TSTAMP		equ	13		; timestamp request
69
ICMP_TSTAMPREPLY	equ	14		; timestamp reply
70
ICMP_IREQ		equ	15		; information request
71
ICMP_IREQREPLY		equ	16		; information reply
72
ICMP_MASKREQ		equ	17		; address mask request
73
ICMP_MASKREPLY		equ	18		; address mask reply
74
ICMP_TRACEROUTE 	equ	30		; traceroute
75
ICMP_DATACONVERR	equ	31		; data conversion error
76
ICMP_MOBILE_REDIRECT	equ	32		; mobile host redirect
77
ICMP_IPV6_WHEREAREYOU	equ	33		; IPv6 where-are-you
78
 ICMP_IPV6_IAMHERE	equ	34		; IPv6 i-am-here
79
ICMP_MOBILE_REGREQUEST	equ	35		; mobile registration req
80
ICMP_MOBILE_REGREPLY	equ	36		; mobile registreation reply
81
ICMP_SKIP		equ	39		; SKIP
82
 
83
ICMP_PHOTURIS		equ	40		; Photuris
84
    ICMP_PHOTURIS_UNKNOWN_INDEX   equ  1		; unknown sec index
85
    ICMP_PHOTURIS_AUTH_FAILED	  equ  2		; auth failed
86
    ICMP_PHOTURIS_DECRYPT_FAILED  equ  3		; decrypt failed
87
 
88
 
89
 
90
struct	ICMP_Packet
91
	.Type		db   ?
92
	.Code		db   ?
93
	.Checksum	dw   ?
94
	.Identifier	dw   ?
95
	.SequenceNumber dw   ?
96
	.Data:
97
ends
98
 
99
 
100
align 4
101
uglobal
102
	ICMP_PACKETS_TX 	rd  MAX_IP
103
	ICMP_PACKETS_RX 	rd  MAX_IP
104
endg
105
 
106
;-----------------------------------------------------------------
107
;
108
; ICMP_init
109
;
110
;  This function resets all ICMP variables
111
;
112
;  IN:  /
113
;  OUT: /
114
;
115
;-----------------------------------------------------------------
116
 
117
align 4
118
ICMP_init:
119
 
120
	xor	eax, eax
121
	mov	edi, ICMP_PACKETS_TX
122
	mov	ecx, 2*MAX_IP
123
	rep	stosd
124
 
125
	ret
126
 
127
 
1171 hidnplayr 128
 
129
 
130
 
131
 
132
 
133
 
134
 
135
 
1159 hidnplayr 136
;--------------------------------
137
;
138
; ICMP_Handler:
139
;
140
;  Called by IP_handler,
141
;  this procedure will send reply's to ICMP echo's etc               ;;; TODO: update this to work with fragmented packets too!
142
;
143
;  IN:  Pointer to buffer in [esp]
144
;       size of buffer in [esp+4]
145
;       pointer to device struct in ebx
146
;       ICMP Packet size in ecx
147
;       pointer to ICMP Packet data in edx
148
;  OUT: /
149
;
150
;--------------------------------
151
 
152
align 4
153
ICMP_Handler:	;TODO: works only on pure ethernet right now !
154
 
155
	DEBUGF	1,"ICMP_Handler - start\n"
156
	cmp	byte [edx + ICMP_Packet.Type], ICMP_ECHO		    ; Is this an echo request? discard if not
157
	jne	.check_sockets
158
 
159
	mov	byte [edx + ICMP_Packet.Type], ICMP_ECHOREPLY		    ; Change Packet type to reply
160
	mov	word [edx + ICMP_Packet.Checksum], 0			    ; Set checksum to 0, needed to calculate new checksum
161
 
1171 hidnplayr 162
	call	ETH_struc2dev
163
	cmp	edi,-1
164
	je	.dump
165
	inc	[ICMP_PACKETS_RX+4*edi]
166
 
1159 hidnplayr 167
; exchange dest and source address in IP header
168
; exchange dest and source MAC in ETH header
169
	mov	esi, [esp]
170
 
171
	mov	eax, dword [esi + ETH_FRAME.DstMAC]
172
	mov	ecx, dword [esi + ETH_FRAME.SrcMAC]
173
	mov	dword [esi + ETH_FRAME.SrcMAC], eax
174
	mov	dword [esi + ETH_FRAME.DstMAC], ecx
175
 
176
	mov	ax, word [esi + ETH_FRAME.DstMAC + 4]
177
	mov	cx, word [esi + ETH_FRAME.SrcMAC + 4]
178
	mov	word [esi + ETH_FRAME.SrcMAC + 4], ax
179
	mov	word [esi + ETH_FRAME.DstMAC + 4], cx
180
 
181
	mov	eax, dword [esi + ETH_FRAME.Data + IPv4_Packet.SourceAddress]
182
	mov	ecx, dword [esi + ETH_FRAME.Data + IPv4_Packet.DestinationAddress]
183
	mov	dword [esi + ETH_FRAME.Data + IPv4_Packet.DestinationAddress], eax
184
	mov	dword [esi + ETH_FRAME.Data + IPv4_Packet.SourceAddress], ecx
185
 
186
; Recalculate ip header checksum
187
;        mov     esi, [esp]
188
	add	esi, ETH_FRAME.Data					    ; Point esi to start of IP Packet
189
	movzx	eax, byte [esi + IPv4_Packet.VersionAndIHL]		      ; Calculate IP Header length by using IHL field
190
	and	eax, 0x0000000F 					    ;
191
	shl	eax, 2							    ;
192
	push	ebx edx esi
193
	stdcall checksum_jb, esi, eax					    ; calculate the checksum
194
	pop	esi edx ebx
195
	xchg	al, ah							    ; convert to intel byte order
196
;        mov     esi, [esp]
197
	mov	word [esi + IPv4_Packet.HeaderChecksum], ax  ; Store it in the IP Packet header
198
 
199
; Recalculate ICMP CheckSum
200
;        mov     esi, [esp]                                                 ; Find length of IP Packet
201
	movzx	eax, word[esi + IPv4_Packet.TotalLength]     ;
202
	xchg	ah , al 						    ;
203
	movzx	edi, byte [esi + IPv4_Packet.VersionAndIHL]  ; Calculate IP Header length by using IHL field
204
	and	edi, 0x0000000F 					    ;
205
	shl	edi, 2							    ;
206
	sub	ax , di 						    ; Now we know the length of ICMP data in eax
207
	push	ebx edx
208
	stdcall checksum_jb,edx,eax					    ; Calculate the checksum of icmp data
209
	pop	edx ebx
210
	xchg	al, ah							    ; Convert to intel byte order
211
	mov	word [edx + ICMP_Packet.Checksum], ax
212
 
1171 hidnplayr 213
	jmp	ETH_Sender						    ; Send the reply
1159 hidnplayr 214
 
1171 hidnplayr 215
 
216
 
217
 
218
 
1159 hidnplayr 219
       .check_sockets:
220
	; TODO: validate the header & checksum. Discard buffer if error
221
 
222
	; Look for an open ICMP socket
223
 
224
	mov	esi, net_sockets
225
  .try_more:
226
	mov	ax , [edx + ICMP_Packet.Identifier]
227
  .next_socket:
228
	mov	esi, [esi + SOCKET.NextPtr]
229
	or	esi, esi
230
	jz	.dump
231
	cmp	[esi + SOCKET.Type], IP_PROTO_ICMP
232
	jne	.next_socket
233
	cmp	[esi + SOCKET.LocalPort], ax
234
	jne	.next_socket
235
 
236
	cmp	[esi + SOCKET.rxDataCount],0	      ; get # of bytes already in buffer
237
	jnz	.dump				      ; only one packet at a time may be in the buffer!
238
 
239
	cmp	ecx, SOCKETBUFFSIZE - SOCKETHEADERSIZE; TODO: fix this problem !
240
	jg	.dump
241
 
1171 hidnplayr 242
	call	IPv4_dest_to_dev
243
	cmp	edi,-1
244
	je	.dump
245
	inc	[ICMP_PACKETS_RX+4*edi]
246
 
1159 hidnplayr 247
	DEBUGF 1,"Found valid ICMP packet for socket %x\n", esi
248
 
249
	lea	ebx, [esi + SOCKET.lock]
250
	call	wait_mutex
251
 
252
	; Now, copy data to socket. We have socket address in esi.
253
	; We have ICMP Packet in edx
254
	; number of bytes in ecx
255
 
256
	; note: we do not strip the header!
257
 
258
	DEBUGF 1,"bytes: %u\n", ecx
259
 
260
	mov	[esi + SOCKET.rxDataCount], ecx
261
 
262
	lea	edi, [esi + SOCKETHEADERSIZE]
263
	push	esi
264
	push	ecx
265
	mov	esi, edx
266
	shr	ecx, 2
267
	rep	movsd	       ; copy the data across
268
	pop	ecx
269
	and	ecx, 3
270
	rep	movsb
271
	pop	esi
272
 
273
	DEBUGF 1,"ICMP socket updated\n"
274
 
275
	mov	[esi + SOCKET.lock], 0
276
 
277
	; flag an event to the application
278
	mov	eax, [esi + SOCKET.PID] 		; get socket owner PID
279
	mov	ecx, 1
280
	mov	esi, TASK_DATA + TASKDATA.pid
281
 
282
       .next_pid:
283
	cmp	[esi], eax
284
	je	.found_pid
285
	inc	ecx
286
	add	esi, 0x20
287
	cmp	ecx, [TASK_COUNT]
288
	jbe	.next_pid
289
 
290
	jmp	.dump
291
 
292
       .found_pid:
293
	shl	ecx, 8
294
	or	[ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK ; stack event
295
 
296
	mov	[check_idle_semaphore], 200
297
 
298
       .dump:
299
	DEBUGF	1,"ICMP_Handler - dumping\n"
300
 
301
	call	kernel_free
1165 hidnplayr 302
	add	esp, 8 ; pop (balance stack)
1159 hidnplayr 303
 
304
	ret
305
 
306
 
307
;--------------------------------
308
;
309
; ICMP_Handler_fragments:
310
;
311
;  Called by IP_handler,
312
;  this procedure will send reply's to ICMP echo's etc
313
;
314
;  IN:  Pointer to buffer in [esp]
315
;       size of buffer in [esp+4]
316
;       pointer to device struct in ebx
317
;       ICMP Packet size in ecx
318
;       pointer to ICMP Packet data in edx
319
;  OUT: /
320
;
321
;--------------------------------
322
 
323
align 4
324
ICMP_Handler_fragments:   ; works only on pure ethernet right now !
325
 
326
	DEBUGF	1,"ICMP_Handler_fragments - start\n"
327
 
328
	cmp	ecx, 65500
329
	jg	.dump
330
 
331
	cmp	byte [edx + ICMP_Packet.Type], ICMP_ECHO		    ; Is this an echo request? discard if not
332
	jne	.dump
333
 
334
	mov	esi, [esp]
335
 
336
	sub	ecx, ICMP_Packet.Data
337
	mov	eax, [esi + IPv4_Packet.SourceAddress]
338
	mov	ebx, [esi + IPv4_Packet.DestinationAddress]
339
	push	word [esi + IPv4_Packet.Identification]
340
 
341
	mov	di , [edx + ICMP_Packet.Identifier]
342
	shl	edi, 16
343
	mov	di , [edx + ICMP_Packet.SequenceNumber]
344
 
345
	mov	esi, edx
346
	add	esi, ICMP_Packet.Data
347
	pop	dx
348
	shl	edx, 16
349
	mov	dx , ICMP_ECHOREPLY shl 8 + 0				    ; Type + Code
350
 
351
	call	ICMP_create_Packet
352
 
353
       .dump:
354
	DEBUGF	1,"ICMP_Handler_fragments - end\n"
355
 
356
	call	kernel_free
1165 hidnplayr 357
	add	esp, 8 ; pop (balance stack)
1159 hidnplayr 358
	ret
359
 
360
;-----------------------------------------------------------------
361
;
362
; Note: ICMP only works on top of IP protocol :)
363
;
364
; inputs:
365
;
366
; eax = dest ip
367
; ebx = source ip
368
; ecx = data length
369
; dh = type
370
; dl = code
371
; high 16 bits of edx = fragment id (for IP header)
372
; esi = data offset
373
; edi = identifier shl 16 + sequence number
374
;
375
;-----------------------------------------------------------------
376
 
377
align 4
378
ICMP_create_Packet:
379
 
380
	DEBUGF 1,"Create ICMP Packet\n"
381
 
382
	push	esi edi edx
383
 
384
	add	ecx, ICMP_Packet.Data
385
	mov	di , IP_PROTO_ICMP
386
	shr	edx, 16
387
 
388
	call	IPv4_create_Packet
389
 
390
	cmp	edi, -1
391
	je	.exit
392
 
1165 hidnplayr 393
	DEBUGF 1,"full icmp packet size: %u\n", ebx
394
 
1159 hidnplayr 395
	pop	eax
396
	mov	word [edi + ICMP_Packet.Type], ax	; Write both type and code bytes at once
397
	pop	eax
398
	mov	[edi + ICMP_Packet.SequenceNumber], ax
399
	shr	eax, 16
400
	mov	[edi + ICMP_Packet.Identifier], ax
401
	mov	[edi + ICMP_Packet.Checksum], 0
402
 
403
	stdcall checksum_jb, edi , ecx
404
	xchg	al, ah
405
	mov	[edi + ICMP_Packet.Checksum], ax
406
 
407
	pop	esi
408
	sub	ecx, ICMP_Packet.Data
409
	add	edi, ICMP_Packet.Data
410
	push	cx
411
	shr	cx , 2
412
	rep	movsd
413
	pop	cx
414
	and	cx , 3
415
	rep	movsb
416
 
417
	sub	edi, ebx  ;; TODO: find a better way to remember start of packet
418
	xchg	ebx, edx
419
	mov	ecx, [ebx + ETH_DEVICE.transmit]
420
	push	edx edi ecx
421
	DEBUGF 1,"Sending ICMP Packet\n"
422
	ret						; Send the packet (create_packet routine outputs pointer to routine to send packet in eax)
423
 
424
  .exit:
1165 hidnplayr 425
	DEBUGF 1,"Creating ICMP Packet failed\n"
426
	add	esp, 3*4
1159 hidnplayr 427
	ret
428
 
429
 
430
 
431
 
432
;---------------------------------------------------------------------------
433
;
434
; ICMP_API
435
;
436
; This function is called by system function 75
437
;
438
; IN:  subfunction number in bl
439
;      device number in bh
440
;      ecx, edx, .. depends on subfunction
441
;
442
; OUT:
443
;
444
;---------------------------------------------------------------------------
445
 
446
align 4
447
ICMP_API:
448
 
449
	movzx	eax, bh
450
	shl	eax, 2
451
 
452
	test	bl, bl
453
	jz	.packets_tx	; 0
454
	dec	bl
455
	jz	.packets_rx	; 1
456
 
457
.error:
458
	mov	eax, -1
459
	ret
460
 
461
.packets_tx:
462
	add	eax, ICMP_PACKETS_TX
463
	mov	eax, [eax]
464
	ret
465
 
466
.packets_rx:
467
	add	eax, ICMP_PACKETS_RX
468
	mov	eax, [eax]
469
	ret