Subversion Repositories Kolibri OS

Rev

Rev 2553 | 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: 2555 $
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
2555 hidnplayr 624
        jz      .eth_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
 
2555 hidnplayr 647
  .eth_error:
648
        DEBUGF  1,"IPv4_output: ethernet error\n"
649
        add     esp, 6+2+4
650
        sub     edi, edi
651
        ret
652
 
1529 hidnplayr 653
  .arp_error:
2555 hidnplayr 654
        DEBUGF  1,"IPv4_output: ARP error (0x%x)\n", eax
2308 hidnplayr 655
        add     esp, 4+4+4+2+2
2555 hidnplayr 656
        sub     edi, edi
657
        ret
658
 
1529 hidnplayr 659
  .too_large:
2555 hidnplayr 660
        DEBUGF  1,"IPv4_output: error: Packet too large!\n"
2308 hidnplayr 661
        sub     edi, edi
662
        ret
1159 hidnplayr 663
 
664
 
1541 hidnplayr 665
 
666
 
667
 
668
;------------------------------------------------------------------
669
;
670
; IPv4_output_raw
671
;
672
; IN: eax = socket ptr
673
;     ecx = data length
674
;     esi = data ptr
675
;
676
; OUT: /
677
;
678
;------------------------------------------------------------------
679
align 4
680
IPv4_output_raw:
681
 
2308 hidnplayr 682
        DEBUGF 1,"IPv4_output_raw: size=%u ptr=%x socket=%x\n", ecx, esi, eax
1541 hidnplayr 683
 
2308 hidnplayr 684
        cmp     ecx, 1480               ;;;;; FIXME
685
        ja      .too_large
1541 hidnplayr 686
 
2308 hidnplayr 687
        sub     esp, 8
688
        push    esi eax
1541 hidnplayr 689
 
2308 hidnplayr 690
        call    ARP_IP_to_MAC
1541 hidnplayr 691
 
2308 hidnplayr 692
        test    eax, 0xffff0000         ; error bits
693
        jnz     .arp_error
1541 hidnplayr 694
 
695
  .continue:
696
 
2308 hidnplayr 697
        push    ebx     ; push the mac
698
        push    ax
1541 hidnplayr 699
 
2308 hidnplayr 700
        call    IPv4_dest_to_dev
701
        inc     [IP_PACKETS_TX+edi]
702
        mov     ebx, [NET_DRV_LIST+edi]
703
        lea     eax, [ebx + ETH_DEVICE.mac]
704
        mov     edx, esp
705
        mov     ecx, [esp + 6+4]
706
        add     ecx, sizeof.IPv4_header
707
        mov     di, ETHER_IPv4
708
        call    ETH_output
709
        jz      .error
1541 hidnplayr 710
 
2308 hidnplayr 711
        add     esp, 6  ; pop the mac
1541 hidnplayr 712
 
2308 hidnplayr 713
        mov     dword[esp+4+4], edx
714
        mov     dword[esp+4+4+4], eax
1541 hidnplayr 715
 
2308 hidnplayr 716
        pop     eax esi
1541 hidnplayr 717
;; todo: check socket options if we should add header, or just compute checksum
718
 
2308 hidnplayr 719
        push    edi ecx
720
        rep     movsb
721
        pop     ecx edi
1541 hidnplayr 722
 
2305 hidnplayr 723
;        [edi + IPv4_header.VersionAndIHL]              ; IPv4, normal length (no Optional header)
724
;        [edi + IPv4_header.TypeOfService]              ; nothing special, just plain ip packet
725
;        [edi + IPv4_header.TotalLength]
726
;        [edi + IPv4_header.TotalLength]                ; internet byte order
727
;        [edi + IPv4_header.FlagsAndFragmentOffset]
1541 hidnplayr 728
 
2308 hidnplayr 729
        mov     [edi + IPv4_header.HeaderChecksum], 0
1541 hidnplayr 730
 
2305 hidnplayr 731
;        [edi + IPv4_header.TimeToLive]                 ; ttl shl 8 + protocol
732
;        [edi + IPv4_header.Protocol]
733
;        [edi + IPv4_header.Identification]             ; fragment id
734
;        [edi + IPv4_header.SourceAddress]
735
;        [edi + IPv4_header.DestinationAddress]
1541 hidnplayr 736
 
2308 hidnplayr 737
        IPv4_checksum edi                       ;;;; todo: checksum for IP packet with options!
738
        add     edi, sizeof.IPv4_header
739
        DEBUGF  1,"IPv4 Packet for device %x created successfully\n", ebx
740
        call    [ebx + NET_DEVICE.transmit]
741
        ret
1541 hidnplayr 742
 
743
  .error:
2308 hidnplayr 744
        add     esp, 6
1541 hidnplayr 745
  .arp_error:
2308 hidnplayr 746
        add     esp, 8+4+4
1541 hidnplayr 747
  .too_large:
2308 hidnplayr 748
        DEBUGF  1,"IPv4_output_raw: Failed\n"
749
        sub     edi, edi
750
        ret
1541 hidnplayr 751
 
752
 
1529 hidnplayr 753
;--------------------------------------------------------
754
;
755
;
756
; IN: dword [esp] = pointer to buffer containing ipv4 packet to be fragmented
757
;     dword [esp+4] = buffer size
758
;     esi = pointer to ip header in that buffer
759
;     ecx = max size of fragments
760
;
761
; OUT: /
762
;
763
;--------------------------------------------------------
1159 hidnplayr 764
 
1482 hidnplayr 765
align 4
1529 hidnplayr 766
IPv4_fragment:
1206 hidnplayr 767
 
2308 hidnplayr 768
        DEBUGF 1,"IPv4_fragment\n"
1482 hidnplayr 769
 
2308 hidnplayr 770
        and     ecx, not 111b   ; align 4
1482 hidnplayr 771
 
2308 hidnplayr 772
        cmp     ecx, sizeof.IPv4_header + 8     ; must be able to put at least 8 bytes
773
        jb      .err2
1482 hidnplayr 774
 
2308 hidnplayr 775
        push    esi ecx
776
        mov     eax, [esi + IPv4_header.DestinationAddress]
777
        call    ARP_IP_to_MAC
778
        pop     ecx esi
779
        cmp     eax, -1
780
        jz      .err2
1482 hidnplayr 781
 
2308 hidnplayr 782
        push    ebx
783
        push    ax
1482 hidnplayr 784
 
2308 hidnplayr 785
        mov     ebx, [NET_DRV_LIST]
786
        lea     eax, [ebx + ETH_DEVICE.mac]
787
        push    eax
1482 hidnplayr 788
 
789
 
2308 hidnplayr 790
        push    esi                             ; ptr to ip header
791
        sub     ecx, sizeof.IPv4_header         ; substract header size
792
        push    ecx                             ; max data size
793
        push    dword 0                         ; offset
1482 hidnplayr 794
 
1529 hidnplayr 795
  .new_fragment:
2308 hidnplayr 796
        DEBUGF 1,"Ipv4_fragment - new_fragmentn"
1482 hidnplayr 797
 
798
 
2308 hidnplayr 799
        mov     eax, [esp + 3*4]
800
        lea     ebx, [esp + 4*4]
801
        mov     di , ETHER_IPv4
802
        call    ETH_output
1482 hidnplayr 803
 
2308 hidnplayr 804
        cmp     edi, -1
805
        jz      .err
1482 hidnplayr 806
 
1529 hidnplayr 807
; copy header
2308 hidnplayr 808
        mov     esi, [esp + 2*4]
809
        mov     ecx, 5  ; 5 dwords: TODO: use IHL field of the header!
810
        rep     movsd
1482 hidnplayr 811
 
1529 hidnplayr 812
; copy data
2308 hidnplayr 813
        mov     esi, [esp + 2*4]
814
        add     esi, sizeof.IPv4_header
815
        add     esi, [esp]      ; offset
1482 hidnplayr 816
 
2308 hidnplayr 817
        mov     ecx, [esp + 1*4]
818
        DEBUGF 1,"IPv4_fragment - copying data (%u bytes)\n", ecx
819
        rep     movsb
1482 hidnplayr 820
 
1529 hidnplayr 821
; now, correct header
2308 hidnplayr 822
        mov     ecx, [esp + 1*4]
823
        add     ecx, sizeof.IPv4_header
824
        xchg    cl, ch
825
        mov     [edi + IPv4_header.TotalLength], cx
1482 hidnplayr 826
 
2308 hidnplayr 827
        mov     ecx, [esp]              ; offset
828
        xchg    cl, ch
1482 hidnplayr 829
 
1529 hidnplayr 830
;        cmp     dword[esp + 4*4], 0     ; last fragment?;<<<<<<
831
;        je      .last_fragment
2308 hidnplayr 832
        or      cx, 1 shl 2             ; more fragments
1529 hidnplayr 833
;  .last_fragment:
2308 hidnplayr 834
        mov     [edi + IPv4_header.FlagsAndFragmentOffset], cx
1482 hidnplayr 835
 
2308 hidnplayr 836
        mov     [edi + IPv4_header.HeaderChecksum], 0
1482 hidnplayr 837
 
2308 hidnplayr 838
        ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<< send the packet
839
        mov     ecx, [esp + 1*4]
1482 hidnplayr 840
 
2308 hidnplayr 841
        push    edx eax
842
        IPv4_checksum edi
1529 hidnplayr 843
 
2308 hidnplayr 844
        call    [ebx + NET_DEVICE.transmit]
845
        ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
1529 hidnplayr 846
 
2308 hidnplayr 847
        mov     ecx,  [esp+4]
848
        add     [esp], ecx
1529 hidnplayr 849
 
2308 hidnplayr 850
        mov     ecx, [esp+3*4+6+4]      ; ptr to begin of buff
851
        add     ecx, [esp+3*4+6+4+4]    ; buff size
852
        sub     ecx, [esp+2*4]          ; ptr to ip header
853
        add     ecx, [esp]              ; offset
1529 hidnplayr 854
 
2308 hidnplayr 855
        DEBUGF 1,"Ipv4_fragment - bytes remaining: %u\n", ecx
1529 hidnplayr 856
 
2308 hidnplayr 857
        cmp     ecx, [esp+1*4]
858
        jae     .new_fragment
1529 hidnplayr 859
 
2308 hidnplayr 860
        mov     [esp+4], ecx            ; set fragment size to remaining packet size
861
        jmp     .new_fragment
1529 hidnplayr 862
 
863
      .err:
2308 hidnplayr 864
        DEBUGF 1,"Ipv4_fragment - failed\n"
1529 hidnplayr 865
      .done:
2308 hidnplayr 866
        add     esp, 12 + 4 + 6
1529 hidnplayr 867
      .err2:
2308 hidnplayr 868
        DEBUGF 1,"Ipv4_fragment - dumping\n"
869
        call    kernel_free
870
        add     esp, 4
1529 hidnplayr 871
 
2308 hidnplayr 872
        ret
1529 hidnplayr 873
 
874
 
875
 
1159 hidnplayr 876
;---------------------------------------------------------------------------
877
;
878
; IPv4_dest_to_dev
879
;
1529 hidnplayr 880
; IN:  eax = Destination IP
881
; OUT: edi = device id * 4
1159 hidnplayr 882
;
883
;---------------------------------------------------------------------------
884
align 4
885
IPv4_dest_to_dev:
886
 
2308 hidnplayr 887
        cmp     eax, 0xffffffff
888
        je      .invalid
1159 hidnplayr 889
 
2308 hidnplayr 890
        xor     edi, edi
891
        mov     ecx, MAX_IP
1159 hidnplayr 892
 
893
  .loop:
2308 hidnplayr 894
        mov     ebx, [IP_LIST+edi]
895
        and     ebx, [SUBNET_LIST+edi]
896
        jz      .next
1529 hidnplayr 897
 
2308 hidnplayr 898
        mov     edx, eax
899
        and     edx, [SUBNET_LIST+edi]
1159 hidnplayr 900
 
2308 hidnplayr 901
        cmp     ebx, edx
902
        je      .found_it
1529 hidnplayr 903
  .next:
2308 hidnplayr 904
        add     edi, 4
905
        loop    .loop
1159 hidnplayr 906
 
1529 hidnplayr 907
  .invalid:
2308 hidnplayr 908
        xor     edi, edi                        ; if none found, use device 0 as default device
1159 hidnplayr 909
 
910
  .found_it:
2308 hidnplayr 911
        DEBUGF  1,"IPv4_dest_to_dev: %u\n", edi
1159 hidnplayr 912
 
2308 hidnplayr 913
        ret
1159 hidnplayr 914
 
915
 
916
 
917
;---------------------------------------------------------------------------
918
;
919
; IPv4_get_frgmnt_num
920
;
921
; IN: /
922
; OUT: fragment number in ax
923
;
924
;---------------------------------------------------------------------------
925
align 4
926
IPv4_get_frgmnt_num:
2308 hidnplayr 927
        xor     ax, ax  ;;; TODO: replace this with real code
1159 hidnplayr 928
 
2308 hidnplayr 929
        ret
1159 hidnplayr 930
 
931
 
932
;---------------------------------------------------------------------------
933
;
934
; IPv4_API
935
;
936
; This function is called by system function 75
937
;
938
; IN:  subfunction number in bl
939
;      device number in bh
940
;      ecx, edx, .. depends on subfunction
941
;
942
; OUT:
943
;
944
;---------------------------------------------------------------------------
945
align 4
946
IPv4_API:
947
 
2308 hidnplayr 948
        movzx   eax, bh
949
        shl     eax, 2
1159 hidnplayr 950
 
2308 hidnplayr 951
        test    bl, bl
952
        jz      .packets_tx     ; 0
953
        dec     bl
954
        jz      .packets_rx     ; 1
955
        dec     bl
956
        jz      .read_ip        ; 2
957
        dec     bl
958
        jz      .write_ip       ; 3
959
        dec     bl
960
        jz      .read_dns       ; 4
961
        dec     bl
962
        jz      .write_dns      ; 5
963
        dec     bl
964
        jz      .read_subnet    ; 6
965
        dec     bl
966
        jz      .write_subnet   ; 7
967
        dec     bl
968
        jz      .read_gateway   ; 8
969
        dec     bl
970
        jz      .write_gateway  ; 9
1159 hidnplayr 971
 
1473 hidnplayr 972
  .error:
2308 hidnplayr 973
        mov     eax, -1
974
        ret
1159 hidnplayr 975
 
1473 hidnplayr 976
  .packets_tx:
2308 hidnplayr 977
        add     eax, IP_PACKETS_TX
978
        mov     eax, [eax]
979
        ret
1159 hidnplayr 980
 
1473 hidnplayr 981
  .packets_rx:
2308 hidnplayr 982
        add     eax, IP_PACKETS_RX
983
        mov     eax, [eax]
984
        ret
1159 hidnplayr 985
 
1473 hidnplayr 986
  .read_ip:
2308 hidnplayr 987
        add     eax, IP_LIST
988
        mov     eax, [eax]
989
        ret
1159 hidnplayr 990
 
1473 hidnplayr 991
  .write_ip:
2308 hidnplayr 992
        add     eax, IP_LIST
993
        mov     [eax], ecx
994
        xor     eax, eax
995
        ret
1159 hidnplayr 996
 
1473 hidnplayr 997
  .read_dns:
2308 hidnplayr 998
        add     eax, DNS_LIST
999
        mov     eax, [eax]
1000
        ret
1159 hidnplayr 1001
 
1473 hidnplayr 1002
  .write_dns:
2308 hidnplayr 1003
        add     eax, DNS_LIST
1004
        mov     [eax], ecx
1005
        xor     eax, eax
1006
        ret
1159 hidnplayr 1007
 
1473 hidnplayr 1008
  .read_subnet:
2308 hidnplayr 1009
        add     eax, SUBNET_LIST
1010
        mov     eax, [eax]
1011
        ret
1159 hidnplayr 1012
 
1473 hidnplayr 1013
  .write_subnet:
2308 hidnplayr 1014
        add     eax, SUBNET_LIST
1015
        mov     [eax], ecx
1016
        xor     eax, eax
1017
        ret
1159 hidnplayr 1018
 
1473 hidnplayr 1019
  .read_gateway:
2308 hidnplayr 1020
        add     eax, GATEWAY_LIST
1021
        mov     eax, [eax]
1022
        ret
1159 hidnplayr 1023
 
1473 hidnplayr 1024
  .write_gateway:
2308 hidnplayr 1025
        add     eax, GATEWAY_LIST
1026
        mov     [eax], ecx
1027
        xor     eax, eax
1028
        ret