Subversion Repositories Kolibri OS

Rev

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

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