Subversion Repositories Kolibri OS

Rev

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