Subversion Repositories Kolibri OS

Rev

Rev 3556 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved.    ;;
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
 
24
$Revision: 3523 $
25
 
26
uglobal
27
        net_10ms        dd ?
28
        net_tmr_count   dw ?
29
endg
30
 
31
MAX_NET_DEVICES         = 16
32
ARP_BLOCK               = 1             ; true or false
33
 
34
MIN_EPHEMERAL_PORT      = 49152
35
MIN_EPHEMERAL_PORT_N    = 0x00C0        ; same in Network byte order (FIXME)
36
MAX_EPHEMERAL_PORT      = 61000
37
MAX_EPHEMERAL_PORT_N    = 0x48EE        ; same in Network byte order (FIXME)
38
 
39
; Ethernet protocol numbers
40
ETHER_ARP               = 0x0608
41
ETHER_IPv4              = 0x0008
42
ETHER_IPv6              = 0xDD86
43
ETHER_PPP_DISCOVERY     = 0x6388
44
ETHER_PPP_SESSION       = 0x6488
45
 
46
; PPP protocol numbers
47
PPP_IPv4                = 0x2100
48
PPP_IPV6                = 0x5780
49
 
50
;Protocol family
51
AF_UNSPEC               = 0
52
AF_LOCAL                = 1
53
AF_INET4                = 2
54
AF_INET6                = 10
55
AF_PPP                  = 777
56
 
57
; Internet protocol numbers
58
IP_PROTO_IP             = 0
59
IP_PROTO_ICMP           = 1
60
IP_PROTO_TCP            = 6
61
IP_PROTO_UDP            = 17
62
 
63
; PPP protocol number
64
PPP_PROTO_ETHERNET      = 666
65
 
66
; Socket types
67
SOCK_STREAM             = 1
68
SOCK_DGRAM              = 2
69
SOCK_RAW                = 3
70
 
71
; Socket options
72
SO_ACCEPTCON            = 1 shl 0
73
SO_BROADCAST            = 1 shl 1
74
SO_DEBUG                = 1 shl 2
75
SO_DONTROUTE            = 1 shl 3
76
SO_KEEPALIVE            = 1 shl 4
77
SO_OOBINLINE            = 1 shl 5
78
SO_REUSEADDR            = 1 shl 6
79
SO_REUSEPORT            = 1 shl 7
80
SO_USELOOPBACK          = 1 shl 8
81
SO_BINDTODEVICE         = 1 shl 9
82
 
83
SO_BLOCK                = 1 shl 10    ; TO BE REMOVED
84
SO_NONBLOCK             = 1 shl 31
85
 
86
; Socket flags for user calls
87
MSG_PEEK                = 0x02
88
MSG_DONTWAIT            = 0x40
89
 
90
; Socket level
91
SOL_SOCKET              = 0
92
 
93
 
94
; Socket States
95
SS_NOFDREF              = 0x0001      ; no file table ref any more
96
SS_ISCONNECTED          = 0x0002      ; socket connected to a peer
97
SS_ISCONNECTING         = 0x0004      ; in process of connecting to peer
98
SS_ISDISCONNECTING      = 0x0008      ; in process of disconnecting
99
SS_CANTSENDMORE         = 0x0010      ; can't send more data to peer
100
SS_CANTRCVMORE          = 0x0020      ; can't receive more data from peer
101
SS_RCVATMARK            = 0x0040      ; at mark on input
102
SS_ISABORTING           = 0x0080      ; aborting fd references - close()
103
SS_RESTARTSYS           = 0x0100      ; restart blocked system calls
104
SS_ISDISCONNECTED       = 0x0800      ; socket disconnected from peer
105
 
106
SS_ASYNC                = 0x0100      ; async i/o notify
107
SS_ISCONFIRMING         = 0x0200      ; deciding to accept connection req
108
SS_MORETOCOME           = 0x0400
109
 
110
SS_BLOCKED              = 0x8000
111
 
112
 
113
SOCKET_MAXDATA          = 4096*32     ; must be 4096*(power of 2) where 'power of 2' is at least 8
114
 
115
; Network driver types
116
NET_TYPE_LOOPBACK       = 0
117
NET_TYPE_ETH            = 1
118
NET_TYPE_SLIP           = 2
119
 
120
MAX_backlog             = 20          ; maximum backlog for stream sockets
121
 
122
; Error Codes
123
ENOBUFS                 = 55
124
ECONNREFUSED            = 61
125
ECONNRESET              = 52
126
ETIMEDOUT               = 60
127
ECONNABORTED            = 53
128
 
129
; Api protocol numbers
130
API_ETH                 = 0
131
API_IPv4                = 1
132
API_ICMP                = 2
133
API_UDP                 = 3
134
API_TCP                 = 4
135
API_ARP                 = 5
136
API_PPPOE               = 6
137
API_IPv6                = 7
138
 
139
HWACC_TCP_IPv4          = 1 shl 0
140
 
141
struct  NET_DEVICE
142
 
143
        type            dd ?    ; Type field
144
        mtu             dd ?    ; Maximal Transmission Unit
145
        name            dd ?    ; Ptr to 0 terminated string
146
 
147
        unload          dd ?    ; Ptrs to driver functions
148
        reset           dd ?    ;
149
        transmit        dd ?    ;
150
 
151
        bytes_tx        dq ?    ; Statistics, updated by the driver
152
        bytes_rx        dq ?    ;
153
        packets_tx      dd ?    ;
154
        packets_rx      dd ?    ;
155
 
156
        state           dd ?    ; link state (0 = no link)
157
        hwacc           dd ?    ; bitmask stating enabled HW accelerations (offload engines)
158
 
159
ends
160
 
161
 
162
; Exactly as it says..
163
macro pseudo_random reg {
164
        add     reg, [esp]
165
        rol     reg, 5
166
        xor     reg, [timer_ticks]
167
;        add     reg, [CPU_FREQ]
168
        imul    reg, 214013
169
        xor     reg, 0xdeadbeef
170
        rol     reg, 9
171
}
172
 
173
; Network to Hardware byte order (dword)
174
macro ntohd reg {
175
 
176
        rol     word reg, 8
177
        rol     dword reg, 16
178
        rol     word reg , 8
179
 
180
}
181
 
182
; Network to Hardware byte order (word)
183
macro ntohw reg {
184
 
185
        rol     word reg, 8
186
 
187
}
188
 
189
 
190
include "queue.inc"
191
 
192
include "loopback.inc"
193
include "ethernet.inc"
194
 
195
include "PPPoE.inc"
196
 
197
include "ARP.inc"
198
include "IPv4.inc"
199
include "IPv6.inc"
200
 
201
include "icmp.inc"
202
include "udp.inc"
203
include "tcp.inc"
204
 
205
include "socket.inc"
206
 
207
 
208
 
209
align 4
210
uglobal
211
 
212
        NET_RUNNING     dd  ?
213
        NET_DEFAULT     dd  ?
214
        NET_DRV_LIST    rd  MAX_NET_DEVICES
215
 
216
endg
217
 
218
 
219
;-----------------------------------------------------------------
220
;
221
; stack_init
222
;
223
;  This function calls all network init procedures
224
;
225
;  IN:  /
226
;  OUT: /
227
;
228
;-----------------------------------------------------------------
229
align 4
230
stack_init:
231
 
232
; Init the network drivers list
233
        xor     eax, eax
234
        mov     edi, NET_RUNNING
235
        mov     ecx, (MAX_NET_DEVICES + 2)
236
        rep     stosd
237
 
238
        PPPoE_init
239
 
240
        IPv4_init
241
;        IPv6_init
242
        ICMP_init
243
 
244
        ARP_init
245
        UDP_init
246
        TCP_init
247
 
248
        SOCKET_init
249
 
250
        mov     [net_tmr_count], 0
251
 
252
        ret
253
 
254
 
255
 
256
; Wakeup every tick.
257
proc stack_handler_has_work?
258
 
259
        mov eax, [timer_ticks]
260
        cmp eax, [net_10ms]
261
 
262
        ret
263
endp
264
 
265
 
266
;-----------------------------------------------------------------
267
;
268
; stack_handler
269
;
270
;  This function is called in kernel loop
271
;
272
;  IN:  /
273
;  OUT: /
274
;
275
;-----------------------------------------------------------------
276
align 4
277
stack_handler:
278
 
279
        ; Test for 10ms tick
280
        mov     eax, [timer_ticks]
281
        cmp     eax, [net_10ms]
282
        je      .exit
283
        mov     [net_10ms], eax
284
 
285
        cmp     [NET_RUNNING], 0
286
        je      .exit
287
 
288
        test    [net_10ms], 0x0f        ; 160ms
289
        jnz     .exit
290
 
291
        TCP_timer_160ms
292
 
293
        test    [net_10ms], 0x3f        ; 640ms
294
        jnz     .exit
295
 
296
        TCP_timer_640ms
297
        ARP_decrease_entry_ttls
298
        IPv4_decrease_fragment_ttls
299
 
300
  .exit:
301
        ret
302
 
303
 
304
 
305
align 4
306
NET_link_changed:
307
 
308
        DEBUGF  1,"NET_link_changed device=0x%x status=0x%x\n", ebx, [ebx + NET_DEVICE.state]
309
 
310
align 4
311
NET_send_event:
312
 
313
        DEBUGF  1,"NET_send_event\n"
314
 
315
; Send event to all applications
316
        push    edi ecx
317
        mov     edi, SLOT_BASE
318
        mov     ecx, [TASK_COUNT]
319
  .loop:
320
        add     edi, 256
321
        or      [edi + APPDATA.event_mask], EVENT_NETWORK2
322
        loop    .loop
323
        pop     ecx edi
324
 
325
        ret
326
 
327
 
328
 
329
;-----------------------------------------------------------------
330
;
331
; NET_add_device:
332
;
333
;  This function is called by the network drivers,
334
;  to register each running NIC to the kernel
335
;
336
;  IN:  Pointer to device structure in ebx
337
;  OUT: Device num in eax, -1 on error
338
;
339
;-----------------------------------------------------------------
340
align 4
341
NET_add_device:
342
 
343
        DEBUGF  1,"NET_Add_Device: %x\n", ebx   ;;; TODO: use mutex to lock net device list
344
 
345
        cmp     [NET_RUNNING], MAX_NET_DEVICES
346
        jae     .error
347
 
348
;----------------------------------
349
; Check if device is already listed
350
        mov     eax, ebx
351
        mov     ecx, MAX_NET_DEVICES    ; We need to check whole list because a device may be removed without re-organizing list
352
        mov     edi, NET_DRV_LIST
353
 
354
        repne   scasd                   ; See if device is already in the list
355
        jz      .error
356
 
357
;----------------------------
358
; Find empty slot in the list
359
        xor     eax, eax
360
        mov     ecx, MAX_NET_DEVICES
361
        mov     edi, NET_DRV_LIST
362
 
363
        repne   scasd
364
        jnz     .error
365
 
366
        sub     edi, 4
367
 
368
;-----------------------------
369
; Add device to the found slot
370
        mov     [edi], ebx              ; add device to list
371
 
372
        mov     eax, edi                ; Calculate device number in eax
373
        sub     eax, NET_DRV_LIST
374
        shr     eax, 2
375
 
376
        inc     [NET_RUNNING]           ; Indicate that one more network device is up and running
377
 
378
        cmp     eax, 1                  ; If it's the first network device, try to set it as default
379
        jne     @f
380
        push    eax
381
        call    NET_set_default
382
        pop     eax
383
       @@:
384
 
385
        call    NET_send_event
386
 
387
        DEBUGF  1,"Device number: %u\n", eax
388
        ret
389
 
390
  .error:
391
        or      eax, -1
392
        DEBUGF  2,"Adding network device failed\n"
393
        ret
394
 
395
 
396
 
397
;-----------------------------------------------------------------
398
;
399
; NET_set_default
400
;
401
;  API to set the default interface
402
;
403
;  IN:  Device num in eax
404
;  OUT: Device num in eax, -1 on error
405
;
406
;-----------------------------------------------------------------
407
align 4
408
NET_set_default:
409
 
410
        DEBUGF  1,"NET_set_default: device=%x\n", eax
411
 
412
        cmp     eax, MAX_NET_DEVICES
413
        jae     .error
414
 
415
        cmp     [NET_DRV_LIST+eax*4], 0
416
        je      .error
417
 
418
        mov     [NET_DEFAULT], eax
419
 
420
        DEBUGF  1,"NET_set_default: succes\n"
421
        ret
422
 
423
  .error:
424
        or      eax, -1
425
        DEBUGF  1,"NET_set_default: failed\n"
426
        ret
427
 
428
 
429
;-----------------------------------------------------------------
430
;
431
; NET_Remove_Device:
432
;
433
;  This function is called by etwork drivers,
434
;  to unregister network devices from the kernel
435
;
436
;  IN:  Pointer to device structure in ebx
437
;  OUT: eax: -1 on error
438
;
439
;-----------------------------------------------------------------
440
align 4
441
NET_remove_device:
442
 
443
        cmp     [NET_RUNNING], 0
444
        je      .error
445
 
446
        cmp     [NET_DRV_LIST], ebx
447
        jne     @f
448
        mov     [NET_DRV_LIST], 0
449
        cmp     [NET_RUNNING], 1
450
        je      @f
451
        ; there are still active devices, find one and make it default
452
        xor     eax, eax
453
        mov     ecx, MAX_NET_DEVICES
454
        mov     edi, NET_DRV_LIST
455
        repe    scasd
456
        je      @f
457
        shr     edi, 2
458
        dec     edi
459
        mov     [NET_DEFAULT], edi
460
       @@:
461
 
462
;----------------------------
463
; Find the driver in the list
464
 
465
        mov     eax, ebx
466
        mov     ecx, MAX_NET_DEVICES
467
        mov     edi, NET_DRV_LIST+4
468
 
469
        repne   scasd
470
        jnz     .error
471
 
472
;------------------------
473
; Remove it from the list
474
 
475
        xor     eax, eax
476
        mov     dword [edi-4], eax
477
 
478
        call    NET_send_event
479
 
480
        dec     [NET_RUNNING]
481
        ret
482
 
483
  .error:
484
        or      eax, -1
485
        ret
486
 
487
 
488
 
489
;-----------------------------------------------------------------
490
;
491
; NET_ptr_to_num
492
;
493
; IN:  ebx = ptr to device struct
494
; OUT: edi = -1 on error, device number otherwise
495
;
496
;-----------------------------------------------------------------
497
align 4
498
NET_ptr_to_num:
499
        push    ecx
500
 
501
        mov     ecx, MAX_NET_DEVICES
502
        mov     edi, NET_DRV_LIST
503
 
504
  .loop:
505
        cmp     ebx, [edi]
506
        jz      .found
507
        add     edi, 4
508
        dec     ecx
509
        jnz     .loop
510
 
511
        ; repnz  scasd could work too if eax is used instead of ebx!
512
 
513
        or      edi, -1
514
 
515
        pop     ecx
516
        ret
517
 
518
  .found:
519
        sub     edi, NET_DRV_LIST
520
        shr     edi, 2
521
 
522
        pop     ecx
523
        ret
524
 
525
;-----------------------------------------------------------------
526
;
527
; checksum_1
528
;
529
;  This is the first of two functions needed to calculate a checksum.
530
;
531
;  IN:  edx = start offset for semi-checksum
532
;       esi = pointer to data
533
;       ecx = data size
534
;  OUT: edx = semi-checksum
535
;
536
;
537
; Code was optimized by diamond
538
;
539
;-----------------------------------------------------------------
540
align 4
541
checksum_1:
542
 
543
        shr     ecx, 1
544
        pushf
545
        jz      .no_2
546
 
547
        shr     ecx, 1
548
        pushf
549
        jz      .no_4
550
 
551
        shr     ecx, 1
552
        pushf
553
        jz      .no_8
554
 
555
  .loop:
556
        add     dl, [esi+1]
557
        adc     dh, [esi+0]
558
 
559
        adc     dl, [esi+3]
560
        adc     dh, [esi+2]
561
 
562
        adc     dl, [esi+5]
563
        adc     dh, [esi+4]
564
 
565
        adc     dl, [esi+7]
566
        adc     dh, [esi+6]
567
 
568
        adc     edx, 0
569
        add     esi, 8
570
 
571
        dec     ecx
572
        jnz     .loop
573
 
574
        adc     edx, 0
575
 
576
  .no_8:
577
        popf
578
        jnc     .no_4
579
 
580
        add     dl, [esi+1]
581
        adc     dh, [esi+0]
582
 
583
        adc     dl, [esi+3]
584
        adc     dh, [esi+2]
585
 
586
        adc     edx, 0
587
        add     esi, 4
588
 
589
  .no_4:
590
        popf
591
        jnc     .no_2
592
 
593
        add     dl, [esi+1]
594
        adc     dh, [esi+0]
595
 
596
        adc     edx, 0
597
        inc     esi
598
        inc     esi
599
 
600
  .no_2:
601
        popf
602
        jnc     .end
603
 
604
        add     dh, [esi+0]
605
        adc     edx, 0
606
  .end:
607
        ret
608
 
609
;-----------------------------------------------------------------
610
;
611
; checksum_2
612
;
613
;  This function calculates the final ip/tcp/udp checksum for you
614
;
615
;  IN:  edx = semi-checksum
616
;  OUT: dx = checksum (in INET byte order)
617
;
618
;-----------------------------------------------------------------
619
align 4
620
checksum_2:
621
 
622
        mov     ecx, edx
623
        shr     ecx, 16
624
        and     edx, 0xffff
625
        add     edx, ecx
626
 
627
        mov     ecx, edx
628
        shr     ecx, 16
629
        add     dx, cx
630
        test    dx, dx          ; it seems that ZF is not set when CF is set :(
631
        not     dx
632
        jnz     .not_zero
633
        dec     dx
634
  .not_zero:
635
        xchg    dl, dh
636
 
637
        DEBUGF  1,"Checksum: %x\n", dx
638
 
639
        ret
640
 
641
 
642
 
643
;----------------------------------------------------------------
644
;
645
;  System function to work with network devices (75)
646
;
647
;----------------------------------------------------------------
648
align 4
649
sys_network:                    ; FIXME: make default device easily accessible
650
 
651
        cmp     ebx, -1
652
        jne     @f
653
 
654
        mov     eax, [NET_RUNNING]
655
        jmp     .return
656
 
657
   @@:
658
        cmp     bh, MAX_NET_DEVICES             ; Check if device number exists
659
        jae     .doesnt_exist
660
 
661
        mov     esi, ebx
662
        and     esi, 0x0000ff00
663
        shr     esi, 6
664
 
665
        cmp     dword [esi + NET_DRV_LIST], 0   ; check if driver is running
666
        je      .doesnt_exist
667
 
668
        mov     eax, [esi + NET_DRV_LIST]
669
 
670
        and     ebx, 0x000000ff
671
        cmp     ebx, .number
672
        ja      .doesnt_exist
673
        jmp     dword [.table + 4*ebx]
674
 
675
  .table:
676
        dd      .get_type               ; 0
677
        dd      .get_dev_name           ; 1
678
        dd      .reset                  ; 2
679
        dd      .stop                   ; 3
680
        dd      .get_ptr                ; 4
681
        dd      .get_drv_name           ; 5
682
        dd      .set_default            ; 6
683
  .number = ($ - .table) / 4 - 1
684
 
685
  .get_type:                            ; 0 = Get device type (ethernet/token ring/...)
686
 
687
        mov     eax, [eax + NET_DEVICE.type]
688
        jmp     .return
689
 
690
 
691
  .get_dev_name:                        ; 1 = Get device name
692
 
693
        mov     esi, [eax + NET_DEVICE.name]
694
        mov     edi, ecx
695
 
696
        mov     ecx, 64/4 ; max length
697
        rep     movsd
698
 
699
        xor     eax, eax
700
        jmp     .return
701
 
702
  .reset:                               ; 2 = Reset the device
703
 
704
        call    [eax + NET_DEVICE.reset]
705
        jmp     .return
706
 
707
  .stop:                                ; 3 = Stop driver for this device
708
 
709
        call    [eax + NET_DEVICE.unload]
710
        jmp     .return
711
 
712
 
713
  .get_ptr:                             ; 4 = Get driver pointer
714
 
715
        jmp     .return
716
 
717
 
718
  .get_drv_name:                        ; 5 = Get driver name
719
 
720
        xor     eax, eax
721
        jmp     .return
722
 
723
 
724
  .set_default:                         ; 6 = Set default device
725
 
726
        call    NET_set_default
727
        jmp     .return
728
 
729
  .doesnt_exist:
730
        mov     eax, -1
731
 
732
  .return:
733
        mov     [esp+32], eax
734
        ret
735
 
736
 
737
;----------------------------------------------------------------
738
;
739
;  System function to work with protocols  (76)
740
;
741
;----------------------------------------------------------------
742
align 4
743
sys_protocols:
744
        cmp     bh, MAX_NET_DEVICES             ; Check if device number exists
745
        jae     .doesnt_exist
746
 
747
        mov     esi, ebx
748
        and     esi, 0x0000ff00
749
        shr     esi, 6                          ; now we have the device num * 4 in esi
750
        cmp     [esi + NET_DRV_LIST], 0         ; check if driver is running
751
        je      .doesnt_exist
752
 
753
        push    .return                         ; return address (we will be using jumps instead of calls)
754
 
755
        mov     eax, ebx                        ; set ax to protocol number
756
        shr     eax, 16                         ;
757
 
758
        cmp     ax, API_ETH
759
        je      ETH_api
760
 
761
        cmp     ax, API_IPv4
762
        je      IPv4_api
763
 
764
        cmp     ax, API_ICMP
765
        je      ICMP_api
766
 
767
        cmp     ax, API_UDP
768
        je      UDP_api
769
 
770
        cmp     ax, API_TCP
771
        je      TCP_api
772
 
773
        cmp     ax, API_ARP
774
        je      ARP_api
775
 
776
        cmp     ax, API_PPPOE
777
        je      PPPoE_api
778
 
779
        cmp     ax, API_IPv6
780
        je      IPv6_api
781
 
782
        add     esp, 4                           ; if we reached here, no function was called, so we need to balance stack
783
 
784
  .doesnt_exist:
785
        mov     eax, -1
786
 
787
  .return:
788
        mov     [esp+28+4], eax                 ; return eax value to the program
789
        ret