Subversion Repositories Kolibri OS

Rev

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

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