Subversion Repositories Kolibri OS

Rev

Rev 7682 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
7678 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2019. All rights reserved.    ;;
3545 hidnplayr 4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  UDP.INC                                                        ;;
7
;;                                                                 ;;
7682 hidnplayr 8
;;  Part of the TCP/IP network stack for KolibriOS                 ;;
3545 hidnplayr 9
;;                                                                 ;;
10
;;    Written by hidnplayr@kolibrios.org                           ;;
11
;;                                                                 ;;
12
;;          GNU GENERAL PUBLIC LICENSE                             ;;
13
;;             Version 2, June 1991                                ;;
14
;;                                                                 ;;
15
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
16
 
4850 mario79 17
$Revision: 9739 $
3545 hidnplayr 18
 
19
 
20
struct  UDP_header
21
 
22
        SourcePort              dw  ?
23
        DestinationPort         dw  ?
24
        Length                  dw  ?  ; Length of (UDP Header + Data)
25
        Checksum                dw  ?
26
 
27
ends
28
 
29
 
3698 hidnplayr 30
uglobal
3545 hidnplayr 31
align 4
3698 hidnplayr 32
 
7682 hidnplayr 33
        UDP_packets_tx          rd  NET_DEVICES_MAX
34
        UDP_packets_rx          rd  NET_DEVICES_MAX
3698 hidnplayr 35
 
3545 hidnplayr 36
endg
37
 
38
 
5976 hidnplayr 39
;-----------------------------------------------------------------;
40
;                                                                 ;
6011 hidnplayr 41
; udp_init: This function resets all UDP variables                ;
5976 hidnplayr 42
;                                                                 ;
43
;-----------------------------------------------------------------;
6011 hidnplayr 44
macro   udp_init {
3545 hidnplayr 45
 
46
        xor     eax, eax
7678 hidnplayr 47
        mov     edi, UDP_packets_tx
3600 hidnplayr 48
        mov     ecx, 2*NET_DEVICES_MAX
3711 clevermous 49
        rep stosd
3545 hidnplayr 50
}
51
 
52
 
6011 hidnplayr 53
macro   udp_checksum    IP1, IP2  { ; esi = ptr to udp packet, ecx = packet size, destroys: ecx, edx
3545 hidnplayr 54
 
55
; Pseudoheader
56
        mov     edx, IP_PROTO_UDP
57
 
5842 hidnplayr 58
        add     dl, byte[IP1+1]
59
        adc     dh, byte[IP1+0]
60
        adc     dl, byte[IP1+3]
61
        adc     dh, byte[IP1+2]
3545 hidnplayr 62
 
5842 hidnplayr 63
        adc     dl, byte[IP2+1]
64
        adc     dh, byte[IP2+0]
65
        adc     dl, byte[IP2+3]
66
        adc     dh, byte[IP2+2]
3545 hidnplayr 67
 
68
        adc     dl, cl ; byte[esi+UDP_header.Length+1]
69
        adc     dh, ch ; byte[esi+UDP_header.Length+0]
70
 
71
; Done with pseudoheader, now do real header
72
        adc     dl, byte[esi+UDP_header.SourcePort+1]
73
        adc     dh, byte[esi+UDP_header.SourcePort+0]
74
 
75
        adc     dl, byte[esi+UDP_header.DestinationPort+1]
76
        adc     dh, byte[esi+UDP_header.DestinationPort+0]
77
 
78
        adc     dl, byte[esi+UDP_header.Length+1]
79
        adc     dh, byte[esi+UDP_header.Length+0]
80
 
81
        adc     edx, 0
82
 
83
; Done with header, now do data
84
        push    esi
85
        movzx   ecx, [esi+UDP_header.Length]
86
        rol     cx , 8
87
        sub     cx , sizeof.UDP_header
88
        add     esi, sizeof.UDP_header
89
 
90
        call    checksum_1
91
        call    checksum_2
92
        pop     esi
93
 
94
        add     [esi+UDP_header.Checksum], dx   ; this final instruction will set or clear ZF :)
95
 
96
}
97
 
98
 
5976 hidnplayr 99
;-----------------------------------------------------------------;
100
;                                                                 ;
6011 hidnplayr 101
; udp_input: Inject the UDP data in the application sockets.      ;
5976 hidnplayr 102
;                                                                 ;
103
;   IN: [esp] = ptr to buffer                                     ;
104
;       ebx = ptr to device struct                                ;
105
;       ecx = UDP packet size                                     ;
106
;       edx = ptr to IPv4 header                                  ;
107
;       esi = ptr to UDP packet data                              ;
108
;       edi = interface number*4                                  ;
109
;                                                                 ;
110
;  OUT: /                                                         ;
111
;                                                                 ;
112
;-----------------------------------------------------------------;
3545 hidnplayr 113
align 4
6011 hidnplayr 114
udp_input:
3545 hidnplayr 115
 
3556 hidnplayr 116
        DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_input: size=%u\n", ecx
3545 hidnplayr 117
 
118
        ; First validate, checksum
119
 
120
        neg     [esi + UDP_header.Checksum]     ; substract checksum from 0
121
        jz      .no_checksum                    ; if checksum is zero, it is considered valid
122
 
123
        ; otherwise, we will re-calculate the checksum and add it to this value, thus creating 0 when it is correct
124
 
5842 hidnplayr 125
        mov     eax, edx
6011 hidnplayr 126
        udp_checksum (eax+IPv4_header.SourceAddress), (eax+IPv4_header.DestinationAddress)
3545 hidnplayr 127
        jnz     .checksum_mismatch
128
 
129
  .no_checksum:
3556 hidnplayr 130
        DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_input: checksum ok\n"
3545 hidnplayr 131
 
132
        ; Convert length to little endian
133
 
134
        rol     [esi + UDP_header.Length], 8
135
 
136
        ; Look for a socket where
137
        ; IP Packet UDP Destination Port = local Port
138
        ; IP Packet SA = Remote IP
139
 
3647 hidnplayr 140
        pusha
141
        mov     ecx, socket_mutex
142
        call    mutex_lock
143
        popa
144
 
3545 hidnplayr 145
        mov     cx, [esi + UDP_header.SourcePort]
146
        mov     dx, [esi + UDP_header.DestinationPort]
147
        mov     eax, net_sockets
148
  .next_socket:
149
        mov     eax, [eax + SOCKET.NextPtr]
150
        or      eax, eax
5522 hidnplayr 151
        jz      .unlock_dump
3545 hidnplayr 152
 
153
        cmp     [eax + SOCKET.Domain], AF_INET4
154
        jne     .next_socket
155
 
156
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
157
        jne     .next_socket
158
 
159
        cmp     [eax + UDP_SOCKET.LocalPort], dx
160
        jne     .next_socket
161
 
3556 hidnplayr 162
        DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_input: socket=%x\n", eax
3545 hidnplayr 163
 
3647 hidnplayr 164
        pusha
165
        mov     ecx, socket_mutex
166
        call    mutex_unlock
167
        popa
168
 
5842 hidnplayr 169
        ;;; TODO: when packet is processed, check more sockets?!
3545 hidnplayr 170
 
5842 hidnplayr 171
; FIXME: check remote IP if possible
172
;
3545 hidnplayr 173
;        cmp     [eax + IP_SOCKET.RemoteIP], 0xffffffff
174
;        je      @f
5842 hidnplayr 175
;        cmp     [eax + IP_SOCKET.RemoteIP],
3545 hidnplayr 176
;        jne     .next_socket
177
;       @@:
178
 
4030 hidnplayr 179
        cmp     [eax + UDP_SOCKET.RemotePort], 0
3545 hidnplayr 180
        je      .updateport
181
 
182
        cmp     [eax + UDP_SOCKET.RemotePort], cx
183
        jne     .dump
184
 
185
        pusha
186
        lea     ecx, [eax + SOCKET.mutex]
187
        call    mutex_lock
188
        popa
189
 
190
  .updatesock:
7678 hidnplayr 191
        inc     [UDP_packets_rx + edi]
3545 hidnplayr 192
 
193
        movzx   ecx, [esi + UDP_header.Length]
194
        sub     ecx, sizeof.UDP_header
195
        add     esi, sizeof.UDP_header
196
 
6011 hidnplayr 197
        jmp     socket_input
3545 hidnplayr 198
 
199
  .updateport:
200
        pusha
201
        lea     ecx, [eax + SOCKET.mutex]
202
        call    mutex_lock
203
        popa
204
 
3556 hidnplayr 205
        DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_input: new remote port=%x\n", cx ; FIXME: find a way to print big endian values with debugf
3545 hidnplayr 206
        mov     [eax + UDP_SOCKET.RemotePort], cx
207
        jmp     .updatesock
208
 
5522 hidnplayr 209
  .unlock_dump:
3647 hidnplayr 210
        pusha
211
        mov     ecx, socket_mutex
212
        call    mutex_unlock
213
        popa
214