Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved.    ;;
4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  UDP.INC                                                        ;;
7
;;                                                                 ;;
8
;;  Part of the tcp/ip network stack for KolibriOS                 ;;
9
;;                                                                 ;;
10
;;    Written by hidnplayr@kolibrios.org                           ;;
11
;;                                                                 ;;
12
;;          GNU GENERAL PUBLIC LICENSE                             ;;
13
;;             Version 2, June 1991                                ;;
14
;;                                                                 ;;
15
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
16
 
17
$Revision: 2995 $
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
 
30
align 4
31
uglobal
3600 hidnplayr 32
        UDP_PACKETS_TX          rd  NET_DEVICES_MAX
33
        UDP_PACKETS_RX          rd  NET_DEVICES_MAX
3545 hidnplayr 34
endg
35
 
36
 
37
;-----------------------------------------------------------------
38
;
39
; UDP_init
40
;
41
;  This function resets all UDP variables
42
;
43
;-----------------------------------------------------------------
44
macro   UDP_init {
45
 
46
        xor     eax, eax
47
        mov     edi, UDP_PACKETS_TX
3600 hidnplayr 48
        mov     ecx, 2*NET_DEVICES_MAX
3545 hidnplayr 49
        rep     stosd
50
}
51
 
52
 
53
macro   UDP_checksum    IP1, IP2  { ; esi = ptr to udp packet, ecx = packet size, destroys: ecx, edx
54
 
55
; Pseudoheader
56
        mov     edx, IP_PROTO_UDP
57
 
58
        add     dl, [IP1+1]
59
        adc     dh, [IP1+0]
60
        adc     dl, [IP1+3]
61
        adc     dh, [IP1+2]
62
 
63
        adc     dl, [IP2+1]
64
        adc     dh, [IP2+0]
65
        adc     dl, [IP2+3]
66
        adc     dh, [IP2+2]
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
 
99
;-----------------------------------------------------------------
100
;
101
; UDP_input:
102
;
103
;  Called by IPv4_input,
104
;  this procedure will inject the udp data diagrams in the application sockets.
105
;
106
;  IN:   [esp]  = Pointer to buffer
107
;       [esp+4] = size of buffer
108
;       ebx = ptr to device struct
109
;       ecx = UDP Packet size
110
;       esi = ptr to UDP header
111
;       edi = ptr to ipv4 source and dest address
112
;
113
;  OUT: /
114
;
115
;-----------------------------------------------------------------
116
align 4
117
UDP_input:
118
 
3556 hidnplayr 119
        DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_input: size=%u\n", ecx
3545 hidnplayr 120
 
121
        ; First validate, checksum
122
 
123
        neg     [esi + UDP_header.Checksum]     ; substract checksum from 0
124
        jz      .no_checksum                    ; if checksum is zero, it is considered valid
125
 
126
        ; otherwise, we will re-calculate the checksum and add it to this value, thus creating 0 when it is correct
127
 
128
        UDP_checksum (edi), (edi+4)
129
        jnz     .checksum_mismatch
130
 
131
  .no_checksum:
3556 hidnplayr 132
        DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_input: checksum ok\n"
3545 hidnplayr 133
 
134
        ; Convert length to little endian
135
 
136
        rol     [esi + UDP_header.Length], 8
137
 
138
        ; Look for a socket where
139
        ; IP Packet UDP Destination Port = local Port
140
        ; IP Packet SA = Remote IP
141
 
142
        mov     cx, [esi + UDP_header.SourcePort]
143
        mov     dx, [esi + UDP_header.DestinationPort]
144
        mov     edi, [edi + 4]                          ; ipv4 source address
145
        mov     eax, net_sockets
146
 
147
  .next_socket:
148
        mov     eax, [eax + SOCKET.NextPtr]
149
        or      eax, eax
150
        jz      .dump
151
 
152
        cmp     [eax + SOCKET.Domain], AF_INET4
153
        jne     .next_socket
154
 
155
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
156
        jne     .next_socket
157
 
158
        cmp     [eax + UDP_SOCKET.LocalPort], dx
159
        jne     .next_socket
160
 
3556 hidnplayr 161
        DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_input: socket=%x\n", eax
3545 hidnplayr 162
 
163
        ;;; TODO: when packet is processed, check more sockets!
164
 
165
;        cmp     [eax + IP_SOCKET.RemoteIP], 0xffffffff
166
;        je      @f
167
;        cmp     [eax + IP_SOCKET.RemoteIP], edi
168
;        jne     .next_socket
169
;       @@:
170
;
171
; FIXME: UDP should check remote IP, but not under all circumstances!
172
 
173
        cmp     [eax + UDP_SOCKET.firstpacket], 0
174
        je      .updateport
175
 
176
        cmp     [eax + UDP_SOCKET.RemotePort], cx
177
        jne     .dump
178
 
179
        pusha
180
        lea     ecx, [eax + SOCKET.mutex]
181
        call    mutex_lock
182
        popa
183
 
184
  .updatesock:
3643 hidnplayr 185
        call    NET_ptr_to_num4
186
        inc     [UDP_PACKETS_RX + edi]
3545 hidnplayr 187
 
188
        movzx   ecx, [esi + UDP_header.Length]
189
        sub     ecx, sizeof.UDP_header
190
        add     esi, sizeof.UDP_header
191
 
192
        jmp     SOCKET_input
193
 
194
  .updateport:
195
        pusha
196
        lea     ecx, [eax + SOCKET.mutex]
197
        call    mutex_lock
198
        popa
199
 
3556 hidnplayr 200
        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 201
        mov     [eax + UDP_SOCKET.RemotePort], cx
202
        inc     [eax + UDP_SOCKET.firstpacket]
203
 
204
        jmp     .updatesock
205
 
206
 
207
  .checksum_mismatch:
3556 hidnplayr 208
        DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_input: checksum mismatch\n"
3545 hidnplayr 209
 
210
  .dump:
211
        call    kernel_free
212
        add     esp, 4 ; pop (balance stack)
3556 hidnplayr 213
        DEBUGF  DEBUG_NETWORK_VERBOSE,"UDP_input: dumping\n"
3545 hidnplayr 214
 
215
        ret
216
 
217
 
218
 
219
 
220
;-----------------------------------------------------------------
221
;
222
; UDP_output
223
;
224
; IN: eax = socket pointer
225
;     ecx = number of bytes to send
226
;     esi = pointer to data
227
;
228
;-----------------------------------------------------------------
229
 
230
align 4
231
UDP_output:
232
 
3556 hidnplayr 233
        DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_output: socket=%x bytes=%u data_ptr=%x\n", eax, ecx, esi
3545 hidnplayr 234
 
235
        mov     dx, [eax + UDP_SOCKET.RemotePort]
3556 hidnplayr 236
        DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_output: remote port=%x, ", dx    ; FIXME: find a way to print big endian values with debugf
3545 hidnplayr 237
        rol     edx, 16
238
        mov     dx, [eax + UDP_SOCKET.LocalPort]
3556 hidnplayr 239
        DEBUGF  DEBUG_NETWORK_VERBOSE, "local port=%x\n", dx
3545 hidnplayr 240
 
241
        sub     esp, 8                                          ; Data ptr and data size will be placed here
242
        push    edx esi
243
        mov     ebx, [eax + SOCKET.device]
244
        mov     edx, [eax + IP_SOCKET.LocalIP]
245
        mov     eax, [eax + IP_SOCKET.RemoteIP]
246
        mov     di, IP_PROTO_UDP shl 8 + 128
247
        add     ecx, sizeof.UDP_header
248
        call    IPv4_output
249
        jz      .fail
250
        mov     [esp + 8], eax                                  ; pointer to buffer start
251
        mov     [esp + 8 + 4], edx                              ; buffer size
252
 
253
        mov     [edi + UDP_header.Length], cx
254
        rol     [edi + UDP_header.Length], 8
255
 
256
        pop     esi
257
        push    edi ecx
258
        sub     ecx, sizeof.UDP_header
259
        add     edi, sizeof.UDP_header
260
        shr     ecx, 2
261
        rep     movsd
262
        mov     ecx, [esp]
263
        and     ecx, 3
264
        rep     movsb
265
        pop     ecx edi
266
 
267
        pop     dword [edi + UDP_header.SourcePort]
268
 
269
; Checksum
270
        mov     esi, edi
271
        mov     [edi + UDP_header.Checksum], 0
272
        UDP_checksum (edi-4), (edi-8)                           ; FIXME: IPv4 packet could have options..
273
 
3556 hidnplayr 274
        DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_output: sending with device %x\n", ebx
3545 hidnplayr 275
        call    [ebx + NET_DEVICE.transmit]
276
        test    eax, eax
277
        jnz     @f
3643 hidnplayr 278
        call    NET_ptr_to_num4
279
        inc     [UDP_PACKETS_TX + edi]
3545 hidnplayr 280
       @@:
281
 
282
        ret
283
 
284
  .fail:
3556 hidnplayr 285
        DEBUGF  DEBUG_NETWORK_ERROR, "UDP_output: failed\n"
3545 hidnplayr 286
        add     esp, 4+4+8
287
        or      eax, -1
288
        ret
289
 
290
 
291
 
292
;---------------------------------------------------------------------------
293
;
294
; UDP_API
295
;
296
; This function is called by system function 75
297
;
298
; IN:  subfunction number in bl
299
;      device number in bh
300
;      ecx, edx, .. depends on subfunction
301
;
302
; OUT:
303
;
304
;---------------------------------------------------------------------------
305
 
306
align 4
307
UDP_api:
308
 
309
        movzx   eax, bh
310
        shl     eax, 2
311
 
312
        test    bl, bl
313
        jz      .packets_tx     ; 0
314
        dec     bl
315
        jz      .packets_rx     ; 1
316
 
317
  .error:
318
        mov     eax, -1
319
        ret
320
 
321
  .packets_tx:
322
        mov     eax, [UDP_PACKETS_TX + eax]
323
        ret
324
 
325
  .packets_rx:
326
        mov     eax, [UDP_PACKETS_RX + eax]
327
        ret