Subversion Repositories Kolibri OS

Rev

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