Subversion Repositories Kolibri OS

Rev

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

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