Subversion Repositories Kolibri OS

Rev

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