Subversion Repositories Kolibri OS

Rev

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