Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
1159 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
1514 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved.    ;;
1159 hidnplayr 4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
1249 hidnplayr 6
;;  IPv4.INC                                                       ;;
1159 hidnplayr 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
 
1206 hidnplayr 19
$Revision: 1514 $
1159 hidnplayr 20
 
1514 hidnplayr 21
MAX_FRAGMENTS	equ 64
1159 hidnplayr 22
MAX_IP		equ MAX_NET_DEVICES
1514 hidnplayr 23
IP_MAX_INTERFACES   equ MAX_IP
1159 hidnplayr 24
 
25
struct	IPv4_Packet
26
	.VersionAndIHL		db  ?  ; Version[0-3 bits] and IHL(header length)[4-7 bits]
1514 hidnplayr 27
	.TypeOfService		db  ?  ; precedence [7-5] minimize delay [4], maximize throughput [3], maximize riliability [2] minimize momentary cost [1] and zero [0]
1159 hidnplayr 28
	.TotalLength		dw  ?
29
	.Identification 	dw  ?
30
	.FlagsAndFragmentOffset dw  ?  ; Flags[0-2] and FragmentOffset[3-15]
31
	.TimeToLive		db  ?  ;
32
	.Protocol		db  ?
33
	.HeaderChecksum 	dw  ?
34
	.SourceAddress		dd  ?
35
	.DestinationAddress	dd  ?
36
	.DataOrOptional:
37
ends
38
 
39
struct	FRAGMENT_slot
40
	.ttl			dw  ?  ; Time to live for this entry, 0 for empty slot's
41
	.id			dw  ?  ; Identification field from IP header
42
	.SrcIP			dd  ?  ; .. from IP header
43
	.DstIP			dd  ?  ; .. from IP header
44
	.ptr			dd  ?  ; Pointer to first packet
45
	.size:
46
ends
47
 
48
struct	FRAGMENT_entry		       ; This structure will replace the ethernet header in fragmented ip packets
49
	.PrevPtr		dd  ?  ; Pointer to previous fragment entry  (-1 for first packet)
50
	.NextPtr		dd  ?  ; Pointer to next fragment entry (-1 for last packet)
51
	.Owner			dd  ?  ; Pointer to structure of driver
1249 hidnplayr 52
				rb  2  ; to match ethernet header size          ; TODO: fix this hack
1159 hidnplayr 53
	.Data:			       ; Ip header begins here (we will need the IP header to re-construct the complete packet)
54
ends
55
 
56
align 4
57
uglobal
1514 hidnplayr 58
 
1159 hidnplayr 59
	IP_LIST 	rd  MAX_IP
60
	SUBNET_LIST	rd  MAX_IP
61
	DNS_LIST	rd  MAX_IP
62
	GATEWAY_LIST	rd  MAX_IP
1514 hidnplayr 63
 
1159 hidnplayr 64
	IP_PACKETS_TX	rd  MAX_IP
65
	IP_PACKETS_RX	rd  MAX_IP
1514 hidnplayr 66
 
1159 hidnplayr 67
	FRAGMENT_LIST	rb  MAX_FRAGMENTS*FRAGMENT_slot.size
68
endg
69
 
70
 
71
;-----------------------------------------------------------------
72
;
73
; IPv4_init
74
;
75
;  This function resets all IP variables
76
;
77
;  IN:  /
78
;  OUT: /
79
;
80
;-----------------------------------------------------------------
81
align 4
82
IPv4_init:
83
 
84
	or	eax, -1
1514 hidnplayr 85
	mov	edi, IP_LIST
86
	mov	ecx, 4*MAX_IP
1159 hidnplayr 87
	rep	stosd
88
 
1514 hidnplayr 89
	inc	eax
1159 hidnplayr 90
	mov	edi, FRAGMENT_LIST
91
	mov	ecx, FRAGMENT_slot.size*MAX_FRAGMENTS/4 + 2*MAX_IP
92
	rep	stosd
93
 
94
	ret
95
 
96
 
97
 
98
;-----------------------------------------------------------------
99
;
1249 hidnplayr 100
; IPv4_Handler:
1159 hidnplayr 101
;
1249 hidnplayr 102
;  Will check if IP Packet isnt damaged
1159 hidnplayr 103
;  and call appropriate handler. (TCP/UDP/ICMP/..)
104
;
105
;  It will also re-construct fragmented packets
106
;
107
;  IN:  Pointer to buffer in [esp]
108
;       size of buffer in [esp+4]
109
;       pointer to device struct in ebx
110
;       pointer to IP Packet data in edx
111
;  OUT: /
112
;
113
;-----------------------------------------------------------------
114
align 4
1473 hidnplayr 115
IPv4_handler:	 ; TODO: implement handler for IP options
1514 hidnplayr 116
		 ; TODO2: add code for raw sockets
1159 hidnplayr 117
 
1514 hidnplayr 118
	DEBUGF	1,"IPv4_Handler, packet from: %u.%u.%u.%u ",\
119
	[edx + IPv4_Packet.SourceAddress]:1,[edx + IPv4_Packet.SourceAddress + 1]:1,[edx + IPv4_Packet.SourceAddress + 2]:1,[edx + IPv4_Packet.SourceAddress + 3]:1
120
	DEBUGF	1,"to: %u.%u.%u.%u\n",\
121
	[edx + IPv4_Packet.DestinationAddress]:1,[edx + IPv4_Packet.DestinationAddress + 1]:1,[edx + IPv4_Packet.DestinationAddress + 2]:1,[edx + IPv4_Packet.DestinationAddress + 3]:1
1159 hidnplayr 122
 
1473 hidnplayr 123
;-------------------------------------------
124
; Check if the packet still has time to live
1159 hidnplayr 125
 
1473 hidnplayr 126
	cmp	byte [edx + IPv4_Packet.TimeToLive], 0
127
	je	.dump
128
 
129
;--------------------------------------
130
; First, check if IP packet has options
131
 
132
	movzx	eax, [edx + IPv4_Packet.VersionAndIHL]
133
	and	al , 0x0f					; get IHL(header length)
134
	cmp	al , 0x05					; IHL!= 5*4(20 bytes)
135
	jnz	.has_options
136
 
137
;-------------------------------
1514 hidnplayr 138
; Now, re-calculate the checksum
1473 hidnplayr 139
 
140
	push	edx ebx
1249 hidnplayr 141
	mov	esi, edx
1482 hidnplayr 142
	call	IPv4_checksum
1473 hidnplayr 143
	pop	ebx edx
1249 hidnplayr 144
 
1473 hidnplayr 145
	cmp	[edx + IPv4_Packet.HeaderChecksum], 0
1249 hidnplayr 146
	jne	.dump						; if checksum isn't valid then dump packet
147
 
1473 hidnplayr 148
	DEBUGF	1,"IPv4 Checksum is correct\n"
1254 hidnplayr 149
 
1514 hidnplayr 150
;-----------------------------------
151
; Check if destination IP is correct
1473 hidnplayr 152
 
1514 hidnplayr 153
	call	NET_ptr_to_num
154
	shl	edi, 2
1473 hidnplayr 155
 
1514 hidnplayr 156
	; check if it matches local ip
1473 hidnplayr 157
 
1514 hidnplayr 158
	mov	eax, dword[IP_LIST+edi]
159
	cmp	[edx + IPv4_Packet.DestinationAddress], eax
160
	je	.ip_ok
1159 hidnplayr 161
 
1514 hidnplayr 162
	; check for broadcast
163
 
164
	mov	eax, dword[SUBNET_LIST+edi]
1159 hidnplayr 165
	not	eax
1514 hidnplayr 166
	or	eax, dword[IP_LIST+edi]
167
	cmp	[edx + IPv4_Packet.DestinationAddress], eax
168
	je	.ip_ok
1159 hidnplayr 169
 
1514 hidnplayr 170
	; or a special broadcast
1159 hidnplayr 171
 
1514 hidnplayr 172
	cmp	[edx + IPv4_Packet.DestinationAddress], -1
173
	je	.ip_ok
1473 hidnplayr 174
 
1514 hidnplayr 175
;        ; maybe it's a multicast then
176
;
177
;        mov     eax, [edx + IPv4_Packet.DestinationAddress]
178
;        and     eax, 0xff000000
179
;        cmp     eax, 224 shl 24
180
;        je      .ip_ok
1159 hidnplayr 181
 
1514 hidnplayr 182
	; or a loopback address
1473 hidnplayr 183
 
1514 hidnplayr 184
	cmp	eax, 127 shl 24
185
	je	.ip_ok
1473 hidnplayr 186
 
1514 hidnplayr 187
	; or it's not meant for us..
1159 hidnplayr 188
 
1514 hidnplayr 189
	DEBUGF	2,"Destination address does not match!\n"
190
	jmp	.dump
1159 hidnplayr 191
 
1514 hidnplayr 192
;------------------------
193
; Now we can update stats
1159 hidnplayr 194
 
1514 hidnplayr 195
  .ip_ok:
196
	inc	[IP_PACKETS_RX+edi]
1159 hidnplayr 197
 
1473 hidnplayr 198
;----------------------------------
199
; Check if the packet is fragmented
1159 hidnplayr 200
 
1473 hidnplayr 201
	test	[edx + IPv4_Packet.FlagsAndFragmentOffset], 1 shl 5	; Is 'more fragments' flag set ?
202
	jnz	.has_fragments						; If so, we definately have a fragmented packet
1159 hidnplayr 203
 
1473 hidnplayr 204
	test	[edx + IPv4_Packet.FlagsAndFragmentOffset], 0xff1f	; If flag is not set, but there is a fragment offset, the packet is last in series of fragmented packets
205
	jnz	.is_last_fragment
206
 
207
;-------------------------------------------------------------------
208
; No, it's just a regular IP packet, pass it to the higher protocols
209
 
210
  .handle_it:							; We reach here if packet hasnt been fragmented, or when it already has been re-constructed
1159 hidnplayr 211
	movzx	eax, byte [edx + IPv4_Packet.VersionAndIHL]	; Calculate Header length by using IHL field
1514 hidnplayr 212
	and	eax, 0x0000000f 				;
1159 hidnplayr 213
	shl	eax, 2						;
214
	movzx	ecx, word [edx + IPv4_Packet.TotalLength]	; Calculate length of encapsulated Packet
215
	xchg	cl , ch 					;
216
	sub	ecx, eax					;
217
 
218
	add	eax, edx
219
	push	eax
1473 hidnplayr 220
 
221
	mov	esi, [edx + IPv4_Packet.SourceAddress]		; These values might be of interest to the higher protocols
222
	mov	edi, [edx + IPv4_Packet.DestinationAddress]	;
1159 hidnplayr 223
	mov	al , [edx + IPv4_Packet.Protocol]
224
	pop	edx						; Offset to data (tcp/udp/icmp/.. Packet)
225
 
226
	cmp	al , IP_PROTO_TCP
1514 hidnplayr 227
	je	TCP_input
1159 hidnplayr 228
 
229
	cmp	al , IP_PROTO_UDP
1514 hidnplayr 230
	je	UDP_input
1159 hidnplayr 231
 
232
	cmp	al , IP_PROTO_ICMP
1514 hidnplayr 233
	je	ICMP_input
1159 hidnplayr 234
 
1473 hidnplayr 235
	DEBUGF	2,"unknown Internet protocol: %u\n", al
1159 hidnplayr 236
 
237
  .dump:
1473 hidnplayr 238
	DEBUGF	2,"IP_Handler - dumping\n"
1159 hidnplayr 239
;        inc     [dumped_rx_count]
240
	call	kernel_free
241
	add	esp, 4						; pop (balance stack)
242
	ret
243
 
244
 
1473 hidnplayr 245
;---------------------------
246
; Fragmented packet handler
247
 
248
 
249
  .has_fragments:
250
	movzx	eax, [edx + IPv4_Packet.FlagsAndFragmentOffset]
251
	xchg	al , ah
1159 hidnplayr 252
	shl	ax , 3
1473 hidnplayr 253
 
1159 hidnplayr 254
	DEBUGF	1,"Fragmented packet, offset:%u, id:%x\n", ax, [edx + IPv4_Packet.Identification]:4
255
 
256
	test	ax , ax 					; Is this the first packet of the fragment?
1473 hidnplayr 257
	jz	.is_first_fragment
1159 hidnplayr 258
 
1473 hidnplayr 259
 
260
;-------------------------------------------------------
261
; We have a fragmented IP packet, but it's not the first
262
 
263
	DEBUGF	1,"Middle fragmented packet received!\n"
264
 
265
	call	IPv4_find_fragment_slot
266
	cmp	esi, -1
267
	je	.dump
268
 
269
	mov	word [esi + FRAGMENT_slot.ttl], 15		; Reset the ttl
270
	mov	esi, [esi + FRAGMENT_slot.ptr]
271
	or	edi, -1
272
  .find_last_entry:						; The following routine will try to find the last entry
273
	cmp	edi, [esi + FRAGMENT_entry.PrevPtr]
274
	jne	.destroy_slot					; Damn, something screwed up, remove the whole slot (and free buffers too if possible!)
275
	mov	edi, esi
276
	mov	esi, [esi + FRAGMENT_entry.NextPtr]
277
	cmp	esi, -1
278
	jne	.find_last_entry
279
								; We found the last entry (pointer is now in edi)
280
								; We are going to overwrite the ethernet header in received packet with a FRAGMENT_entry structure
281
 
282
	pop	eax						; pointer to packet
283
	mov	[edi + FRAGMENT_entry.NextPtr], eax		; update pointer of previous entry to the new entry
284
	mov	[eax + FRAGMENT_entry.NextPtr], -1
285
	mov	[eax + FRAGMENT_entry.PrevPtr], edi
286
	mov	[eax + FRAGMENT_entry.Owner], ebx
287
 
288
	add	esp, 4
289
	ret
290
 
291
 
292
;------------------------------------
293
; We have received the first fragment
294
 
295
  .is_first_fragment:
1159 hidnplayr 296
	DEBUGF	1,"First fragmented packet received!\n"
297
								; try to locate a free slot..
298
	mov	ecx, MAX_FRAGMENTS
299
	mov	esi, FRAGMENT_LIST
1473 hidnplayr 300
  .find_free_slot:
1159 hidnplayr 301
	cmp	word [esi + FRAGMENT_slot.ttl], 0
302
	je	.found_free_slot
303
	add	esi, FRAGMENT_slot.size
304
	loop	.find_free_slot
305
	jmp	.dump						; If no free slot was found, dump the packet
306
 
1473 hidnplayr 307
  .found_free_slot:						; We found a free slot, let's fill in the FRAGMENT_slot structure
1159 hidnplayr 308
	mov	word [esi + FRAGMENT_slot.ttl], 15		; RFC recommends 15 secs as ttl
309
	mov	ax , word [edx + IPv4_Packet.Identification]
310
	mov	word [esi + FRAGMENT_slot.id], ax
311
	mov	eax, dword [edx + IPv4_Packet.SourceAddress]
312
	mov	dword [esi + FRAGMENT_slot.SrcIP], eax
313
	mov	eax, dword [edx + IPv4_Packet.DestinationAddress]
314
	mov	dword [esi + FRAGMENT_slot.DstIP], eax
315
	pop	eax
316
	mov	dword [esi + FRAGMENT_slot.ptr], eax
317
								; Now, replace ethernet header in original buffer with a FRAGMENT_entry structure
318
	mov	[eax + FRAGMENT_entry.NextPtr], -1
319
	mov	[eax + FRAGMENT_entry.PrevPtr], -1
320
	mov	[eax + FRAGMENT_entry.Owner], ebx
321
 
322
	add	esp, 4						; balance stack and exit
323
	ret
324
 
325
 
1473 hidnplayr 326
;-----------------------------------
327
; We have received the last fragment
1159 hidnplayr 328
 
1473 hidnplayr 329
  .is_last_fragment:
330
	DEBUGF	1,"Last fragmented packet received!\n"
1159 hidnplayr 331
 
1473 hidnplayr 332
	call	IPv4_find_fragment_slot
1159 hidnplayr 333
	cmp	esi, -1
334
	je	.dump
335
 
336
	mov	esi, [esi + FRAGMENT_slot.ptr]			; We found the first entry, let's calculate total size of the packet in eax, so we can allocate a buffer
337
	push	esi
1473 hidnplayr 338
	xor	eax, eax
1159 hidnplayr 339
	or	edi, -1
1473 hidnplayr 340
 
341
  .count_bytes:
1159 hidnplayr 342
	cmp	[esi + FRAGMENT_entry.PrevPtr], edi
1473 hidnplayr 343
	jne	.destroy_slot_pop						  ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!)
1159 hidnplayr 344
	mov	cx, word [esi + FRAGMENT_entry.Data + IPv4_Packet.TotalLength]	  ; Add total length
345
	xchg	cl, ch
346
	DEBUGF	1,"Packet size: %u\n", cx
347
	add	ax, cx
348
	movzx	cx, byte [esi + FRAGMENT_entry.Data + IPv4_Packet.VersionAndIHL]  ; Sub Header length
349
	and	cx, 0x000F
350
	shl	cx, 2
351
	DEBUGF	1,"Header size: %u\n", cx
352
	sub	ax, cx
353
	mov	edi, esi
354
	mov	esi, [esi + FRAGMENT_entry.NextPtr]
355
	cmp	esi, -1
356
	jne	.count_bytes
357
 
1514 hidnplayr 358
	mov	esi, [esp+4]
1159 hidnplayr 359
	mov	[edi + FRAGMENT_entry.NextPtr], esi			       ; Add this packet to the chain, this simplifies the following code
360
	mov	[esi + FRAGMENT_entry.NextPtr], -1
361
	mov	[esi + FRAGMENT_entry.PrevPtr], edi
362
	mov	[esi + FRAGMENT_entry.Owner], ebx
363
 
364
	mov	cx, [edx + IPv4_Packet.TotalLength]			       ; Note: This time we dont substract Header length
365
	xchg	cl , ch
366
	DEBUGF	1,"Packet size: %u\n", cx
367
	add	ax , cx
368
	DEBUGF	1,"Total Received data size: %u\n", eax
369
 
370
	push	eax
371
	mov	ax , [edx + IPv4_Packet.FlagsAndFragmentOffset]
372
	xchg	al , ah
373
	shl	ax , 3
374
	add	cx , ax
375
	pop	eax
376
	DEBUGF	1,"Total Fragment size: %u\n", ecx
377
 
378
	cmp	ax, cx
379
	jne	.destroy_slot_pop
380
 
381
	push	eax
382
	push	eax
383
	call	kernel_alloc
384
	test	eax, eax
385
	je	.destroy_slot_pop							; If we dont have enough space to allocate the buffer, discard all packets in slot
386
	mov	edx, [esp+4]								; Get pointer to first fragment entry back in edx
387
 
1473 hidnplayr 388
  .rebuild_packet_loop:
1159 hidnplayr 389
	movzx	ecx, word [edx + FRAGMENT_entry.Data + IPv4_Packet.FlagsAndFragmentOffset]	; Calculate the fragment offset
1473 hidnplayr 390
	xchg	cl , ch 									;  intel byte order
1159 hidnplayr 391
	shl	cx , 3										;   multiply by 8 and clear first 3 bits
392
	DEBUGF	1,"Fragment offset: %u\n", cx
393
 
394
	lea	edi, [eax + ecx]								; Notice that edi will be equal to eax for first fragment
395
	movzx	ebx, byte [edx + FRAGMENT_entry.Data + IPv4_Packet.VersionAndIHL]		; Find header size (in ebx) of fragment
396
	and	bx , 0x000F									;
397
	shl	bx , 2										;
398
 
399
	lea	esi, [edx + FRAGMENT_entry.Data]						; Set esi to the correct begin of fragment
400
	movzx	ecx, word [edx + FRAGMENT_entry.Data + IPv4_Packet.TotalLength] 		; Calculate total length of fragment
401
	xchg	cl, ch										;  intel byte order
402
 
403
	cmp	edi, eax									; Is this packet the first fragment ?
404
	je	.first_fragment
405
	sub	cx, bx										; If not, dont copy the header
406
	add	esi, ebx									;
1473 hidnplayr 407
  .first_fragment:
1159 hidnplayr 408
 
409
	push	cx										; First copy dword-wise, then byte-wise
410
	shr	cx, 2										;
411
	rep	movsd										;
412
	pop	cx										;
413
	and	cx, 3										;
414
	rep	movsb										;
415
 
416
	push	eax
417
	push	edx										; Push pointer to fragment onto stack
1473 hidnplayr 418
	mov	ebx, [edx + FRAGMENT_entry.Owner]						; we need to remeber the owner, in case this is the last packet
1159 hidnplayr 419
	mov	edx, [edx + FRAGMENT_entry.NextPtr]						; Set edx to the next pointer
420
	call	kernel_free									; free the previous fragment buffer (this uses the value from stack)
421
	pop	eax
422
	cmp	edx, -1 									; Check if it is last fragment in chain
423
	jne	.rebuild_packet_loop
424
 
425
	pop	ecx										;
426
	xchg	cl, ch
427
	mov	edx, eax
428
	mov	word [edx + IPv4_Packet.TotalLength], cx
429
	add	esp, 8
430
 
1473 hidnplayr 431
	xchg	cl, ch		    ;
432
 
433
	push	ecx		   ;;;;
434
	push	eax		   ;;;;
435
 
436
;        mov     esi, edx           ;  This prints the IP packet to the debug board (usefull when using serial output debug..)
1159 hidnplayr 437
;                                   ;
438
;       @@:                         ;
439
;        lodsb                      ;
440
;        DEBUGF  1,"%x ", eax:2     ;
441
;        loop    @r                 ;
442
 
1473 hidnplayr 443
	jmp	.handle_it	    ; edx = buf ptr, ecx = size, [esp] buf ptr, [esp+4], total size, ebx=device ptr
1249 hidnplayr 444
 
1473 hidnplayr 445
  .destroy_slot_pop:
446
	add	esp, 4
447
  .destroy_slot:
448
	DEBUGF	1,"Destroy fragment slot!\n"
449
	; TODO!
450
	jmp	.dump
1249 hidnplayr 451
 
452
 
1159 hidnplayr 453
 
454
 
1473 hidnplayr 455
;-----------------------------------
456
; The IP packet has some options
1159 hidnplayr 457
 
1473 hidnplayr 458
  .has_options:
459
	jmp	.dump
1159 hidnplayr 460
 
461
 
1166 hidnplayr 462
 
1159 hidnplayr 463
 
464
 
465
 
466
;-----------------------------------------------------------------
467
;
468
; find fragment slot
469
;
1514 hidnplayr 470
; IN: pointer to fragmented packet in edx
1159 hidnplayr 471
; OUT: pointer to slot in edi, -1 on error
472
;
473
;-----------------------------------------------------------------
1473 hidnplayr 474
align 4
475
IPv4_find_fragment_slot:
1159 hidnplayr 476
 
1514 hidnplayr 477
;;; TODO: the RFC says we should check protocol number too
478
 
1159 hidnplayr 479
	push	eax ebx ecx edx
480
	mov	ax , word [edx + IPv4_Packet.Identification]
481
	mov	ecx, MAX_FRAGMENTS
482
	mov	esi, FRAGMENT_LIST
483
	mov	ebx, dword [edx + IPv4_Packet.SourceAddress]
484
	mov	edx, dword [edx + IPv4_Packet.DestinationAddress]
485
  .find_slot:
486
	cmp	word [esi + FRAGMENT_slot.id], ax
487
	jne	.try_next
488
	cmp	dword [esi + FRAGMENT_slot.SrcIP], ebx
489
	jne	.try_next
490
	cmp	dword [esi + FRAGMENT_slot.DstIP], edx
491
	je	.found_slot
492
  .try_next:
493
	add	esi, FRAGMENT_slot.size
494
	loop	.find_slot
1473 hidnplayr 495
;        pop     edx ebx
1159 hidnplayr 496
	or	esi, -1
497
;        ret
498
 
499
  .found_slot:
500
	pop	edx ecx ebx eax
501
	ret
502
 
503
 
504
;-----------------------------------------------------------------
505
;
506
; Decrease TimeToLive of all fragment slots
507
;
508
; IN: /
509
; OUT: /
510
;
511
;-----------------------------------------------------------------
512
align 4
513
IPv4_decrease_fragment_ttls:
514
 
515
	mov	esi, FRAGMENT_LIST
516
	mov	ecx, MAX_FRAGMENTS
517
  .loop:
518
	cmp	[esi + FRAGMENT_slot.ttl], 0
519
	je	.try_next
520
	dec	[esi + FRAGMENT_slot.ttl]
521
	jnz	.try_next
522
	DEBUGF 1,"Fragment slot timed-out!\n"
1514 hidnplayr 523
;;; TODO: clear all entry's of timed-out slot
1159 hidnplayr 524
  .try_next:
525
	add	esi, 4
526
	loop	.loop
527
	ret
528
 
529
 
530
 
531
 
532
 
1514 hidnplayr 533
;------------------------------------------------------------------
1159 hidnplayr 534
;
1514 hidnplayr 535
;
536
; IN: dword [esp] = pointer to packet to be fragmented
537
;     dword [esp+4] = buffer size
538
;     edx = pointer to IPv4 header in that packet
539
;     ecx = data length
540
;     ebx = device structure
541
;
542
; OUT: /
543
;
544
;------------------------------------------------------------------
545
align 4
546
IPv4_fragment:
547
 
548
;;; TODO: write code here
549
 
550
 
551
	call	kernel_free
552
	add	esp, 4
553
 
554
	ret
555
 
556
 
557
 
558
 
559
;------------------------------------------------------------------
560
;
1159 hidnplayr 561
; Create_IPv4_Packet
562
;
563
; IN: eax = dest ip
564
;     ebx = source ip
565
;     ecx = data length
1514 hidnplayr 566
;     dx  = fragment id  ;;;;
1159 hidnplayr 567
;     di  = protocol
568
;
1249 hidnplayr 569
; OUT: eax = pointer to buffer start
570
;      ebx = pointer to device struct (needed for sending procedure)
1159 hidnplayr 571
;      ecx = unchanged (packet size of embedded data)
1249 hidnplayr 572
;      edx = size of complete buffer
1514 hidnplayr 573
;      edi = pointer to start of data (0 on error)
1159 hidnplayr 574
;
1514 hidnplayr 575
;------------------------------------------------------------------
1159 hidnplayr 576
align 4
1196 hidnplayr 577
IPv4_create_packet:
1159 hidnplayr 578
 
1206 hidnplayr 579
	DEBUGF 1,"Create IPv4 Packet (size=%u)\n", ecx
1159 hidnplayr 580
 
1514 hidnplayr 581
	cmp	ecx, 65500	      ; Max IPv4 packet size
1159 hidnplayr 582
	jg	.exit_
583
 
1514 hidnplayr 584
	test	ebx, ebx	      ; if source ip = 0
1208 hidnplayr 585
	jnz	.ip_ok		      ; and local ip is valid
586
				      ; use local ip instead
587
	cmp	[IP_LIST],0xffffffff  ;
588
	je	.ip_ok		      ; TODO: find solution to send broadcast
1514 hidnplayr 589
				      ;  on device other then device 0
1208 hidnplayr 590
	mov	ebx, [IP_LIST]	      ;
591
				      ;
592
  .ip_ok:			      ;
593
 
1206 hidnplayr 594
	push	ecx eax ebx dx di
595
 
1159 hidnplayr 596
	cmp	eax, -1
1514 hidnplayr 597
	je	.broadcast		; If it is broadcast, just send
1159 hidnplayr 598
 
1196 hidnplayr 599
	call	ARP_IP_to_MAC
1159 hidnplayr 600
 
1196 hidnplayr 601
	cmp	eax, -1
1206 hidnplayr 602
	je	.not_found
1196 hidnplayr 603
 
1206 hidnplayr 604
	push	ebx
1196 hidnplayr 605
	push	ax
606
 
607
	jmp	.send
608
 
1159 hidnplayr 609
  .broadcast:
1196 hidnplayr 610
	push	word -1
611
	push	dword -1
1159 hidnplayr 612
 
613
  .send:
614
	call	IPv4_dest_to_dev
1171 hidnplayr 615
	inc	[IP_PACKETS_TX+4*edi]
1514 hidnplayr 616
	mov	edx, [NET_DRV_LIST + 4*edi]
1206 hidnplayr 617
	lea	eax, [edx + ETH_DEVICE.mac]
618
	mov	ebx, esp
619
	mov	ecx, [esp+18]	 ;; 18 or  22 ??
1159 hidnplayr 620
	add	ecx, IPv4_Packet.DataOrOptional
621
	mov	di , ETHER_IPv4
1514 hidnplayr 622
	;;; TODO: detect if packet is too large for ethernet, if so, call IPv4_fragment
623
	call	ETH_create_packet		   ;;; TODO: figure out a way to make this work with other protocols too
1206 hidnplayr 624
	add	esp, 6
1514 hidnplayr 625
	test	edi, edi
626
	jz	.exit
1159 hidnplayr 627
 
628
	mov	[edi + IPv4_Packet.VersionAndIHL], 0x45   ; IPv4, normal length (no Optional header)
629
	mov	[edi + IPv4_Packet.TypeOfService], 0
630
	xchg	ch, cl
631
	mov	[edi + IPv4_Packet.TotalLength], cx
632
	mov	[edi + IPv4_Packet.FlagsAndFragmentOffset], 0x0000
633
	mov	[edi + IPv4_Packet.TimeToLive], 128
634
	mov	[edi + IPv4_Packet.HeaderChecksum], 0
635
	pop	cx
636
	mov	[edi + IPv4_Packet.Protocol], cl
637
	pop	cx
638
	mov	[edi + IPv4_Packet.Identification], cx
639
	pop	ecx
640
	mov	[edi + IPv4_Packet.SourceAddress], ecx
641
	pop	ecx
642
	mov	[edi + IPv4_Packet.DestinationAddress], ecx
643
 
1473 hidnplayr 644
	push	eax edx esi
1249 hidnplayr 645
	mov	esi, edi
1482 hidnplayr 646
	call	IPv4_checksum
1473 hidnplayr 647
	pop	esi edx eax ecx
1159 hidnplayr 648
	add	edi, IPv4_Packet.DataOrOptional
649
 
1514 hidnplayr 650
	DEBUGF	1,"IPv4 Packet for device %x created successfully\n", ebx
1159 hidnplayr 651
 
652
	ret
653
 
1206 hidnplayr 654
 
655
  .not_found:
1514 hidnplayr 656
	DEBUGF	1,"Create IPv4 Packet - ARP entry not found!\n"
657
	;;;;;;
1159 hidnplayr 658
  .exit:
1206 hidnplayr 659
	add	esp, 16
1159 hidnplayr 660
  .exit_:
1514 hidnplayr 661
	DEBUGF	1,"Create IPv4 Packet - failed\n"
662
	and	edi, 0
1159 hidnplayr 663
	ret
664
 
665
 
666
 
1482 hidnplayr 667
align 4
668
IPv4_checksum:
1206 hidnplayr 669
 
1482 hidnplayr 670
; This is the fast procedure to create or check a IP header without options
671
;
672
; To create a new checksum, the checksum field must be set to 0 before computation
673
;
674
; To check an existing checksum, leave the checksum as is, and it will be 0 after this procedure, if it was correct
675
 
676
	xor	edx, edx
677
 
678
	add	dl, [esi+1]
679
	adc	dh, [esi+0]
680
 
681
	adc	dl, [esi+3]
682
	adc	dh, [esi+2]
683
 
684
	adc	dl, [esi+5]
685
	adc	dh, [esi+4]
686
 
687
	adc	dl, [esi+7]
688
	adc	dh, [esi+6]
689
 
690
	adc	dl, [esi+9]
691
	adc	dh, [esi+8]
692
 
693
; we skip 11th and 12th byte, they are the checksum bytes and should be 0 for re-calculation
694
 
695
	adc	dl, [esi+13]
696
	adc	dh, [esi+12]
697
 
698
	adc	dl, [esi+15]
699
	adc	dh, [esi+14]
700
 
701
	adc	dl, [esi+17]
702
	adc	dh, [esi+16]
703
 
704
	adc	dl, [esi+19]
705
	adc	dh, [esi+18]
706
 
707
	adc	edx, 0
708
 
709
	call	checksum_2
710
 
711
	neg	word [esi+10]		; zero will stay zero so we just get the checksum
712
	add	word [esi+10], dx	;  , else we will get (new checksum - old checksum) in the end, wich should be 0 :)
713
 
714
	ret
715
 
716
 
717
 
718
 
719
 
1159 hidnplayr 720
;---------------------------------------------------------------------------
721
;
722
; IPv4_dest_to_dev
723
;
724
; IN: Destination IP in eax
725
; OUT: device id in edi
726
;
727
;---------------------------------------------------------------------------
728
align 4
729
IPv4_dest_to_dev:
730
 
731
	DEBUGF 1,"IPv4 destination to device: "
732
 
733
	xor	edi, edi
734
	mov	ecx, MAX_IP
735
 
736
  .loop:
737
	mov	ebx, [IP_LIST+edi]		; we dont need to worry about non exisiting ip interfaces
738
	and	ebx, [SUBNET_LIST+edi]		; they have IP and SUBNET set to all one's, so they will have no match except 255.255.255.255
739
						; (only a moron would insert that ip into this function..)
740
	mov	edx, eax
741
	and	edx, [SUBNET_LIST+edi]
742
 
743
	cmp	ebx, edx
744
	je	.found_it
745
 
746
	add	edi, 4
747
	loop	.loop
748
 
749
	xor	edi, edi	; if none found, use device 0 as default device
750
 
751
  .found_it:
752
	shr	edi, 2
753
 
1473 hidnplayr 754
	DEBUGF	1,"%u\n",edi
1159 hidnplayr 755
 
756
	ret
757
 
758
 
759
 
760
;---------------------------------------------------------------------------
761
;
762
; IPv4_get_frgmnt_num
763
;
764
; IN: /
765
; OUT: fragment number in ax
766
;
767
;---------------------------------------------------------------------------
768
align 4
769
IPv4_get_frgmnt_num:
770
	xor	ax, ax	;;; TODO: replace this with real code
771
 
772
	ret
773
 
774
 
775
;---------------------------------------------------------------------------
776
;
777
; IPv4_API
778
;
779
; This function is called by system function 75
780
;
781
; IN:  subfunction number in bl
782
;      device number in bh
783
;      ecx, edx, .. depends on subfunction
784
;
785
; OUT:
786
;
787
;---------------------------------------------------------------------------
788
align 4
789
IPv4_API:
790
 
791
	movzx	eax, bh
792
	shl	eax, 2
793
 
794
	test	bl, bl
795
	jz	.packets_tx	; 0
796
	dec	bl
797
	jz	.packets_rx	; 1
798
	dec	bl
799
	jz	.read_ip	; 2
800
	dec	bl
801
	jz	.write_ip	; 3
802
	dec	bl
803
	jz	.read_dns	; 4
804
	dec	bl
805
	jz	.write_dns	; 5
806
	dec	bl
807
	jz	.read_subnet	; 6
808
	dec	bl
809
	jz	.write_subnet	; 7
810
	dec	bl
811
	jz	.read_gateway	; 8
812
	dec	bl
813
	jz	.write_gateway	; 9
814
 
1473 hidnplayr 815
  .error:
1159 hidnplayr 816
	mov	eax, -1
817
	ret
818
 
1473 hidnplayr 819
  .packets_tx:
1159 hidnplayr 820
	add	eax, IP_PACKETS_TX
821
	mov	eax, [eax]
822
	ret
823
 
1473 hidnplayr 824
  .packets_rx:
1159 hidnplayr 825
	add	eax, IP_PACKETS_RX
826
	mov	eax, [eax]
827
	ret
828
 
1473 hidnplayr 829
  .read_ip:
1159 hidnplayr 830
	add	eax, IP_LIST
831
	mov	eax, [eax]
832
	ret
833
 
1473 hidnplayr 834
  .write_ip:
1159 hidnplayr 835
	add	eax, IP_LIST
836
	mov	[eax], ecx
837
	xor	eax, eax
838
	ret
839
 
1473 hidnplayr 840
  .read_dns:
1159 hidnplayr 841
	add	eax, DNS_LIST
842
	mov	eax, [eax]
843
	ret
844
 
1473 hidnplayr 845
  .write_dns:
1159 hidnplayr 846
	add	eax, DNS_LIST
847
	mov	[eax], ecx
848
	xor	eax, eax
849
	ret
850
 
1473 hidnplayr 851
  .read_subnet:
1159 hidnplayr 852
	add	eax, SUBNET_LIST
853
	mov	eax, [eax]
854
	ret
855
 
1473 hidnplayr 856
  .write_subnet:
1159 hidnplayr 857
	add	eax, SUBNET_LIST
858
	mov	[eax], ecx
859
	xor	eax, eax
860
	ret
861
 
1473 hidnplayr 862
  .read_gateway:
1159 hidnplayr 863
	add	eax, GATEWAY_LIST
864
	mov	eax, [eax]
865
	ret
866
 
1473 hidnplayr 867
  .write_gateway:
1159 hidnplayr 868
	add	eax, GATEWAY_LIST
869
	mov	[eax], ecx
870
	xor	eax, eax
871
	ret
872