Subversion Repositories Kolibri OS

Rev

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

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