Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
5363 yogev_ezra 3
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved.    ;;
3545 hidnplayr 4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  STACK.INC                                                      ;;
7
;;                                                                 ;;
8
;;  TCP/IP stack for KolibriOS                                     ;;
9
;;                                                                 ;;
10
;;    Written by hidnplayr@kolibrios.org                           ;;
11
;;                                                                 ;;
12
;;     Some parts of code are based on the work of:                ;;
13
;;      Mike Hibbett (menuetos network stack)                      ;;
14
;;      Eugen Brasoveanu (solar os network stack and drivers)      ;;
15
;;      mike.dld (kolibrios socket code)                           ;;
16
;;                                                                 ;;
17
;;     TCP part is based on 4.4BSD                                 ;;
18
;;                                                                 ;;
19
;;          GNU GENERAL PUBLIC LICENSE                             ;;
20
;;             Version 2, June 1991                                ;;
21
;;                                                                 ;;
22
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
23
 
4850 mario79 24
$Revision: 5842 $
3545 hidnplayr 25
 
26
uglobal
27
        net_10ms        dd ?
28
        net_tmr_count   dw ?
29
endg
30
 
3556 hidnplayr 31
DEBUG_NETWORK_ERROR     = 1
4388 hidnplayr 32
DEBUG_NETWORK_VERBOSE   = 0
3556 hidnplayr 33
 
3600 hidnplayr 34
NET_DEVICES_MAX         = 16
5528 hidnplayr 35
NET_BUFFERS             = 512
36
NET_BUFFER_SIZE         = 2048
3545 hidnplayr 37
ARP_BLOCK               = 1             ; true or false
38
 
3600 hidnplayr 39
EPHEMERAL_PORT_MIN      = 49152
40
EPHEMERAL_PORT_MAX      = 61000
3545 hidnplayr 41
MIN_EPHEMERAL_PORT_N    = 0x00C0        ; same in Network byte order (FIXME)
42
MAX_EPHEMERAL_PORT_N    = 0x48EE        ; same in Network byte order (FIXME)
43
 
44
; Ethernet protocol numbers
3600 hidnplayr 45
ETHER_PROTO_ARP                 = 0x0608
46
ETHER_PROTO_IPv4                = 0x0008
47
ETHER_PROTO_IPv6                = 0xDD86
48
ETHER_PROTO_PPP_DISCOVERY       = 0x6388
49
ETHER_PROTO_PPP_SESSION         = 0x6488
3545 hidnplayr 50
 
3600 hidnplayr 51
; Internet protocol numbers
52
IP_PROTO_IP             = 0
53
IP_PROTO_ICMP           = 1
54
IP_PROTO_TCP            = 6
55
IP_PROTO_UDP            = 17
5842 hidnplayr 56
IP_PROTO_RAW            = 255
3600 hidnplayr 57
 
5842 hidnplayr 58
; IP options
59
IP_TOS                  = 1
60
IP_TTL                  = 2
61
IP_HDRINCL              = 3
62
 
3545 hidnplayr 63
; PPP protocol numbers
3600 hidnplayr 64
PPP_PROTO_IPv4          = 0x2100
65
PPP_PROTO_IPV6          = 0x5780
66
PPP_PROTO_ETHERNET      = 666           ; FIXME
3545 hidnplayr 67
 
68
;Protocol family
69
AF_UNSPEC               = 0
70
AF_LOCAL                = 1
71
AF_INET4                = 2
72
AF_INET6                = 10
3600 hidnplayr 73
AF_PPP                  = 777           ; FIXME
3545 hidnplayr 74
 
75
; Socket types
76
SOCK_STREAM             = 1
77
SOCK_DGRAM              = 2
78
SOCK_RAW                = 3
79
 
5842 hidnplayr 80
; Socket level
81
SOL_SOCKET              = 0xffff
82
 
3545 hidnplayr 83
; Socket options
84
SO_ACCEPTCON            = 1 shl 0
85
SO_BROADCAST            = 1 shl 1
86
SO_DEBUG                = 1 shl 2
87
SO_DONTROUTE            = 1 shl 3
88
SO_KEEPALIVE            = 1 shl 4
89
SO_OOBINLINE            = 1 shl 5
90
SO_REUSEADDR            = 1 shl 6
91
SO_REUSEPORT            = 1 shl 7
92
SO_USELOOPBACK          = 1 shl 8
93
SO_BINDTODEVICE         = 1 shl 9
94
 
95
SO_NONBLOCK             = 1 shl 31
96
 
97
; Socket flags for user calls
98
MSG_PEEK                = 0x02
99
MSG_DONTWAIT            = 0x40
100
 
101
; Socket States
3600 hidnplayr 102
SS_NOFDREF              = 0x0001        ; no file table ref any more
103
SS_ISCONNECTED          = 0x0002        ; socket connected to a peer
104
SS_ISCONNECTING         = 0x0004        ; in process of connecting to peer
105
SS_ISDISCONNECTING      = 0x0008        ; in process of disconnecting
106
SS_CANTSENDMORE         = 0x0010        ; can't send more data to peer
107
SS_CANTRCVMORE          = 0x0020        ; can't receive more data from peer
108
SS_RCVATMARK            = 0x0040        ; at mark on input
109
SS_ISABORTING           = 0x0080        ; aborting fd references - close()
110
SS_RESTARTSYS           = 0x0100        ; restart blocked system calls
111
SS_ISDISCONNECTED       = 0x0800        ; socket disconnected from peer
3545 hidnplayr 112
 
3674 hidnplayr 113
SS_ASYNC                = 0x1000        ; async i/o notify
114
SS_ISCONFIRMING         = 0x2000        ; deciding to accept connection req
115
SS_MORETOCOME           = 0x4000
3545 hidnplayr 116
 
117
SS_BLOCKED              = 0x8000
118
 
119
 
4959 hidnplayr 120
SOCKET_MAXDATA          = 4096*64       ; must be 4096*(power of 2) where 'power of 2' is at least 8
3600 hidnplayr 121
MAX_backlog             = 20            ; maximum backlog for stream sockets
3545 hidnplayr 122
 
123
; Error Codes
3674 hidnplayr 124
ENOBUFS                 = 1
4025 hidnplayr 125
EINPROGRESS             = 2
3674 hidnplayr 126
EOPNOTSUPP              = 4
127
EWOULDBLOCK             = 6
128
ENOTCONN                = 9
129
EALREADY                = 10
130
EINVAL                  = 11
131
EMSGSIZE                = 12
132
ENOMEM                  = 18
133
EADDRINUSE              = 20
3545 hidnplayr 134
ECONNREFUSED            = 61
135
ECONNRESET              = 52
4025 hidnplayr 136
EISCONN                 = 56
3545 hidnplayr 137
ETIMEDOUT               = 60
138
ECONNABORTED            = 53
139
 
140
; Api protocol numbers
141
API_ETH                 = 0
142
API_IPv4                = 1
143
API_ICMP                = 2
144
API_UDP                 = 3
145
API_TCP                 = 4
146
API_ARP                 = 5
147
API_PPPOE               = 6
148
API_IPv6                = 7
149
 
3600 hidnplayr 150
; Network device types
151
NET_DEVICE_LOOPBACK     = 0
152
NET_DEVICE_ETH          = 1
153
NET_DEVICE_SLIP         = 2
154
 
155
; Network link types (link protocols)
5528 hidnplayr 156
NET_LINK_LOOPBACK       = 0
3600 hidnplayr 157
NET_LINK_MAC            = 1     ; Media access control (ethernet, isdn, ...)
158
NET_LINK_PPP            = 2     ; Point to Point Protocol (PPPoE, ...)
159
NET_LINK_IEEE802.11     = 3     ; IEEE 802.11 (WiFi)
160
 
161
; Hardware acceleration bits
4387 hidnplayr 162
NET_HWACC_TCP_IPv4_IN   = 1 shl 0
163
NET_HWACC_TCP_IPv4_OUT  = 1 shl 1
3545 hidnplayr 164
 
5522 hidnplayr 165
; Network frame types
166
NET_BUFF_LOOPBACK      = 0
167
NET_BUFF_ETH           = 1
168
 
3545 hidnplayr 169
struct  NET_DEVICE
170
 
3600 hidnplayr 171
        device_type     dd ?    ; Type field
3545 hidnplayr 172
        mtu             dd ?    ; Maximal Transmission Unit
173
        name            dd ?    ; Ptr to 0 terminated string
174
 
175
        unload          dd ?    ; Ptrs to driver functions
176
        reset           dd ?    ;
177
        transmit        dd ?    ;
178
 
179
        bytes_tx        dq ?    ; Statistics, updated by the driver
180
        bytes_rx        dq ?    ;
181
        packets_tx      dd ?    ;
182
        packets_rx      dd ?    ;
183
 
3600 hidnplayr 184
        link_state      dd ?    ; link state (0 = no link)
3545 hidnplayr 185
        hwacc           dd ?    ; bitmask stating enabled HW accelerations (offload engines)
186
 
187
ends
188
 
5522 hidnplayr 189
struct  NET_BUFF
3545 hidnplayr 190
 
5522 hidnplayr 191
        NextPtr         dd ?    ; pointer to next frame in list
192
        PrevPtr         dd ?    ; pointer to previous frame in list
193
        device          dd ?    ; ptr to NET_DEVICE structure
194
        type            dd ?    ; encapsulation type: e.g. Ethernet
195
        length          dd ?    ; size of encapsulated data
196
        offset          dd ?    ; offset to actual data (24 bytes for default frame)
197
        data            rb 0
198
 
199
ends
200
 
201
 
3545 hidnplayr 202
; Exactly as it says..
203
macro pseudo_random reg {
204
        add     reg, [esp]
205
        rol     reg, 5
206
        xor     reg, [timer_ticks]
207
;        add     reg, [CPU_FREQ]
208
        imul    reg, 214013
209
        xor     reg, 0xdeadbeef
210
        rol     reg, 9
211
}
212
 
213
; Network to Hardware byte order (dword)
214
macro ntohd reg {
215
 
216
        rol     word reg, 8
217
        rol     dword reg, 16
218
        rol     word reg , 8
219
 
220
}
221
 
222
; Network to Hardware byte order (word)
223
macro ntohw reg {
224
 
225
        rol     word reg, 8
226
 
227
}
228
 
229
 
230
include "queue.inc"
231
 
232
include "loopback.inc"
233
include "ethernet.inc"
234
 
235
include "PPPoE.inc"
236
 
237
include "ARP.inc"
238
include "IPv4.inc"
239
include "IPv6.inc"
240
 
241
include "icmp.inc"
242
include "udp.inc"
243
include "tcp.inc"
244
 
245
include "socket.inc"
246
 
247
 
248
 
3698 hidnplayr 249
uglobal
3545 hidnplayr 250
align 4
251
 
5528 hidnplayr 252
        NET_RUNNING     dd ?
253
        NET_DRV_LIST    rd NET_DEVICES_MAX
3545 hidnplayr 254
 
5528 hidnplayr 255
        NET_BUFFS_FREE  rd NET_BUFFERS
256
        .current        dd ?
257
 
3545 hidnplayr 258
endg
259
 
260
 
261
;-----------------------------------------------------------------
262
;
263
; stack_init
264
;
265
;  This function calls all network init procedures
266
;
267
;  IN:  /
268
;  OUT: /
269
;
270
;-----------------------------------------------------------------
271
align 4
272
stack_init:
273
 
5528 hidnplayr 274
; allocate network buffers
275
        stdcall kernel_alloc, NET_BUFFER_SIZE*NET_BUFFERS
276
        test    eax, eax
277
        jz      .fail
278
 
279
        mov     edi, NET_BUFFS_FREE
280
        mov     ecx, NET_BUFFERS
281
        cld
282
  .loop:
283
        stosd
284
        add     eax, NET_BUFFER_SIZE
285
        dec     ecx
286
        jnz     .loop
287
 
288
        mov     eax, NET_BUFFS_FREE
289
        stosd
290
 
3545 hidnplayr 291
; Init the network drivers list
292
        xor     eax, eax
293
        mov     edi, NET_RUNNING
5524 hidnplayr 294
        mov     ecx, (NET_DEVICES_MAX + 1)
3711 clevermous 295
        rep stosd
3545 hidnplayr 296
 
3982 hidnplayr 297
        ETH_init
298
 
3545 hidnplayr 299
        PPPoE_init
300
 
301
        IPv4_init
302
;        IPv6_init
303
        ICMP_init
304
 
305
        ARP_init
306
        UDP_init
307
        TCP_init
308
 
309
        SOCKET_init
310
 
3601 hidnplayr 311
        LOOP_init
312
 
3545 hidnplayr 313
        mov     [net_tmr_count], 0
5528 hidnplayr 314
        ret
3545 hidnplayr 315
 
5528 hidnplayr 316
  .fail:
317
        DEBUGF  DEBUG_NETWORK_ERROR, "Stack init failed!\n"
3545 hidnplayr 318
        ret
319
 
320
 
321
 
322
; Wakeup every tick.
323
proc stack_handler_has_work?
324
 
3711 clevermous 325
        mov     eax, [timer_ticks]
326
        cmp     eax, [net_10ms]
3545 hidnplayr 327
 
328
        ret
329
endp
330
 
331
 
332
;-----------------------------------------------------------------
333
;
334
; stack_handler
335
;
336
;  This function is called in kernel loop
337
;
338
;  IN:  /
339
;  OUT: /
340
;
341
;-----------------------------------------------------------------
342
align 4
343
stack_handler:
344
 
345
        ; Test for 10ms tick
346
        mov     eax, [timer_ticks]
347
        cmp     eax, [net_10ms]
348
        je      .exit
349
        mov     [net_10ms], eax
350
 
351
        cmp     [NET_RUNNING], 0
352
        je      .exit
353
 
354
        test    [net_10ms], 0x0f        ; 160ms
355
        jnz     .exit
356
 
357
        TCP_timer_160ms
358
 
359
        test    [net_10ms], 0x3f        ; 640ms
360
        jnz     .exit
361
 
362
        ARP_decrease_entry_ttls
363
        IPv4_decrease_fragment_ttls
364
 
5013 hidnplayr 365
        xor     edx, edx
366
        mov     eax, [TCP_timer1_event]
367
        mov     ebx, [eax + EVENT.id]
368
        xor     esi, esi
369
        call    raise_event
370
 
3545 hidnplayr 371
  .exit:
372
        ret
373
 
374
 
3861 hidnplayr 375
align 4
5528 hidnplayr 376
proc NET_BUFF_alloc stdcall, buffersize
377
        cmp     [buffersize], NET_BUFFER_SIZE
378
        ja      .too_large
5522 hidnplayr 379
 
5528 hidnplayr 380
        spin_lock_irqsave
5522 hidnplayr 381
 
5528 hidnplayr 382
        mov     eax, [NET_BUFFS_FREE.current]
383
        cmp     eax, NET_BUFFS_FREE+NET_BUFFERS*4
384
        jae     .out_of_mem
385
        mov     eax, [eax]
386
        add     [NET_BUFFS_FREE.current], 4
387
 
388
        spin_unlock_irqrestore
389
 
5536 hidnplayr 390
        DEBUGF  DEBUG_NETWORK_VERBOSE, "net alloc: 0x%x\n", eax
5528 hidnplayr 391
        ret
392
 
393
  .out_of_mem:
394
        spin_unlock_irqrestore
395
 
396
        xor     eax, eax
397
        DEBUGF  DEBUG_NETWORK_ERROR, "NET_BUFF_alloc: out of mem!\n"
398
        ret
399
 
400
  .too_large:
401
        xor     eax, eax
402
        DEBUGF  DEBUG_NETWORK_ERROR, "NET_BUFF_alloc: too large!\n"
403
        ret
404
endp
405
 
406
 
5522 hidnplayr 407
align 4
5528 hidnplayr 408
proc NET_BUFF_free stdcall, buffer
3545 hidnplayr 409
 
5536 hidnplayr 410
        DEBUGF  DEBUG_NETWORK_VERBOSE, "net free: 0x%x\n", [buffer]
3861 hidnplayr 411
 
5528 hidnplayr 412
        spin_lock_irqsave
413
 
414
        sub     [NET_BUFFS_FREE.current], 4
415
        mov     eax, [NET_BUFFS_FREE.current]
416
        push    [buffer]
417
        pop     dword[eax]
418
 
419
        spin_unlock_irqrestore
420
 
421
        ret
422
endp
423
 
424
 
3545 hidnplayr 425
align 4
426
NET_link_changed:
427
 
3601 hidnplayr 428
        DEBUGF  DEBUG_NETWORK_VERBOSE, "NET_link_changed device=0x%x status=0x%x\n", ebx, [ebx + NET_DEVICE.link_state]
3545 hidnplayr 429
 
430
align 4
431
NET_send_event:
432
 
3556 hidnplayr 433
        DEBUGF  DEBUG_NETWORK_VERBOSE, "NET_send_event\n"
3545 hidnplayr 434
 
435
; Send event to all applications
436
        push    edi ecx
437
        mov     edi, SLOT_BASE
438
        mov     ecx, [TASK_COUNT]
439
  .loop:
440
        add     edi, 256
441
        or      [edi + APPDATA.event_mask], EVENT_NETWORK2
442
        loop    .loop
443
        pop     ecx edi
444
 
445
        ret
446
 
447
 
448
 
449
;-----------------------------------------------------------------
450
;
451
; NET_add_device:
452
;
453
;  This function is called by the network drivers,
454
;  to register each running NIC to the kernel
455
;
456
;  IN:  Pointer to device structure in ebx
457
;  OUT: Device num in eax, -1 on error
458
;
459
;-----------------------------------------------------------------
460
align 4
461
NET_add_device:
462
 
3556 hidnplayr 463
        DEBUGF  DEBUG_NETWORK_VERBOSE, "NET_Add_Device: %x\n", ebx   ;;; TODO: use mutex to lock net device list
3545 hidnplayr 464
 
3600 hidnplayr 465
        cmp     [NET_RUNNING], NET_DEVICES_MAX
3545 hidnplayr 466
        jae     .error
467
 
468
;----------------------------------
469
; Check if device is already listed
470
        mov     eax, ebx
3600 hidnplayr 471
        mov     ecx, NET_DEVICES_MAX    ; We need to check whole list because a device may be removed without re-organizing list
3545 hidnplayr 472
        mov     edi, NET_DRV_LIST
473
 
3711 clevermous 474
        repne scasd                     ; See if device is already in the list
3545 hidnplayr 475
        jz      .error
476
 
477
;----------------------------
478
; Find empty slot in the list
479
        xor     eax, eax
3600 hidnplayr 480
        mov     ecx, NET_DEVICES_MAX
3545 hidnplayr 481
        mov     edi, NET_DRV_LIST
482
 
3711 clevermous 483
        repne scasd
3545 hidnplayr 484
        jnz     .error
485
 
486
        sub     edi, 4
487
 
488
;-----------------------------
489
; Add device to the found slot
490
        mov     [edi], ebx              ; add device to list
491
 
492
        mov     eax, edi                ; Calculate device number in eax
493
        sub     eax, NET_DRV_LIST
494
        shr     eax, 2
495
 
496
        inc     [NET_RUNNING]           ; Indicate that one more network device is up and running
497
 
498
        call    NET_send_event
499
 
3556 hidnplayr 500
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Device number: %u\n", eax
3545 hidnplayr 501
        ret
502
 
503
  .error:
504
        or      eax, -1
3556 hidnplayr 505
        DEBUGF  DEBUG_NETWORK_ERROR, "Adding network device failed\n"
3545 hidnplayr 506
        ret
507
 
508
 
509
 
510
;-----------------------------------------------------------------
511
;
512
; NET_Remove_Device:
513
;
3601 hidnplayr 514
;  This function is called by network drivers,
3545 hidnplayr 515
;  to unregister network devices from the kernel
516
;
517
;  IN:  Pointer to device structure in ebx
518
;  OUT: eax: -1 on error
519
;
520
;-----------------------------------------------------------------
521
align 4
522
NET_remove_device:
523
 
524
        cmp     [NET_RUNNING], 0
525
        je      .error
526
 
527
;----------------------------
528
; Find the driver in the list
529
 
530
        mov     eax, ebx
3600 hidnplayr 531
        mov     ecx, NET_DEVICES_MAX
3601 hidnplayr 532
        mov     edi, NET_DRV_LIST
3545 hidnplayr 533
 
3711 clevermous 534
        repne scasd
3545 hidnplayr 535
        jnz     .error
536
 
537
;------------------------
538
; Remove it from the list
539
 
540
        xor     eax, eax
541
        mov     dword [edi-4], eax
3601 hidnplayr 542
        dec     [NET_RUNNING]
3545 hidnplayr 543
 
544
        call    NET_send_event
545
 
3601 hidnplayr 546
        xor     eax, eax
3545 hidnplayr 547
        ret
548
 
549
  .error:
550
        or      eax, -1
551
        ret
552
 
553
 
554
 
555
;-----------------------------------------------------------------
556
;
557
; NET_ptr_to_num
558
;
559
; IN:  ebx = ptr to device struct
560
; OUT: edi = -1 on error, device number otherwise
561
;
562
;-----------------------------------------------------------------
563
align 4
564
NET_ptr_to_num:
3643 hidnplayr 565
 
566
        call    NET_ptr_to_num4
567
        ror     edi, 2          ; If -1, stay -1
568
                                ; valid device numbers have last two bits 0, so do just shr
569
 
570
        ret
571
 
572
align 4
573
NET_ptr_to_num4:                ; Todo, place number in device structure so we only need to verify?
574
 
5522 hidnplayr 575
        test    ebx, ebx
576
        jz      .fail
577
 
3545 hidnplayr 578
        push    ecx
3600 hidnplayr 579
        mov     ecx, NET_DEVICES_MAX
3545 hidnplayr 580
        mov     edi, NET_DRV_LIST
581
  .loop:
582
        cmp     ebx, [edi]
3643 hidnplayr 583
        je      .found
3545 hidnplayr 584
        add     edi, 4
585
        dec     ecx
586
        jnz     .loop
587
 
5522 hidnplayr 588
        pop     ecx
589
  .fail:
3545 hidnplayr 590
        or      edi, -1
591
        ret
592
 
593
  .found:
594
        sub     edi, NET_DRV_LIST
595
        pop     ecx
596
        ret
597
 
598
;-----------------------------------------------------------------
599
;
600
; checksum_1
601
;
602
;  This is the first of two functions needed to calculate a checksum.
603
;
604
;  IN:  edx = start offset for semi-checksum
605
;       esi = pointer to data
606
;       ecx = data size
607
;  OUT: edx = semi-checksum
608
;
609
;
610
; Code was optimized by diamond
611
;
612
;-----------------------------------------------------------------
613
align 4
614
checksum_1:
615
 
616
        shr     ecx, 1
617
        pushf
618
        jz      .no_2
619
 
620
        shr     ecx, 1
621
        pushf
622
        jz      .no_4
623
 
624
        shr     ecx, 1
625
        pushf
626
        jz      .no_8
627
 
628
  .loop:
629
        add     dl, [esi+1]
630
        adc     dh, [esi+0]
631
 
632
        adc     dl, [esi+3]
633
        adc     dh, [esi+2]
634
 
635
        adc     dl, [esi+5]
636
        adc     dh, [esi+4]
637
 
638
        adc     dl, [esi+7]
639
        adc     dh, [esi+6]
640
 
641
        adc     edx, 0
642
        add     esi, 8
643
 
644
        dec     ecx
645
        jnz     .loop
646
 
647
        adc     edx, 0
648
 
649
  .no_8:
650
        popf
651
        jnc     .no_4
652
 
653
        add     dl, [esi+1]
654
        adc     dh, [esi+0]
655
 
656
        adc     dl, [esi+3]
657
        adc     dh, [esi+2]
658
 
659
        adc     edx, 0
660
        add     esi, 4
661
 
662
  .no_4:
663
        popf
664
        jnc     .no_2
665
 
666
        add     dl, [esi+1]
667
        adc     dh, [esi+0]
668
 
669
        adc     edx, 0
670
        inc     esi
671
        inc     esi
672
 
673
  .no_2:
674
        popf
675
        jnc     .end
676
 
677
        add     dh, [esi+0]
678
        adc     edx, 0
679
  .end:
680
        ret
681
 
682
;-----------------------------------------------------------------
683
;
684
; checksum_2
685
;
686
;  This function calculates the final ip/tcp/udp checksum for you
687
;
688
;  IN:  edx = semi-checksum
689
;  OUT: dx = checksum (in INET byte order)
690
;
691
;-----------------------------------------------------------------
692
align 4
693
checksum_2:
694
 
695
        mov     ecx, edx
696
        shr     ecx, 16
697
        and     edx, 0xffff
698
        add     edx, ecx
699
 
700
        mov     ecx, edx
701
        shr     ecx, 16
702
        add     dx, cx
703
        test    dx, dx          ; it seems that ZF is not set when CF is set :(
704
        not     dx
705
        jnz     .not_zero
706
        dec     dx
707
  .not_zero:
708
        xchg    dl, dh
709
 
3556 hidnplayr 710
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Checksum: %x\n", dx
3545 hidnplayr 711
 
712
        ret
713
 
714
 
715
 
716
;----------------------------------------------------------------
717
;
3601 hidnplayr 718
;  System function to work with network devices (74)
3545 hidnplayr 719
;
720
;----------------------------------------------------------------
721
align 4
3601 hidnplayr 722
sys_network:
3545 hidnplayr 723
 
3879 hidnplayr 724
        cmp     bl, 255
3545 hidnplayr 725
        jne     @f
726
 
727
        mov     eax, [NET_RUNNING]
3601 hidnplayr 728
        mov     [esp+32], eax
729
        ret
3545 hidnplayr 730
 
731
   @@:
3600 hidnplayr 732
        cmp     bh, NET_DEVICES_MAX             ; Check if device number exists
3545 hidnplayr 733
        jae     .doesnt_exist
734
 
735
        mov     esi, ebx
736
        and     esi, 0x0000ff00
737
        shr     esi, 6
738
 
739
        cmp     dword [esi + NET_DRV_LIST], 0   ; check if driver is running
740
        je      .doesnt_exist
741
 
742
        mov     eax, [esi + NET_DRV_LIST]
743
 
744
        and     ebx, 0x000000ff
745
        cmp     ebx, .number
746
        ja      .doesnt_exist
747
        jmp     dword [.table + 4*ebx]
748
 
749
  .table:
750
        dd      .get_type               ; 0
751
        dd      .get_dev_name           ; 1
752
        dd      .reset                  ; 2
753
        dd      .stop                   ; 3
754
        dd      .get_ptr                ; 4
755
        dd      .get_drv_name           ; 5
3601 hidnplayr 756
 
757
        dd      .packets_tx             ; 6
758
        dd      .packets_rx             ; 7
759
        dd      .bytes_tx               ; 8
760
        dd      .bytes_rx               ; 9
761
        dd      .state                  ; 10
3545 hidnplayr 762
  .number = ($ - .table) / 4 - 1
763
 
3601 hidnplayr 764
  .get_type:
3600 hidnplayr 765
        mov     eax, [eax + NET_DEVICE.device_type]
3601 hidnplayr 766
        mov     [esp+32], eax
767
        ret
3545 hidnplayr 768
 
3601 hidnplayr 769
  .get_dev_name:
3545 hidnplayr 770
        mov     esi, [eax + NET_DEVICE.name]
771
        mov     edi, ecx
772
 
773
        mov     ecx, 64/4 ; max length
3711 clevermous 774
        rep movsd
3545 hidnplayr 775
 
776
        xor     eax, eax
3601 hidnplayr 777
        mov     [esp+32], eax
778
        ret
3545 hidnplayr 779
 
3601 hidnplayr 780
  .reset:
3545 hidnplayr 781
        call    [eax + NET_DEVICE.reset]
3601 hidnplayr 782
        mov     [esp+32], eax
783
        ret
3545 hidnplayr 784
 
3601 hidnplayr 785
  .stop:
3545 hidnplayr 786
        call    [eax + NET_DEVICE.unload]
3601 hidnplayr 787
        mov     [esp+32], eax
788
        ret
3545 hidnplayr 789
 
790
 
3601 hidnplayr 791
  .get_ptr:
792
        mov     [esp+32], eax
793
        ret
3545 hidnplayr 794
 
795
 
3601 hidnplayr 796
  .get_drv_name:
797
        xor     eax, eax
798
        mov     [esp+32], eax
799
        ret
3545 hidnplayr 800
 
3601 hidnplayr 801
  .packets_tx:
802
        mov     eax, [eax + NET_DEVICE.packets_tx]
803
        mov     [esp+32], eax
804
        ret
3545 hidnplayr 805
 
3601 hidnplayr 806
  .packets_rx:
807
        mov     eax, [eax + NET_DEVICE.packets_rx]
808
        mov     [esp+32], eax
809
        ret
3545 hidnplayr 810
 
3601 hidnplayr 811
  .bytes_tx:
812
        mov     ebx, dword [eax + NET_DEVICE.bytes_tx + 4]
813
        mov     [esp+20], ebx
814
        mov     eax, dword [eax + NET_DEVICE.bytes_tx]
815
        mov     [esp+32], eax
816
        ret
3545 hidnplayr 817
 
3601 hidnplayr 818
  .bytes_rx:
819
        mov     ebx, dword [eax + NET_DEVICE.bytes_rx + 4]
820
        mov     [esp+20], ebx
821
        mov     eax, dword [eax + NET_DEVICE.bytes_rx]
822
        mov     [esp+32], eax
823
        ret
3545 hidnplayr 824
 
3601 hidnplayr 825
  .state:
826
        mov     eax, [eax + NET_DEVICE.link_state]
3545 hidnplayr 827
        mov     [esp+32], eax
828
        ret
829
 
830
 
3601 hidnplayr 831
  .doesnt_exist:
832
        mov     dword[esp+32], -1
833
        ret
834
 
835
 
836
 
3545 hidnplayr 837
;----------------------------------------------------------------
838
;
839
;  System function to work with protocols  (76)
840
;
841
;----------------------------------------------------------------
842
align 4
843
sys_protocols:
3600 hidnplayr 844
        cmp     bh, NET_DEVICES_MAX             ; Check if device number exists
3545 hidnplayr 845
        jae     .doesnt_exist
846
 
847
        mov     esi, ebx
848
        and     esi, 0x0000ff00
849
        shr     esi, 6                          ; now we have the device num * 4 in esi
850
        cmp     [esi + NET_DRV_LIST], 0         ; check if driver is running
851
        je      .doesnt_exist
852
 
853
        push    .return                         ; return address (we will be using jumps instead of calls)
854
 
855
        mov     eax, ebx                        ; set ax to protocol number
856
        shr     eax, 16                         ;
857
 
858
        cmp     ax, API_ETH
859
        je      ETH_api
860
 
861
        cmp     ax, API_IPv4
862
        je      IPv4_api
863
 
864
        cmp     ax, API_ICMP
865
        je      ICMP_api
866
 
867
        cmp     ax, API_UDP
868
        je      UDP_api
869
 
870
        cmp     ax, API_TCP
871
        je      TCP_api
872
 
873
        cmp     ax, API_ARP
874
        je      ARP_api
875
 
876
        cmp     ax, API_PPPOE
877
        je      PPPoE_api
878
 
879
        cmp     ax, API_IPv6
880
        je      IPv6_api
881
 
882
        add     esp, 4                           ; if we reached here, no function was called, so we need to balance stack
883
 
884
  .doesnt_exist:
885
        mov     eax, -1
886
 
887
  .return:
888
        mov     [esp+28+4], eax                 ; return eax value to the program
889
        ret