Subversion Repositories Kolibri OS

Rev

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