Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
3555 Serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
5565 serge 3
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved.    ;;
3555 Serge 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
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
379 serge 16
 
593 mikedld 17
$Revision: 5594 $
379 serge 18
 
593 mikedld 19
 
3555 Serge 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
 
3725 Serge 30
uglobal
3555 Serge 31
align 4
3725 Serge 32
 
3626 Serge 33
        UDP_PACKETS_TX          rd  NET_DEVICES_MAX
34
        UDP_PACKETS_RX          rd  NET_DEVICES_MAX
3725 Serge 35
 
3555 Serge 36
endg
37
 
38
 
39
;-----------------------------------------------------------------
1 ha 40
;
3555 Serge 41
; UDP_init
379 serge 42
;
3555 Serge 43
;  This function resets all UDP variables
44
;
45
;-----------------------------------------------------------------
46
macro   UDP_init {
261 hidnplayr 47
 
3555 Serge 48
        xor     eax, eax
49
        mov     edi, UDP_PACKETS_TX
3626 Serge 50
        mov     ecx, 2*NET_DEVICES_MAX
3725 Serge 51
        rep stosd
3555 Serge 52
}
261 hidnplayr 53
 
3555 Serge 54
 
55
macro   UDP_checksum    IP1, IP2  { ; esi = ptr to udp packet, ecx = packet size, destroys: ecx, edx
56
 
57
; Pseudoheader
58
        mov     edx, IP_PROTO_UDP
59
 
60
        add     dl, [IP1+1]
61
        adc     dh, [IP1+0]
62
        adc     dl, [IP1+3]
63
        adc     dh, [IP1+2]
64
 
65
        adc     dl, [IP2+1]
66
        adc     dh, [IP2+0]
67
        adc     dl, [IP2+3]
68
        adc     dh, [IP2+2]
69
 
70
        adc     dl, cl ; byte[esi+UDP_header.Length+1]
71
        adc     dh, ch ; byte[esi+UDP_header.Length+0]
72
 
73
; Done with pseudoheader, now do real header
74
        adc     dl, byte[esi+UDP_header.SourcePort+1]
75
        adc     dh, byte[esi+UDP_header.SourcePort+0]
76
 
77
        adc     dl, byte[esi+UDP_header.DestinationPort+1]
78
        adc     dh, byte[esi+UDP_header.DestinationPort+0]
79
 
80
        adc     dl, byte[esi+UDP_header.Length+1]
81
        adc     dh, byte[esi+UDP_header.Length+0]
82
 
83
        adc     edx, 0
84
 
85
; Done with header, now do data
86
        push    esi
87
        movzx   ecx, [esi+UDP_header.Length]
88
        rol     cx , 8
89
        sub     cx , sizeof.UDP_header
90
        add     esi, sizeof.UDP_header
91
 
92
        call    checksum_1
93
        call    checksum_2
94
        pop     esi
95
 
96
        add     [esi+UDP_header.Checksum], dx   ; this final instruction will set or clear ZF :)
97
 
98
}
99
 
100
 
101
;-----------------------------------------------------------------
261 hidnplayr 102
;
3555 Serge 103
; UDP_input:
261 hidnplayr 104
;
3555 Serge 105
;  Called by IPv4_input,
106
;  this procedure will inject the udp data diagrams in the application sockets.
261 hidnplayr 107
;
3555 Serge 108
;  IN:   [esp]  = Pointer to buffer
109
;       [esp+4] = size of buffer
110
;       ebx = ptr to device struct
111
;       ecx = UDP Packet size
112
;       esi = ptr to UDP header
113
;       edi = ptr to ipv4 source and dest address
261 hidnplayr 114
;
3555 Serge 115
;  OUT: /
116
;
117
;-----------------------------------------------------------------
118
align 4
119
UDP_input:
261 hidnplayr 120
 
3589 Serge 121
        DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_input: size=%u\n", ecx
261 hidnplayr 122
 
3555 Serge 123
        ; First validate, checksum
261 hidnplayr 124
 
3555 Serge 125
        neg     [esi + UDP_header.Checksum]     ; substract checksum from 0
126
        jz      .no_checksum                    ; if checksum is zero, it is considered valid
261 hidnplayr 127
 
3555 Serge 128
        ; otherwise, we will re-calculate the checksum and add it to this value, thus creating 0 when it is correct
129
 
130
        UDP_checksum (edi), (edi+4)
131
        jnz     .checksum_mismatch
132
 
133
  .no_checksum:
3589 Serge 134
        DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_input: checksum ok\n"
3555 Serge 135
 
136
        ; Convert length to little endian
137
 
138
        rol     [esi + UDP_header.Length], 8
139
 
140
        ; Look for a socket where
141
        ; IP Packet UDP Destination Port = local Port
142
        ; IP Packet SA = Remote IP
143
 
3725 Serge 144
        pusha
145
        mov     ecx, socket_mutex
146
        call    mutex_lock
147
        popa
148
 
3555 Serge 149
        mov     cx, [esi + UDP_header.SourcePort]
150
        mov     dx, [esi + UDP_header.DestinationPort]
151
        mov     edi, [edi + 4]                          ; ipv4 source address
152
        mov     eax, net_sockets
153
 
154
  .next_socket:
155
        mov     eax, [eax + SOCKET.NextPtr]
156
        or      eax, eax
5565 serge 157
        jz      .unlock_dump
3555 Serge 158
 
159
        cmp     [eax + SOCKET.Domain], AF_INET4
160
        jne     .next_socket
161
 
162
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
163
        jne     .next_socket
164
 
165
        cmp     [eax + UDP_SOCKET.LocalPort], dx
166
        jne     .next_socket
167
 
3589 Serge 168
        DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_input: socket=%x\n", eax
3555 Serge 169
 
3725 Serge 170
        pusha
171
        mov     ecx, socket_mutex
172
        call    mutex_unlock
173
        popa
174
 
3555 Serge 175
        ;;; TODO: when packet is processed, check more sockets!
176
 
177
;        cmp     [eax + IP_SOCKET.RemoteIP], 0xffffffff
178
;        je      @f
179
;        cmp     [eax + IP_SOCKET.RemoteIP], edi
180
;        jne     .next_socket
181
;       @@:
1 ha 182
;
3555 Serge 183
; FIXME: UDP should check remote IP, but not under all circumstances!
184
 
4265 Serge 185
        cmp     [eax + UDP_SOCKET.RemotePort], 0
3555 Serge 186
        je      .updateport
187
 
188
        cmp     [eax + UDP_SOCKET.RemotePort], cx
189
        jne     .dump
190
 
191
        pusha
192
        lea     ecx, [eax + SOCKET.mutex]
193
        call    mutex_lock
194
        popa
195
 
196
  .updatesock:
3725 Serge 197
        call    NET_ptr_to_num4
198
        inc     [UDP_PACKETS_RX + edi]
3555 Serge 199
 
200
        movzx   ecx, [esi + UDP_header.Length]
201
        sub     ecx, sizeof.UDP_header
202
        add     esi, sizeof.UDP_header
203
 
204
        jmp     SOCKET_input
205
 
206
  .updateport:
207
        pusha
208
        lea     ecx, [eax + SOCKET.mutex]
209
        call    mutex_lock
210
        popa
211
 
3589 Serge 212
        DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_input: new remote port=%x\n", cx ; FIXME: find a way to print big endian values with debugf
3555 Serge 213
        mov     [eax + UDP_SOCKET.RemotePort], cx
214
        jmp     .updatesock
215
 
5565 serge 216
  .unlock_dump:
3725 Serge 217
        pusha
218
        mov     ecx, socket_mutex
219
        call    mutex_unlock
220
        popa
221
 
222
        DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_input: no socket found\n"
223
        jmp     .dump
224
 
3555 Serge 225
  .checksum_mismatch:
3589 Serge 226
        DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_input: checksum mismatch\n"
3555 Serge 227
 
228
  .dump:
5565 serge 229
        DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_input: dumping\n"
230
        call    NET_BUFF_free
3555 Serge 231
        ret
232
 
233
 
234
 
235
;-----------------------------------------------------------------
1 ha 236
;
3555 Serge 237
; UDP_output
238
;
239
; IN: eax = socket pointer
240
;     ecx = number of bytes to send
241
;     esi = pointer to data
242
;
5201 serge 243
; OUT: eax = -1 on error
244
;
3555 Serge 245
;-----------------------------------------------------------------
379 serge 246
 
3555 Serge 247
align 4
248
UDP_output:
379 serge 249
 
3589 Serge 250
        DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_output: socket=%x bytes=%u data_ptr=%x\n", eax, ecx, esi
379 serge 251
 
3555 Serge 252
        mov     dx, [eax + UDP_SOCKET.RemotePort]
3589 Serge 253
        DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_output: remote port=%x, ", dx    ; FIXME: find a way to print big endian values with debugf
3555 Serge 254
        rol     edx, 16
255
        mov     dx, [eax + UDP_SOCKET.LocalPort]
3589 Serge 256
        DEBUGF  DEBUG_NETWORK_VERBOSE, "local port=%x\n", dx
379 serge 257
 
5565 serge 258
        sub     esp, 4                                          ; Data ptr will be placed here
3555 Serge 259
        push    edx esi
260
        mov     edx, [eax + IP_SOCKET.LocalIP]
5594 serge 261
        mov     ebx, [eax + IP_SOCKET.device]
3555 Serge 262
        mov     eax, [eax + IP_SOCKET.RemoteIP]
263
        mov     di, IP_PROTO_UDP shl 8 + 128
264
        add     ecx, sizeof.UDP_header
265
        call    IPv4_output
266
        jz      .fail
267
        mov     [esp + 8], eax                                  ; pointer to buffer start
379 serge 268
 
3555 Serge 269
        mov     [edi + UDP_header.Length], cx
270
        rol     [edi + UDP_header.Length], 8
379 serge 271
 
3555 Serge 272
        pop     esi
273
        push    edi ecx
274
        sub     ecx, sizeof.UDP_header
275
        add     edi, sizeof.UDP_header
276
        shr     ecx, 2
3725 Serge 277
        rep movsd
3555 Serge 278
        mov     ecx, [esp]
279
        and     ecx, 3
3725 Serge 280
        rep movsb
3555 Serge 281
        pop     ecx edi
379 serge 282
 
3555 Serge 283
        pop     dword [edi + UDP_header.SourcePort]
1 ha 284
 
3555 Serge 285
; Checksum
286
        mov     esi, edi
287
        mov     [edi + UDP_header.Checksum], 0
288
        UDP_checksum (edi-4), (edi-8)                           ; FIXME: IPv4 packet could have options..
379 serge 289
 
3589 Serge 290
        DEBUGF  DEBUG_NETWORK_VERBOSE, "UDP_output: sending with device %x\n", ebx
3555 Serge 291
        call    [ebx + NET_DEVICE.transmit]
292
        test    eax, eax
293
        jnz     @f
3725 Serge 294
        call    NET_ptr_to_num4
295
        inc     [UDP_PACKETS_TX + edi]
3555 Serge 296
       @@:
379 serge 297
 
3555 Serge 298
        ret
379 serge 299
 
3555 Serge 300
  .fail:
3589 Serge 301
        DEBUGF  DEBUG_NETWORK_ERROR, "UDP_output: failed\n"
3555 Serge 302
        add     esp, 4+4+8
303
        or      eax, -1
304
        ret
379 serge 305
 
306
 
307
 
4265 Serge 308
 
309
;-----------------------------------------------------------------
310
;
311
; UDP_connect
312
;
313
;   IN: eax = socket pointer
314
;  OUT: eax = 0 ok / -1 error
315
;       ebx = error code
316
;
317
;-------------------------
318
align 4
319
UDP_connect:
320
 
321
        test    [eax + SOCKET.state], SS_ISCONNECTED
322
        jz      @f
323
        call    UDP_disconnect
324
  @@:
325
 
326
        push    eax edx
327
        lea     ecx, [eax + SOCKET.mutex]
328
        call    mutex_lock
329
        pop     edx eax
330
 
331
; Fill in local IP
332
        cmp     [eax + IP_SOCKET.LocalIP], 0
333
        jne     @f
334
        push    [IP_LIST + 4]                                   ; FIXME: use correct local IP
335
        pop     [eax + IP_SOCKET.LocalIP]
336
 
337
; Fill in remote port and IP, overwriting eventually previous values
338
        pushw   [edx + 2]
339
        pop     [eax + UDP_SOCKET.RemotePort]
340
 
341
        pushd   [edx + 4]
342
        pop     [eax + IP_SOCKET.RemoteIP]
343
 
344
; Find a local port, if user didnt define one
345
        cmp     [eax + UDP_SOCKET.LocalPort], 0
346
        jne     @f
347
        call    SOCKET_find_port
348
       @@:
349
 
350
        push    eax
351
        init_queue (eax + SOCKET_QUEUE_LOCATION)                ; Set up data receiving queue
352
        pop     eax
353
 
354
        push    eax
355
        lea     ecx, [eax + SOCKET.mutex]
356
        call    mutex_unlock
357
        pop     eax
358
 
359
        call    SOCKET_is_connected
360
 
361
        xor     eax, eax
362
        ret
363
 
364
 
365
;-----------------------------------------------------------------
366
;
367
; UDP_disconnect
368
;
369
;   IN: eax = socket pointer
370
;  OUT: eax = socket pointer
371
;
372
;-------------------------
373
align 4
374
UDP_disconnect:
375
 
376
        ; TODO: remove the pending received data
377
 
378
        call    SOCKET_is_disconnected
379
 
380
        ret
381
 
382
 
383
 
384
 
385
 
3555 Serge 386
;---------------------------------------------------------------------------
387
;
388
; UDP_API
389
;
390
; This function is called by system function 75
391
;
392
; IN:  subfunction number in bl
393
;      device number in bh
394
;      ecx, edx, .. depends on subfunction
395
;
396
; OUT:
397
;
398
;---------------------------------------------------------------------------
1 ha 399
 
3555 Serge 400
align 4
401
UDP_api:
379 serge 402
 
3555 Serge 403
        movzx   eax, bh
404
        shl     eax, 2
379 serge 405
 
3555 Serge 406
        test    bl, bl
407
        jz      .packets_tx     ; 0
408
        dec     bl
409
        jz      .packets_rx     ; 1
379 serge 410
 
3555 Serge 411
  .error:
412
        mov     eax, -1
413
        ret
379 serge 414
 
3555 Serge 415
  .packets_tx:
416
        mov     eax, [UDP_PACKETS_TX + eax]
417
        ret
379 serge 418
 
3555 Serge 419
  .packets_rx:
420
        mov     eax, [UDP_PACKETS_RX + eax]
421
        ret