Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
6122 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2016. All rights reserved.    ;;
3545 hidnplayr 4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  IPv4.INC                                                       ;;
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
 
4850 mario79 19
$Revision: 6122 $
3545 hidnplayr 20
 
4053 hidnplayr 21
IPv4_MAX_FRAGMENTS              = 64
4387 hidnplayr 22
IPv4_MAX_ROUTES                 = 64
3545 hidnplayr 23
 
4387 hidnplayr 24
IPv4_ROUTE_FLAG_UP              = 1 shl 0
25
IPv4_ROUTE_FLAG_GATEWAY         = 1 shl 1
26
IPv4_ROUTE_FLAG_HOST            = 1 shl 2
27
IPv4_ROUTE_FLAG_D               = 1 shl 3       ; Route was created by a redirect
28
IPv4_ROUTE_FLAG_M               = 1 shl 4       ; Route was modified by a redirect
29
 
3545 hidnplayr 30
struct  IPv4_header
31
 
32
        VersionAndIHL           db ?    ; Version[0-3 bits] and IHL(header length)[4-7 bits]
33
        TypeOfService           db ?    ; precedence [7-5] minimize delay [4], maximize throughput [3], maximize riliability [2] minimize momentary cost [1] and zero [0]
34
        TotalLength             dw ?
35
        Identification          dw ?
36
        FlagsAndFragmentOffset  dw ?    ; Flags[0-2] and FragmentOffset[3-15]
37
        TimeToLive              db ?    ;
38
        Protocol                db ?
39
        HeaderChecksum          dw ?
40
        SourceAddress           dd ?
41
        DestinationAddress      dd ?
42
 
43
ends
44
 
4052 hidnplayr 45
struct  IPv4_FRAGMENT_slot
3545 hidnplayr 46
 
47
        ttl                     dw ?    ; Time to live for this entry, 0 for empty slot's
48
        id                      dw ?    ; Identification field from IP header
49
        SrcIP                   dd ?    ; .. from IP header
50
        DstIP                   dd ?    ; .. from IP header
51
        ptr                     dd ?    ; Pointer to first packet
52
 
53
ends
54
 
4052 hidnplayr 55
struct  IPv4_FRAGMENT_entry             ; This structure will replace the ethernet header in fragmented ip packets
3545 hidnplayr 56
 
57
        PrevPtr                 dd ?    ; Pointer to previous fragment entry  (-1 for first packet)
58
        NextPtr                 dd ?    ; Pointer to next fragment entry (-1 for last packet)
59
        Owner                   dd ?    ; Pointer to structure of driver
60
                                rb 2    ; to match ethernet header size         ;;; FIXME
61
                                        ; Ip header begins here (we will need the IP header to re-construct the complete packet)
62
ends
63
 
4387 hidnplayr 64
struct  IPv4_ROUTE
3545 hidnplayr 65
 
4387 hidnplayr 66
        Destination             dd ?
67
        Gateway                 dd ?
68
        Flags                   dd ?
69
        Use                     dd ?
70
        Interface               dd ?
71
 
72
ends
73
 
74
 
3698 hidnplayr 75
uglobal
3545 hidnplayr 76
align 4
77
 
3600 hidnplayr 78
        IP_LIST                 rd NET_DEVICES_MAX
79
        SUBNET_LIST             rd NET_DEVICES_MAX
80
        DNS_LIST                rd NET_DEVICES_MAX
81
        GATEWAY_LIST            rd NET_DEVICES_MAX
82
        BROADCAST_LIST          rd NET_DEVICES_MAX
3545 hidnplayr 83
 
4052 hidnplayr 84
        IPv4_packets_tx         rd NET_DEVICES_MAX
85
        IPv4_packets_rx         rd NET_DEVICES_MAX
86
        IPv4_packets_dumped     rd NET_DEVICES_MAX
3545 hidnplayr 87
 
4052 hidnplayr 88
        IPv4_FRAGMENT_LIST      rb IPv4_MAX_FRAGMENTS * sizeof.IPv4_FRAGMENT_slot
3698 hidnplayr 89
 
4387 hidnplayr 90
        IPv4_ROUTES             rd IPv4_MAX_ROUTES * sizeof.IPv4_ROUTE
91
 
3545 hidnplayr 92
endg
93
 
94
 
6011 hidnplayr 95
;-----------------------------------------------------------------;
96
;                                                                 ;
97
; ipv4_init: Resets all IPv4 variables                            ;
98
;                                                                 ;
99
;-----------------------------------------------------------------;
100
macro   ipv4_init {
3545 hidnplayr 101
 
102
        xor     eax, eax
103
        mov     edi, IP_LIST
4052 hidnplayr 104
        mov     ecx, 7*NET_DEVICES_MAX + (sizeof.IPv4_FRAGMENT_slot*IPv4_MAX_FRAGMENTS)/4
3711 clevermous 105
        rep stosd
3545 hidnplayr 106
 
107
}
108
 
109
 
6011 hidnplayr 110
;-----------------------------------------------------------------;
111
;                                                                 ;
112
; Decrease TimeToLive of all fragment slots                       ;
113
;                                                                 ;
114
;-----------------------------------------------------------------;
115
macro ipv4_decrease_fragment_ttls {
3545 hidnplayr 116
 
117
local   .loop, .next
118
 
4052 hidnplayr 119
        mov     esi, IPv4_FRAGMENT_LIST
120
        mov     ecx, IPv4_MAX_FRAGMENTS
3545 hidnplayr 121
  .loop:
4052 hidnplayr 122
        cmp     [esi + IPv4_FRAGMENT_slot.ttl], 0
3545 hidnplayr 123
        je      .next
4052 hidnplayr 124
        dec     [esi + IPv4_FRAGMENT_slot.ttl]
3545 hidnplayr 125
        jz      .died
126
  .next:
4052 hidnplayr 127
        add     esi, sizeof.IPv4_FRAGMENT_slot
3545 hidnplayr 128
        dec     ecx
129
        jnz     .loop
130
        jmp     .done
131
 
132
  .died:
3556 hidnplayr 133
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4 Fragment slot timed-out!\n"
3545 hidnplayr 134
;;; TODO: clear all entry's of timed-out slot
135
        jmp     .next
136
 
137
  .done:
138
}
139
 
140
 
141
 
6011 hidnplayr 142
macro ipv4_checksum ptr {
3545 hidnplayr 143
 
144
; This is the fast procedure to create or check an IP header without options
145
; To create a new checksum, the checksum field must be set to 0 before computation
146
; To check an existing checksum, leave the checksum as is, and it will be 0 after this procedure, if it was correct
147
 
148
        push    ebx
149
        xor     ebx, ebx
150
        add     bl, [ptr+1]
151
        adc     bh, [ptr+0]
152
 
153
        adc     bl, [ptr+3]
154
        adc     bh, [ptr+2]
155
 
156
        adc     bl, [ptr+5]
157
        adc     bh, [ptr+4]
158
 
159
        adc     bl, [ptr+7]
160
        adc     bh, [ptr+6]
161
 
162
        adc     bl, [ptr+9]
163
        adc     bh, [ptr+8]
164
 
165
; we skip 11th and 12th byte, they are the checksum bytes and should be 0 for re-calculation
166
 
167
        adc     bl, [ptr+13]
168
        adc     bh, [ptr+12]
169
 
170
        adc     bl, [ptr+15]
171
        adc     bh, [ptr+14]
172
 
173
        adc     bl, [ptr+17]
174
        adc     bh, [ptr+16]
175
 
176
        adc     bl, [ptr+19]
177
        adc     bh, [ptr+18]
178
 
179
        adc     ebx, 0
180
 
181
        push    ecx
182
        mov     ecx, ebx
183
        shr     ecx, 16
184
        and     ebx, 0xffff
185
        add     ebx, ecx
186
 
187
        mov     ecx, ebx
188
        shr     ecx, 16
189
        add     ebx, ecx
190
 
191
        not     bx
192
        jnz     .not_zero
193
        dec     bx
194
  .not_zero:
195
        xchg    bl, bh
196
        pop     ecx
197
 
198
        neg     word [ptr+10]           ; zero will stay zero so we just get the checksum
199
        add     word [ptr+10], bx       ;  , else we will get (new checksum - old checksum) in the end, wich should be 0 :)
200
        pop     ebx
201
 
202
}
203
 
204
 
205
 
6011 hidnplayr 206
;-----------------------------------------------------------------;
207
;                                                                 ;
208
; ipv4_input: Check if IPv4 Packet isnt damaged and call          ;
209
; appropriate handler. (TCP/UDP/ICMP/..)                          ;
210
; We will also re-construct fragmented packets.                   ;
211
;                                                                 ;
212
;  IN:  Pointer to buffer in [esp]                                ;
213
;       pointer to device struct in ebx                           ;
214
;       pointer to IPv4 header in edx                             ;
215
;       size of IPv4 packet in ecx                                ;
216
;                                                                 ;
217
;  OUT: /                                                         ;
218
;                                                                 ;
219
;-----------------------------------------------------------------;
3545 hidnplayr 220
align 4
6011 hidnplayr 221
ipv4_input:
3545 hidnplayr 222
 
5522 hidnplayr 223
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: packet from %u.%u.%u.%u ",\
3545 hidnplayr 224
        [edx + IPv4_header.SourceAddress + 0]:1,[edx + IPv4_header.SourceAddress + 1]:1,\
225
        [edx + IPv4_header.SourceAddress + 2]:1,[edx + IPv4_header.SourceAddress + 3]:1
5522 hidnplayr 226
        DEBUGF  DEBUG_NETWORK_VERBOSE, "to %u.%u.%u.%u\n",\
3545 hidnplayr 227
        [edx + IPv4_header.DestinationAddress + 0]:1,[edx + IPv4_header.DestinationAddress + 1]:1,\
228
        [edx + IPv4_header.DestinationAddress + 2]:1,[edx + IPv4_header.DestinationAddress + 3]:1
229
 
6011 hidnplayr 230
        call    net_ptr_to_num4
5842 hidnplayr 231
        cmp     edi, -1
232
        je      .invalid_device
233
 
3545 hidnplayr 234
;-------------------------------
235
; re-calculate the checksum
236
 
6011 hidnplayr 237
        ipv4_checksum edx
3545 hidnplayr 238
        jnz     .dump                                           ; if checksum isn't valid then dump packet
239
 
3556 hidnplayr 240
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Checksum ok\n"
3545 hidnplayr 241
 
5842 hidnplayr 242
;--------------------------------
243
; Check if destination IP matches
3545 hidnplayr 244
 
5842 hidnplayr 245
; local ip (Using RFC1122 strong end system model)
3545 hidnplayr 246
        mov     eax, [edx + IPv4_header.DestinationAddress]
247
        cmp     eax, [IP_LIST + edi]
248
        je      .ip_ok
249
 
5842 hidnplayr 250
; network layer broadcast
3545 hidnplayr 251
        cmp     eax, [BROADCAST_LIST + edi]
252
        je      .ip_ok
253
 
5842 hidnplayr 254
; physical layer broadcast (255.255.255.255)
3545 hidnplayr 255
        cmp     eax, 0xffffffff
256
        je      .ip_ok
257
 
5842 hidnplayr 258
; multicast (224.0.0.0/4 = 224.0.0.0 to 239.255.255.255)
3545 hidnplayr 259
        and     eax, 0x0fffffff
260
        cmp     eax, 224
261
        je      .ip_ok
262
 
5842 hidnplayr 263
; maybe we just dont have an IP yet and should accept everything on the IP level
4976 hidnplayr 264
        cmp     [IP_LIST + edi], 0
3545 hidnplayr 265
        je      .ip_ok
266
 
5842 hidnplayr 267
; or it's just not meant for us.. :(
3556 hidnplayr 268
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Destination address does not match!\n"
3545 hidnplayr 269
        jmp     .dump
270
 
271
;------------------------
272
; Now we can update stats
273
 
274
  .ip_ok:
4052 hidnplayr 275
        inc     [IPv4_packets_rx + edi]
3545 hidnplayr 276
 
277
;----------------------------------
278
; Check if the packet is fragmented
279
 
280
        test    [edx + IPv4_header.FlagsAndFragmentOffset], 1 shl 5     ; Is 'more fragments' flag set ?
281
        jnz     .has_fragments                                          ; If so, we definately have a fragmented packet
282
 
283
        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
284
        jnz     .is_last_fragment
285
 
286
;-------------------------------------------------------------------
287
; No, it's just a regular IP packet, pass it to the higher protocols
288
 
289
  .handle_it:                                                   ; We reach here if packet hasnt been fragmented, or when it already has been re-constructed
290
 
291
        movzx   esi, [edx + IPv4_header.VersionAndIHL]          ; Calculate Header length by using IHL field
292
        and     esi, 0x0000000f                                 ;
293
        shl     esi, 2                                          ;
294
 
295
        movzx   ecx, [edx + IPv4_header.TotalLength]            ; Calculate length of encapsulated Packet
296
        xchg    cl, ch                                          ;
297
        sub     ecx, esi                                        ;
298
 
299
        mov     al, [edx + IPv4_header.Protocol]
300
        add     esi, edx                                        ; make esi ptr to data
301
 
302
        cmp     al, IP_PROTO_TCP
6011 hidnplayr 303
        je      tcp_input
3545 hidnplayr 304
 
305
        cmp     al, IP_PROTO_UDP
6011 hidnplayr 306
        je      udp_input
3545 hidnplayr 307
 
308
        cmp     al, IP_PROTO_ICMP
6011 hidnplayr 309
        je      icmp_input
3545 hidnplayr 310
 
5842 hidnplayr 311
;-------------------------------
312
; Look for a matching RAW socket
313
        pusha
314
        mov     ecx, socket_mutex
315
        call    mutex_lock
316
        popa
317
 
318
        add     ecx, esi
319
        sub     ecx, edx
320
        mov     esi, edx
321
        movzx   edx, al
322
        mov     eax, net_sockets
323
  .next_socket:
324
        mov     eax, [eax + SOCKET.NextPtr]
325
        or      eax, eax
326
        jz      .dump_unlock
327
 
328
        cmp     [eax + SOCKET.Domain], AF_INET4
329
        jne     .next_socket
330
 
331
        cmp     [eax + SOCKET.Protocol], edx
332
        jne     .next_socket
333
 
334
        pusha
335
        mov     ecx, socket_mutex
336
        call    mutex_unlock
337
        popa
338
 
339
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: found matching RAW socket: 0x%x\n", eax
340
 
341
        pusha
342
        lea     ecx, [eax + SOCKET.mutex]
343
        call    mutex_lock
344
        popa
345
 
6011 hidnplayr 346
        jmp     socket_input
5842 hidnplayr 347
 
348
  .dump_unlock:
349
 
350
        pusha
351
        mov     ecx, socket_mutex
352
        call    mutex_unlock
353
        popa
354
 
3556 hidnplayr 355
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: unknown protocol %u\n", al
3545 hidnplayr 356
 
357
  .dump:
3556 hidnplayr 358
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: dumping\n"
5842 hidnplayr 359
        inc     [IPv4_packets_dumped + edi]
6011 hidnplayr 360
        call    net_buff_free
3545 hidnplayr 361
        ret
362
 
5842 hidnplayr 363
  .invalid_device:
364
        DEBUGF  DEBUG_NETWORK_ERROR, "IPv4_input: packet originated from invalid device\n"
6011 hidnplayr 365
        call    net_buff_free
5842 hidnplayr 366
        ret
3545 hidnplayr 367
 
5842 hidnplayr 368
 
3545 hidnplayr 369
;---------------------------
370
; Fragmented packet handler
371
 
372
 
373
  .has_fragments:
374
        movzx   eax, [edx + IPv4_header.FlagsAndFragmentOffset]
375
        xchg    al, ah
376
        shl     ax, 3
377
 
4258 hidnplayr 378
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: fragmented packet offset=%u id=%x ptr=0x%x\n", ax, [edx + IPv4_header.Identification]:4, edx
3545 hidnplayr 379
 
380
        test    ax, ax                                          ; Is this the first packet of the fragment?
381
        jz      .is_first_fragment
382
 
383
 
384
;-------------------------------------------------------
385
; We have a fragmented IP packet, but it's not the first
386
 
3556 hidnplayr 387
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Middle fragment packet received!\n"
3545 hidnplayr 388
 
6011 hidnplayr 389
        call    ipv4_find_fragment_slot
3545 hidnplayr 390
        cmp     esi, -1
391
        je      .dump
392
 
4052 hidnplayr 393
        mov     [esi + IPv4_FRAGMENT_slot.ttl], 15              ; Reset the ttl
394
        mov     esi, [esi + IPv4_FRAGMENT_slot.ptr]
3545 hidnplayr 395
        or      edi, -1
396
  .find_last_entry:                                             ; The following routine will try to find the last entry
4052 hidnplayr 397
        cmp     edi, [esi + IPv4_FRAGMENT_entry.PrevPtr]
3545 hidnplayr 398
        jne     .destroy_slot                                   ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!)
399
        mov     edi, esi
4052 hidnplayr 400
        mov     esi, [esi + IPv4_FRAGMENT_entry.NextPtr]
3545 hidnplayr 401
        cmp     esi, -1
402
        jne     .find_last_entry
403
                                                                ; We found the last entry (pointer is now in edi)
404
                                                                ; We are going to overwrite the ethernet header in received packet with a FRAGMENT_entry structure
405
 
406
        pop     eax                                             ; pointer to packet
4052 hidnplayr 407
        mov     [edi + IPv4_FRAGMENT_entry.NextPtr], eax        ; update pointer of previous entry to the new entry
408
        mov     [eax + IPv4_FRAGMENT_entry.NextPtr], -1
409
        mov     [eax + IPv4_FRAGMENT_entry.PrevPtr], edi
410
        mov     [eax + IPv4_FRAGMENT_entry.Owner], ebx
3545 hidnplayr 411
 
412
        ret
413
 
414
 
415
;------------------------------------
416
; We have received the first fragment
417
 
418
  .is_first_fragment:
3556 hidnplayr 419
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: First fragment packet received!\n"
3545 hidnplayr 420
                                                                ; try to locate a free slot..
4052 hidnplayr 421
        mov     ecx, IPv4_MAX_FRAGMENTS
422
        mov     esi, IPv4_FRAGMENT_LIST
3545 hidnplayr 423
  .find_free_slot:
4052 hidnplayr 424
        cmp     word [esi + IPv4_FRAGMENT_slot.ttl], 0
3545 hidnplayr 425
        je      .found_free_slot
4052 hidnplayr 426
        add     esi, sizeof.IPv4_FRAGMENT_slot
3545 hidnplayr 427
        loop    .find_free_slot
428
        jmp     .dump                                           ; If no free slot was found, dump the packet
429
 
430
  .found_free_slot:                                             ; We found a free slot, let's fill in the FRAGMENT_slot structure
4052 hidnplayr 431
        mov     [esi + IPv4_FRAGMENT_slot.ttl], 15              ; RFC recommends 15 secs as ttl
3545 hidnplayr 432
        mov     ax, [edx + IPv4_header.Identification]
4052 hidnplayr 433
        mov     [esi + IPv4_FRAGMENT_slot.id], ax
3545 hidnplayr 434
        mov     eax, [edx + IPv4_header.SourceAddress]
4052 hidnplayr 435
        mov     [esi + IPv4_FRAGMENT_slot.SrcIP], eax
3545 hidnplayr 436
        mov     eax, [edx + IPv4_header.DestinationAddress]
4052 hidnplayr 437
        mov     [esi + IPv4_FRAGMENT_slot.DstIP], eax
3545 hidnplayr 438
        pop     eax
4052 hidnplayr 439
        mov     [esi + IPv4_FRAGMENT_slot.ptr], eax
3545 hidnplayr 440
                                                                ; Now, replace ethernet header in original buffer with a FRAGMENT_entry structure
4052 hidnplayr 441
        mov     [eax + IPv4_FRAGMENT_entry.NextPtr], -1
442
        mov     [eax + IPv4_FRAGMENT_entry.PrevPtr], -1
443
        mov     [eax + IPv4_FRAGMENT_entry.Owner], ebx
3545 hidnplayr 444
 
445
        ret
446
 
447
 
448
;-----------------------------------
449
; We have received the last fragment
450
 
451
  .is_last_fragment:
3556 hidnplayr 452
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Last fragment packet received!\n"
3545 hidnplayr 453
 
6011 hidnplayr 454
        call    ipv4_find_fragment_slot
3545 hidnplayr 455
        cmp     esi, -1
456
        je      .dump
457
 
4052 hidnplayr 458
        mov     esi, [esi + IPv4_FRAGMENT_slot.ptr]                     ; We found the first entry, let's calculate total size of the packet in eax, so we can allocate a buffer
3545 hidnplayr 459
        push    esi
460
        xor     eax, eax
461
        or      edi, -1
462
 
463
  .count_bytes:
4052 hidnplayr 464
        cmp     [esi + IPv4_FRAGMENT_entry.PrevPtr], edi
465
        jne     .destroy_slot_pop                                                       ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!)
466
        mov     cx, [esi + sizeof.IPv4_FRAGMENT_entry + IPv4_header.TotalLength]        ; Add total length
3545 hidnplayr 467
        xchg    cl, ch
3556 hidnplayr 468
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Packet size=%u\n", cx
3545 hidnplayr 469
        add     ax, cx
4052 hidnplayr 470
        movzx   cx, [esi + sizeof.IPv4_FRAGMENT_entry + IPv4_header.VersionAndIHL]      ; Sub Header length
3545 hidnplayr 471
        and     cx, 0x000F
472
        shl     cx, 2
3556 hidnplayr 473
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Header size=%u\n", cx
3545 hidnplayr 474
        sub     ax, cx
475
        mov     edi, esi
4052 hidnplayr 476
        mov     esi, [esi + IPv4_FRAGMENT_entry.NextPtr]
3545 hidnplayr 477
        cmp     esi, -1
478
        jne     .count_bytes
479
 
480
        mov     esi, [esp+4]
4052 hidnplayr 481
        mov     [edi + IPv4_FRAGMENT_entry.NextPtr], esi                                ; Add this packet to the chain, this simplifies the following code
482
        mov     [esi + IPv4_FRAGMENT_entry.NextPtr], -1
483
        mov     [esi + IPv4_FRAGMENT_entry.PrevPtr], edi
484
        mov     [esi + IPv4_FRAGMENT_entry.Owner], ebx
3545 hidnplayr 485
 
4052 hidnplayr 486
        mov     cx, [edx + IPv4_header.TotalLength]                                     ; Note: This time we dont substract Header length
3545 hidnplayr 487
        xchg    cl, ch
3556 hidnplayr 488
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Packet size=%u\n", cx
3545 hidnplayr 489
        add     ax, cx
3556 hidnplayr 490
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Total Received data size=%u\n", eax
3545 hidnplayr 491
 
492
        push    eax
493
        mov     ax, [edx + IPv4_header.FlagsAndFragmentOffset]
494
        xchg    al, ah
495
        shl     ax, 3
496
        add     cx, ax
497
        pop     eax
3556 hidnplayr 498
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Total Fragment size=%u\n", ecx
3545 hidnplayr 499
 
500
        cmp     ax, cx
501
        jne     .destroy_slot_pop
502
 
503
        push    eax
504
        push    eax
505
        call    kernel_alloc
506
        test    eax, eax
507
        je      .destroy_slot_pop                                                       ; If we dont have enough space to allocate the buffer, discard all packets in slot
508
        mov     edx, [esp+4]                                                            ; Get pointer to first fragment entry back in edx
509
 
510
  .rebuild_packet_loop:
4052 hidnplayr 511
        movzx   ecx, [edx + sizeof.IPv4_FRAGMENT_entry + IPv4_header.FlagsAndFragmentOffset] ; Calculate the fragment offset
3545 hidnplayr 512
        xchg    cl, ch                                                                  ;  intel byte order
513
        shl     cx, 3                                                                   ;   multiply by 8 and clear first 3 bits
3556 hidnplayr 514
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Fragment offset=%u\n", cx
3545 hidnplayr 515
 
516
        lea     edi, [eax + ecx]                                                        ; Notice that edi will be equal to eax for first fragment
4258 hidnplayr 517
        movzx   ebx, [edx + sizeof.IPv4_FRAGMENT_entry + IPv4_header.VersionAndIHL]     ; Find header size (in ebx) of fragment
3545 hidnplayr 518
        and     bx, 0x000F                                                              ;
519
        shl     bx, 2                                                                   ;
520
 
4258 hidnplayr 521
        lea     esi, [edx + sizeof.IPv4_FRAGMENT_entry]                                 ; Set esi to the correct begin of fragment
522
        movzx   ecx, [edx + sizeof.IPv4_FRAGMENT_entry + IPv4_header.TotalLength]       ; Calculate total length of fragment
3545 hidnplayr 523
        xchg    cl, ch                                                                  ;  intel byte order
524
 
525
        cmp     edi, eax                                                                ; Is this packet the first fragment ?
526
        je      .first_fragment
527
        sub     cx, bx                                                                  ; If not, dont copy the header
528
        add     esi, ebx                                                                ;
529
  .first_fragment:
530
 
4258 hidnplayr 531
 
532
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Copying %u bytes from 0x%x to 0x%x\n", ecx, esi, edi
3545 hidnplayr 533
        push    cx                                                                      ; First copy dword-wise, then byte-wise
534
        shr     cx, 2                                                                   ;
3711 clevermous 535
        rep movsd                                                                       ;
3545 hidnplayr 536
        pop     cx                                                                      ;
537
        and     cx, 3                                                                   ;
3711 clevermous 538
        rep movsb                                                                       ;
3545 hidnplayr 539
 
540
        push    eax
4259 hidnplayr 541
        push    [edx + IPv4_FRAGMENT_entry.Owner]                                       ; we need to remeber the owner, in case this is the last packet
542
        push    [edx + IPv4_FRAGMENT_entry.NextPtr]                                     ; Set edx to the next pointer
3545 hidnplayr 543
        push    edx                                                                     ; Push pointer to fragment onto stack
4258 hidnplayr 544
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Next Fragment: 0x%x\n", edx
6011 hidnplayr 545
        call    net_buff_free                                                          ; free the previous fragment buffer (this uses the value from stack)
4258 hidnplayr 546
        pop     edx ebx eax
3545 hidnplayr 547
        cmp     edx, -1                                                                 ; Check if it is last fragment in chain
548
        jne     .rebuild_packet_loop
549
 
550
        pop     ecx
551
        xchg    cl, ch
552
        mov     edx, eax
553
        mov     [edx + IPv4_header.TotalLength], cx
4259 hidnplayr 554
        add     esp, 12
3545 hidnplayr 555
        xchg    cl, ch
4259 hidnplayr 556
        push    ecx edx                 ; size and pointer
557
        jmp     .handle_it              ; edx = buf ptr, ecx = size, [esp] buf ptr, [esp+4], total size, ebx=device ptr
3545 hidnplayr 558
 
559
  .destroy_slot_pop:
560
        add     esp, 4
561
  .destroy_slot:
3556 hidnplayr 562
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Destroy fragment slot!\n"
3545 hidnplayr 563
        ; TODO!
564
        jmp     .dump
565
 
566
 
567
 
568
 
569
 
6011 hidnplayr 570
;-----------------------------------------------------------------;
571
;                                                                 ;
572
; ipv4_find_fragment_slot                                         ;
573
;                                                                 ;
574
; IN: pointer to fragmented packet in edx                         ;
575
;                                                                 ;
576
; OUT: pointer to slot in esi, -1 on error                        ;
577
;                                                                 ;
578
;-----------------------------------------------------------------;
3545 hidnplayr 579
align 4
6011 hidnplayr 580
ipv4_find_fragment_slot:
3545 hidnplayr 581
 
582
;;; TODO: the RFC says we should check protocol number too
583
 
584
        push    eax ebx ecx edx
585
        mov     ax, [edx + IPv4_header.Identification]
4052 hidnplayr 586
        mov     ecx, IPv4_MAX_FRAGMENTS
587
        mov     esi, IPv4_FRAGMENT_LIST
3545 hidnplayr 588
        mov     ebx, [edx + IPv4_header.SourceAddress]
589
        mov     edx, [edx + IPv4_header.DestinationAddress]
590
  .find_slot:
4052 hidnplayr 591
        cmp     [esi + IPv4_FRAGMENT_slot.id], ax
3545 hidnplayr 592
        jne     .try_next
4052 hidnplayr 593
        cmp     [esi + IPv4_FRAGMENT_slot.SrcIP], ebx
3545 hidnplayr 594
        jne     .try_next
4052 hidnplayr 595
        cmp     [esi + IPv4_FRAGMENT_slot.DstIP], edx
3545 hidnplayr 596
        je      .found_slot
597
  .try_next:
4052 hidnplayr 598
        add     esi, sizeof.IPv4_FRAGMENT_slot
3545 hidnplayr 599
        loop    .find_slot
600
 
601
        or      esi, -1
602
  .found_slot:
603
        pop     edx ecx ebx eax
604
        ret
605
 
606
 
6011 hidnplayr 607
;------------------------------------------------------------------;
608
;                                                                  ;
609
; ipv4_output                                                      ;
610
;                                                                  ;
611
;  IN:  al = protocol                                              ;
612
;       ah = TTL                                                   ;
613
;       ebx = device ptr (or 0 to let IP layer decide)             ;
614
;       ecx = data length                                          ;
615
;       edx = Source IP                                            ;
616
;       edi = Destination IP                                       ;
617
;                                                                  ;
618
; OUT:  eax = pointer to buffer start                              ;
619
;       eax = 0 on error                                           ;
620
;       ebx = device ptr (send packet through this device)         ;
621
;       ecx = data length                                          ;
622
;       edx = size of complete frame                               ;
623
;       edi = start of IPv4 payload                                ;
624
;                                                                  ;
625
;------------------------------------------------------------------;
3545 hidnplayr 626
align 4
6011 hidnplayr 627
ipv4_output:
3545 hidnplayr 628
 
3601 hidnplayr 629
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_output: size=%u ip=0x%x\n", ecx, eax
3545 hidnplayr 630
 
631
        cmp     ecx, 65500              ; Max IPv4 packet size
632
        ja      .too_large
633
 
5842 hidnplayr 634
        push    ecx ax edi
635
        mov     eax, edi
6011 hidnplayr 636
        call    ipv4_route              ; outputs device number in edi, dest ip in eax, source IP in edx
6122 hidnplayr 637
        test    eax, eax
638
        jz      .no_route
4052 hidnplayr 639
        push    edx
3610 hidnplayr 640
        test    edi, edi
641
        jz      .loopback
642
 
6011 hidnplayr 643
        call    arp_ip_to_mac
3545 hidnplayr 644
        test    eax, 0xffff0000         ; error bits
645
        jnz     .arp_error
646
        push    ebx                     ; push the mac onto the stack
647
        push    ax
648
 
5842 hidnplayr 649
        inc     [IPv4_packets_tx + edi] ; update stats
3545 hidnplayr 650
 
5015 hidnplayr 651
        mov     ax, ETHER_PROTO_IPv4
3638 hidnplayr 652
        mov     ebx, [NET_DRV_LIST + edi]
4052 hidnplayr 653
        mov     ecx, [esp + 6 + 8 + 2]
3545 hidnplayr 654
        add     ecx, sizeof.IPv4_header
5015 hidnplayr 655
        mov     edx, esp
6011 hidnplayr 656
        call    eth_output
3545 hidnplayr 657
        jz      .eth_error
658
        add     esp, 6                  ; pop the mac out of the stack
659
 
660
  .continue:
661
        xchg    cl, ch                                  ; internet byte order
662
        mov     [edi + IPv4_header.VersionAndIHL], 0x45 ; IPv4, normal length (no Optional header)
663
        mov     [edi + IPv4_header.TypeOfService], 0    ; nothing special, just plain ip packet
664
        mov     [edi + IPv4_header.TotalLength], cx
665
        mov     [edi + IPv4_header.Identification], 0   ; fragment id: FIXME
666
        mov     [edi + IPv4_header.FlagsAndFragmentOffset], 0
4052 hidnplayr 667
 
3545 hidnplayr 668
        mov     [edi + IPv4_header.HeaderChecksum], 0
669
        popd    [edi + IPv4_header.SourceAddress]
670
        popd    [edi + IPv4_header.DestinationAddress]
671
 
4052 hidnplayr 672
        pop     word[edi + IPv4_header.TimeToLive]      ; ttl shl 8 + protocol
673
;               [edi + IPv4_header.Protocol]
674
 
3545 hidnplayr 675
        pop     ecx
676
 
6011 hidnplayr 677
        ipv4_checksum edi
3545 hidnplayr 678
        add     edi, sizeof.IPv4_header
3556 hidnplayr 679
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_output: success!\n"
3545 hidnplayr 680
        ret
681
 
682
  .eth_error:
3603 hidnplayr 683
        DEBUGF  DEBUG_NETWORK_ERROR, "IPv4_output: ethernet error\n"
3545 hidnplayr 684
        add     esp, 3*4+2+6
5015 hidnplayr 685
        xor     eax, eax
3545 hidnplayr 686
        ret
687
 
6122 hidnplayr 688
  .no_route:
689
        DEBUGF  DEBUG_NETWORK_ERROR, "IPv4_output: No route to host!\n"
690
        add     esp, 2*4+2
691
        xor     eax, eax
692
        ret
693
 
3545 hidnplayr 694
  .arp_error:
3603 hidnplayr 695
        DEBUGF  DEBUG_NETWORK_ERROR, "IPv4_output: ARP error=%x\n", eax
5842 hidnplayr 696
        add     esp, 4
697
        pop     eax
698
        DEBUGF  DEBUG_NETWORK_ERROR, "IPv4_output: ip=0x%x\n", eax
699
        add     esp, 4+2
5015 hidnplayr 700
        xor     eax, eax
3545 hidnplayr 701
        ret
702
 
703
  .too_large:
3556 hidnplayr 704
        DEBUGF  DEBUG_NETWORK_ERROR, "IPv4_output: Packet too large!\n"
5015 hidnplayr 705
        xor     eax, eax
3545 hidnplayr 706
        ret
707
 
708
  .loopback:
5522 hidnplayr 709
        mov     dword [esp], eax                        ; set source IP to dest IP
3610 hidnplayr 710
        mov     ecx, [esp + 10]
3545 hidnplayr 711
        add     ecx, sizeof.IPv4_header
3600 hidnplayr 712
        mov     edi, AF_INET4
6011 hidnplayr 713
        call    loop_output
3545 hidnplayr 714
        jmp     .continue
715
 
716
 
717
 
718
 
6011 hidnplayr 719
;------------------------------------------------------------------;
720
;                                                                  ;
721
; ipv4_output_raw                                                  ;
722
;                                                                  ;
723
;  IN: eax = socket ptr                                            ;
724
;      ecx = data length                                           ;
725
;      esi = data ptr                                              ;
726
;                                                                  ;
727
; OUT: eax = -1 on error                                           ;
728
;                                                                  ;
729
;------------------------------------------------------------------;
3545 hidnplayr 730
align 4
6011 hidnplayr 731
ipv4_output_raw:
3545 hidnplayr 732
 
733
        DEBUGF 1,"IPv4_output_raw: size=%u ptr=%x socket=%x\n", ecx, esi, eax
734
 
735
        sub     esp, 8
736
        push    esi eax
737
 
6011 hidnplayr 738
        call    ipv4_route
739
        call    arp_ip_to_mac
3545 hidnplayr 740
 
741
        test    eax, 0xffff0000         ; error bits
742
        jnz     .arp_error
743
 
744
        push    ebx                     ; push the mac
745
        push    ax
746
 
4052 hidnplayr 747
        inc     [IPv4_packets_tx + 4*edi]
5015 hidnplayr 748
        mov     ax, ETHER_PROTO_IPv4
3601 hidnplayr 749
        mov     ebx, [NET_DRV_LIST + 4*edi]
3545 hidnplayr 750
        mov     ecx, [esp + 6 + 4]
751
        add     ecx, sizeof.IPv4_header
5015 hidnplayr 752
        mov     edx, esp
6011 hidnplayr 753
        call    eth_output
3545 hidnplayr 754
        jz      .error
755
        add     esp, 6  ; pop the mac
756
 
757
        mov     dword[esp+4+4], edx
758
        mov     dword[esp+4+4+4], eax
759
 
760
        pop     eax esi
5842 hidnplayr 761
;; TODO: check socket options if we should add header, or just compute checksum
3545 hidnplayr 762
 
763
        push    edi ecx
3711 clevermous 764
        rep movsb
3545 hidnplayr 765
        pop     ecx edi
766
 
767
;        [edi + IPv4_header.VersionAndIHL]              ; IPv4, normal length (no Optional header)
768
;        [edi + IPv4_header.TypeOfService]              ; nothing special, just plain ip packet
769
;        [edi + IPv4_header.TotalLength]
770
;        [edi + IPv4_header.TotalLength]                ; internet byte order
771
;        [edi + IPv4_header.FlagsAndFragmentOffset]
772
 
773
        mov     [edi + IPv4_header.HeaderChecksum], 0
774
 
775
;        [edi + IPv4_header.TimeToLive]                 ; ttl shl 8 + protocol
776
;        [edi + IPv4_header.Protocol]
777
;        [edi + IPv4_header.Identification]             ; fragment id
778
;        [edi + IPv4_header.SourceAddress]
779
;        [edi + IPv4_header.DestinationAddress]
780
 
6011 hidnplayr 781
        ipv4_checksum edi                       ;;;; todo: checksum for IP packet with options!
3545 hidnplayr 782
        add     edi, sizeof.IPv4_header
3556 hidnplayr 783
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_output_raw: device=%x\n", ebx
3545 hidnplayr 784
        call    [ebx + NET_DEVICE.transmit]
785
        ret
786
 
787
  .error:
5842 hidnplayr 788
        add     esp, 6+8+4+4
789
        mov     ebx, ENOBUFS            ; FIXME: NOBUFS or MSGSIZE error
790
        or      eax, -1
791
        ret
792
 
3545 hidnplayr 793
  .arp_error:
794
        add     esp, 8+4+4
5842 hidnplayr 795
        mov     ebx, ENOTCONN
5015 hidnplayr 796
        or      eax, -1
3545 hidnplayr 797
        ret
798
 
799
 
6011 hidnplayr 800
;-----------------------------------------------------------------;
801
;                                                                 ;
802
; ipv4_fragment                                                   ;
803
;                                                                 ;
804
;  IN:  [esp] = ptr to packet buffer to fragment                  ;
805
;       edi = ptrr to ip header in that buffer                    ;
806
;       ebx = device ptr                                          ;
807
;                                                                 ;
808
;  OUT: /                                                         ;
809
;                                                                 ;
810
;-----------------------------------------------------------------;
811
proc ipv4_fragment stdcall buffer
3545 hidnplayr 812
 
5842 hidnplayr 813
locals
814
        offset          dd ?
815
        headerlength    dd ?
816
        headerptr       dd ?
817
        dataptr         dd ?
818
        remaining       dd ?
819
        segmentsize     dd ?
820
endl
3545 hidnplayr 821
 
3556 hidnplayr 822
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_fragment\n"
3545 hidnplayr 823
 
5842 hidnplayr 824
; We must be able to put at least 8 bytes per segment
825
        movzx   eax, byte[edi]          ; IHL
826
        and     eax, 0xf
827
        shl     eax, 2
828
        mov     [headerlength], eax
829
        add     eax, 8
830
        mov     ecx, [ebx + NET_DEVICE.mtu]
831
        and     ecx, not 11b
832
        cmp     ecx, eax
833
        jb      .fail
3545 hidnplayr 834
 
5842 hidnplayr 835
        mov     [edi + IPv4_header.HeaderChecksum], 0
3545 hidnplayr 836
 
5842 hidnplayr 837
        mov     [segmentsize], ecx
838
        mov     [headerptr], edi
839
        movzx   ecx, [edi + IPv4_header.TotalLength]
840
        xchg    cl, ch
841
        sub     ecx, [headerlength]
842
        mov     [remaining], ecx
843
        mov     [offset], 0
3545 hidnplayr 844
 
5842 hidnplayr 845
        add     edi, [headerlength]
846
        mov     [dataptr], edi
3545 hidnplayr 847
 
5842 hidnplayr 848
  .loop:
849
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Ipv4_fragment: new fragment"
3545 hidnplayr 850
 
5842 hidnplayr 851
        mov     ecx, [segmentsize]
852
        cmp     ecx, [remaining]
853
        jbe     @f
854
        mov     ecx, [remaining]
855
  @@:
3545 hidnplayr 856
 
5015 hidnplayr 857
        mov     ax, ETHER_PROTO_IPv4
5842 hidnplayr 858
        mov     edx, [esp]
859
        add     edx, [edx + NET_BUFF.offset]
860
;        add     edx, ETH_header.DstMAC         ; = 0
3545 hidnplayr 861
        call    ETH_output
5842 hidnplayr 862
        jz      .fail
3545 hidnplayr 863
 
5842 hidnplayr 864
        push    edi
865
        mov     edx, ecx
866
 
3545 hidnplayr 867
; copy header
5842 hidnplayr 868
        mov     esi, [headerptr]
869
        mov     ecx, [headerlength]
870
        shr     ecx, 2
3711 clevermous 871
        rep movsd
3545 hidnplayr 872
 
873
; copy data
5842 hidnplayr 874
        mov     esi, [dataptr]
875
        add     esi, [offset]
876
        mov     ecx, edx
877
        sub     ecx, [headerlength]
878
        shr     ecx, 2
879
        rep movsd
880
        pop     edi
3545 hidnplayr 881
 
882
; now, correct header
5842 hidnplayr 883
; packet length
884
        mov     ax, dx
885
        xchg    al, ah
886
        mov     [edi + IPv4_header.TotalLength], ax
3545 hidnplayr 887
 
5842 hidnplayr 888
; offset
889
        mov     eax, [offset]
890
        xchg    al, ah
3545 hidnplayr 891
 
5842 hidnplayr 892
        sub     edx, [headerlength]
893
        sub     [remaining], edx
894
        je      @f
895
        jb      .fail
896
        or      ah, 1 shl 2             ; more fragments
897
        add     [offset], edx
898
  @@:
899
        mov     [edi + IPv4_header.FlagsAndFragmentOffset], ax
3545 hidnplayr 900
 
5842 hidnplayr 901
; Send the fragment
3545 hidnplayr 902
        IPv4_checksum edi
903
        call    [ebx + NET_DEVICE.transmit]
904
 
5842 hidnplayr 905
        cmp     [remaining], 0
906
        jne     .loop
3545 hidnplayr 907
 
5842 hidnplayr 908
        call    NET_BUFF_free
909
        ret
3545 hidnplayr 910
 
5842 hidnplayr 911
      .fail:
3556 hidnplayr 912
        DEBUGF  DEBUG_NETWORK_ERROR, "Ipv4_fragment: failed\n"
5522 hidnplayr 913
        call    NET_BUFF_free
3545 hidnplayr 914
        ret
915
 
5842 hidnplayr 916
endp
3545 hidnplayr 917
 
918
 
5842 hidnplayr 919
 
6011 hidnplayr 920
;-----------------------------------------------------------------;
921
;                                                                 ;
922
; ipv4_route                                                      ;
923
;                                                                 ;
924
; IN:   eax = Destination IP                                      ;
925
;       ebx = outgoing device / 0                                 ;
926
;       edx = Source IP                                           ;
927
;                                                                 ;
6122 hidnplayr 928
; OUT:  eax = Destination IP (may be gateway), 0 on error         ;
6011 hidnplayr 929
;       edx = Source IP                                           ;
930
;       edi = device number*4                                     ;
931
;                                                                 ;
932
; DESTROYED:                                                      ;
933
;       ecx                                                       ;
934
;                                                                 ;
935
;-----------------------------------------------------------------;
3545 hidnplayr 936
align 4
6122 hidnplayr 937
ipv4_route:
3545 hidnplayr 938
 
5584 hidnplayr 939
        test    ebx, ebx
940
        jnz     .got_device
941
 
3545 hidnplayr 942
        cmp     eax, 0xffffffff
943
        je      .broadcast
944
 
945
        xor     edi, edi
946
  .loop:
4052 hidnplayr 947
        mov     ebx, [IP_LIST + edi]
948
        and     ebx, [SUBNET_LIST + edi]
3545 hidnplayr 949
        jz      .next
4052 hidnplayr 950
        mov     ecx, eax
951
        and     ecx, [SUBNET_LIST + edi]
952
        cmp     ebx, ecx
953
        je      .got_it
3545 hidnplayr 954
  .next:
955
        add     edi, 4
4052 hidnplayr 956
        cmp     edi, 4*NET_DEVICES_MAX
957
        jb      .loop
3545 hidnplayr 958
 
4052 hidnplayr 959
        mov     eax, [GATEWAY_LIST + 4]         ; TODO: let user (or a user space daemon) configure default route
3545 hidnplayr 960
  .broadcast:
4052 hidnplayr 961
        mov     edi, 4                          ; TODO: same as above
962
  .got_it:
963
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_route: %u\n", edi
964
        test    edx, edx
965
        jnz     @f
966
        mov     edx, [IP_LIST + edi]
967
  @@:
968
 
3545 hidnplayr 969
        ret
970
 
5584 hidnplayr 971
  .got_device:
972
; Validate device ptr and convert to device number
6011 hidnplayr 973
        call    net_ptr_to_num4
5584 hidnplayr 974
        cmp     edi, -1
975
        je      .fail
3545 hidnplayr 976
 
5584 hidnplayr 977
        mov     edx, [IP_LIST + edi]            ; Source IP
3545 hidnplayr 978
 
5584 hidnplayr 979
; Check if we should route to gateway or not
980
        mov     ebx, [IP_LIST + edi]
981
        and     ebx, [SUBNET_LIST + edi]
982
        mov     ecx, eax
983
        and     ecx, [SUBNET_LIST + edi]
984
        je      @f
985
        mov     eax, [GATEWAY_LIST + edi]
986
  @@:
987
        ret
988
 
989
  .fail:
6122 hidnplayr 990
        xor     eax, eax
5584 hidnplayr 991
        ret
992
 
993
 
994
 
6011 hidnplayr 995
;-----------------------------------------------------------------;
996
;                                                                 ;
997
; ipv4_get_frgmnt_num                                             ;
998
;                                                                 ;
999
;  IN: /                                                          ;
1000
;                                                                 ;
1001
; OUT: ax = fragment number                                       ;
1002
;                                                                 ;
1003
;-----------------------------------------------------------------;
3545 hidnplayr 1004
align 4
6011 hidnplayr 1005
ipv4_get_frgmnt_num:
3545 hidnplayr 1006
        xor     ax, ax  ;;; TODO: replace this with real code
1007
 
1008
        ret
1009
 
1010
 
6011 hidnplayr 1011
;-----------------------------------------------------------------;
1012
;                                                                 ;
1013
; ipv4_connect                                                    ;
1014
;                                                                 ;
1015
;   IN: eax = socket pointer                                      ;
1016
;                                                                 ;
1017
;  OUT: eax = 0 on success                                        ;
1018
;       eax = -1 on error                                         ;
1019
;       ebx = error code on error                                 ;
1020
;                                                                 ;
1021
;-----------------------------------------------------------------;
4030 hidnplayr 1022
align 4
6011 hidnplayr 1023
ipv4_connect:
4030 hidnplayr 1024
 
4035 hidnplayr 1025
        push    eax edx
4030 hidnplayr 1026
        lea     ecx, [eax + SOCKET.mutex]
1027
        call    mutex_lock
4035 hidnplayr 1028
        pop     edx eax
4030 hidnplayr 1029
 
1030
; Fill in local IP
1031
        cmp     [eax + IP_SOCKET.LocalIP], 0
1032
        jne     @f
1033
        push    [IP_LIST + 4]                                   ; FIXME: use correct local IP
1034
        pop     [eax + IP_SOCKET.LocalIP]
1035
 
1036
; Fill in remote IP
1037
        pushd   [edx + 4]
1038
        pop     [eax + IP_SOCKET.RemoteIP]
1039
 
1040
        lea     ecx, [eax + SOCKET.mutex]
1041
        call    mutex_unlock
1042
 
1043
        xor     eax, eax
1044
        ret
1045
 
1046
 
6011 hidnplayr 1047
;-----------------------------------------------------------------;
1048
;                                                                 ;
1049
; ipv4_API: Part of system function 76.                           ;
1050
;                                                                 ;
1051
;  IN:  bl = subfunction number                                   ;
1052
;       bh = device number                                        ;
1053
;       ecx, edx, .. depends on subfunction                       ;
1054
;                                                                 ;
1055
; OUT:  depends on subfunction                                    ;
1056
;                                                                 ;
1057
;-----------------------------------------------------------------;
3545 hidnplayr 1058
align 4
6011 hidnplayr 1059
ipv4_api:
3545 hidnplayr 1060
 
1061
        movzx   eax, bh
1062
        shl     eax, 2
1063
 
1064
        and     ebx, 0x000000ff
1065
        cmp     ebx, .number
1066
        ja      .error
1067
        jmp     dword [.table + 4*ebx]
1068
 
1069
  .table:
1070
        dd      .packets_tx     ; 0
1071
        dd      .packets_rx     ; 1
1072
        dd      .read_ip        ; 2
1073
        dd      .write_ip       ; 3
1074
        dd      .read_dns       ; 4
1075
        dd      .write_dns      ; 5
1076
        dd      .read_subnet    ; 6
1077
        dd      .write_subnet   ; 7
1078
        dd      .read_gateway   ; 8
1079
        dd      .write_gateway  ; 9
1080
  .number = ($ - .table) / 4 - 1
1081
 
1082
  .error:
1083
        mov     eax, -1
1084
        ret
1085
 
1086
  .packets_tx:
4052 hidnplayr 1087
        mov     eax, [IPv4_packets_tx + eax]
3545 hidnplayr 1088
        ret
1089
 
1090
  .packets_rx:
4052 hidnplayr 1091
        mov     eax, [IPv4_packets_rx + eax]
3545 hidnplayr 1092
        ret
1093
 
1094
  .read_ip:
1095
        mov     eax, [IP_LIST + eax]
1096
        ret
1097
 
1098
  .write_ip:
1099
        mov     [IP_LIST + eax], ecx
1100
        mov     edi, eax                        ; device number, we'll need it for ARP
1101
 
1102
        ; pre-calculate the local broadcast address
1103
        mov     ebx, [SUBNET_LIST + eax]
1104
        not     ebx
1105
        or      ebx, ecx
1106
        mov     [BROADCAST_LIST + eax], ebx
1107
 
3601 hidnplayr 1108
        mov     ebx, [NET_DRV_LIST + eax]
1109
        mov     eax, [IP_LIST + eax]
6011 hidnplayr 1110
        call    arp_output_request              ; now send a gratuitous ARP
3545 hidnplayr 1111
 
6011 hidnplayr 1112
        call    net_send_event
3545 hidnplayr 1113
        xor     eax, eax
1114
        ret
1115
 
1116
  .read_dns:
1117
        mov     eax, [DNS_LIST + eax]
1118
        ret
1119
 
1120
  .write_dns:
1121
        mov     [DNS_LIST + eax], ecx
6011 hidnplayr 1122
        call    net_send_event
3545 hidnplayr 1123
        xor     eax, eax
1124
        ret
1125
 
1126
  .read_subnet:
1127
        mov     eax, [SUBNET_LIST + eax]
1128
        ret
1129
 
1130
  .write_subnet:
1131
        mov     [SUBNET_LIST + eax], ecx
1132
 
1133
        ; pre-calculate the local broadcast address
1134
        mov     ebx, [IP_LIST + eax]
1135
        not     ecx
1136
        or      ecx, ebx
1137
        mov     [BROADCAST_LIST + eax], ecx
1138
 
6011 hidnplayr 1139
        call    net_send_event
3545 hidnplayr 1140
        xor     eax, eax
1141
        ret
1142
 
1143
  .read_gateway:
1144
        mov     eax, [GATEWAY_LIST + eax]
1145
        ret
1146
 
1147
  .write_gateway:
1148
        mov     [GATEWAY_LIST + eax], ecx
1149
 
6011 hidnplayr 1150
        call    net_send_event
3545 hidnplayr 1151
        xor     eax, eax
1152
        ret