Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
1159 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
2877 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved.    ;;
1159 hidnplayr 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
 
1206 hidnplayr 17
$Revision: 2980 $
1159 hidnplayr 18
 
19
 
2310 hidnplayr 20
struct  UDP_header
1159 hidnplayr 21
 
2308 hidnplayr 22
        SourcePort              dw  ?
23
        DestinationPort         dw  ?
24
        Length                  dw  ?  ; Length of (UDP Header + Data)
25
        Checksum                dw  ?
2305 hidnplayr 26
 
1159 hidnplayr 27
ends
28
 
29
 
30
align 4
31
uglobal
2924 hidnplayr 32
        UDP_PACKETS_TX          rd  MAX_NET_DEVICES
33
        UDP_PACKETS_RX          rd  MAX_NET_DEVICES
1159 hidnplayr 34
endg
35
 
36
 
37
;-----------------------------------------------------------------
38
;
39
; UDP_init
40
;
41
;  This function resets all UDP variables
42
;
43
;-----------------------------------------------------------------
2308 hidnplayr 44
macro   UDP_init {
1159 hidnplayr 45
 
2308 hidnplayr 46
        xor     eax, eax
47
        mov     edi, UDP_PACKETS_TX
2924 hidnplayr 48
        mov     ecx, 2*MAX_NET_DEVICES
2308 hidnplayr 49
        rep     stosd
1529 hidnplayr 50
}
1159 hidnplayr 51
 
52
 
2308 hidnplayr 53
macro   UDP_checksum    IP1, IP2  { ; esi = ptr to udp packet, ecx = packet size, destroys: ecx, edx
1529 hidnplayr 54
 
55
; Pseudoheader
2308 hidnplayr 56
        mov     edx, IP_PROTO_UDP
1529 hidnplayr 57
 
2308 hidnplayr 58
        add     dl, [IP1+1]
59
        adc     dh, [IP1+0]
60
        adc     dl, [IP1+3]
61
        adc     dh, [IP1+2]
1529 hidnplayr 62
 
2308 hidnplayr 63
        adc     dl, [IP2+1]
64
        adc     dh, [IP2+0]
65
        adc     dl, [IP2+3]
66
        adc     dh, [IP2+2]
1529 hidnplayr 67
 
2310 hidnplayr 68
        adc     dl, cl ; byte[esi+UDP_header.Length+1]
69
        adc     dh, ch ; byte[esi+UDP_header.Length+0]
1529 hidnplayr 70
 
71
; Done with pseudoheader, now do real header
2310 hidnplayr 72
        adc     dl, byte[esi+UDP_header.SourcePort+1]
73
        adc     dh, byte[esi+UDP_header.SourcePort+0]
1529 hidnplayr 74
 
2310 hidnplayr 75
        adc     dl, byte[esi+UDP_header.DestinationPort+1]
76
        adc     dh, byte[esi+UDP_header.DestinationPort+0]
1529 hidnplayr 77
 
2310 hidnplayr 78
        adc     dl, byte[esi+UDP_header.Length+1]
79
        adc     dh, byte[esi+UDP_header.Length+0]
1529 hidnplayr 80
 
2308 hidnplayr 81
        adc     edx, 0
1529 hidnplayr 82
 
83
; Done with header, now do data
2308 hidnplayr 84
        push    esi
2310 hidnplayr 85
        movzx   ecx, [esi+UDP_header.Length]
2308 hidnplayr 86
        rol     cx , 8
2310 hidnplayr 87
        sub     cx , sizeof.UDP_header
88
        add     esi, sizeof.UDP_header
1529 hidnplayr 89
 
2308 hidnplayr 90
        call    checksum_1
91
        call    checksum_2
92
        pop     esi
1529 hidnplayr 93
 
2310 hidnplayr 94
        add     [esi+UDP_header.Checksum], dx   ; this final instruction will set or clear ZF :)
1529 hidnplayr 95
 
96
}
97
 
98
 
1159 hidnplayr 99
;-----------------------------------------------------------------
100
;
1514 hidnplayr 101
; UDP_input:
1159 hidnplayr 102
;
1514 hidnplayr 103
;  Called by IPv4_input,
1159 hidnplayr 104
;  this procedure will inject the udp data diagrams in the application sockets.
105
;
1529 hidnplayr 106
;  IN:   [esp]  = Pointer to buffer
107
;       [esp+4] = size of buffer
108
;       ebx = ptr to device struct
109
;       ecx = UDP Packet size
2310 hidnplayr 110
;       esi = ptr to UDP header
2308 hidnplayr 111
;       edi = ptr to ipv4 source and dest address
1484 hidnplayr 112
;
1159 hidnplayr 113
;  OUT: /
114
;
115
;-----------------------------------------------------------------
1206 hidnplayr 116
align 4
1514 hidnplayr 117
UDP_input:
1159 hidnplayr 118
 
2891 hidnplayr 119
        DEBUGF  1,"UDP_input: size=%u\n", ecx
1473 hidnplayr 120
 
2390 hidnplayr 121
        ; First validate, checksum
2310 hidnplayr 122
 
123
        neg     [esi + UDP_header.Checksum]     ; substract checksum from 0
2390 hidnplayr 124
        jz      .no_checksum                    ; if checksum is zero, it is considered valid
1159 hidnplayr 125
 
2390 hidnplayr 126
        ; otherwise, we will re-calculate the checksum and add it to this value, thus creating 0 when it is correct
127
 
2308 hidnplayr 128
        UDP_checksum (edi), (edi+4)
2390 hidnplayr 129
        jnz     .checksum_mismatch
1249 hidnplayr 130
 
1473 hidnplayr 131
  .no_checksum:
2891 hidnplayr 132
        DEBUGF  1,"UDP_input: checksum ok\n"
1473 hidnplayr 133
 
2310 hidnplayr 134
        ; Convert port numbers to intel format
135
 
2369 hidnplayr 136
        rol     [esi + UDP_header.DestinationPort], 8
137
        rol     [esi + UDP_header.SourcePort], 8
138
        rol     [esi + UDP_header.Length], 8
2310 hidnplayr 139
 
2308 hidnplayr 140
        ; Look for a socket where
141
        ; IP Packet UDP Destination Port = local Port
142
        ; IP Packet SA = Remote IP
1159 hidnplayr 143
 
2369 hidnplayr 144
        mov     cx, [esi + UDP_header.SourcePort]
145
        mov     dx, [esi + UDP_header.DestinationPort]
2310 hidnplayr 146
        mov     edi, [edi + 4]                          ; ipv4 source address
2308 hidnplayr 147
        mov     eax, net_sockets
2310 hidnplayr 148
 
1159 hidnplayr 149
  .next_socket:
2308 hidnplayr 150
        mov     eax, [eax + SOCKET.NextPtr]
151
        or      eax, eax
152
        jz      .dump
2310 hidnplayr 153
 
2308 hidnplayr 154
        cmp     [eax + SOCKET.Domain], AF_INET4
155
        jne     .next_socket
2310 hidnplayr 156
 
2308 hidnplayr 157
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
158
        jne     .next_socket
2310 hidnplayr 159
 
2369 hidnplayr 160
        cmp     [eax + UDP_SOCKET.LocalPort], dx
2308 hidnplayr 161
        jne     .next_socket
1159 hidnplayr 162
 
2891 hidnplayr 163
        DEBUGF  1,"UDP_input: socket=%x\n", eax
1208 hidnplayr 164
 
2308 hidnplayr 165
        ;;; TODO: when packet is processed, check more sockets!
1159 hidnplayr 166
 
2366 hidnplayr 167
;        cmp     [eax + IP_SOCKET.RemoteIP], 0xffffffff
168
;        je      @f
169
;        cmp     [eax + IP_SOCKET.RemoteIP], edi
170
;        jne     .next_socket
171
;       @@:
172
;
173
; FIXME: UDP should check remote IP, but not under all circumstances!
1159 hidnplayr 174
 
2308 hidnplayr 175
        cmp     [eax + UDP_SOCKET.firstpacket], 0
2311 hidnplayr 176
        je      .updateport
1159 hidnplayr 177
 
2310 hidnplayr 178
        cmp     [eax + UDP_SOCKET.RemotePort], cx
2308 hidnplayr 179
        jne     .dump
1159 hidnplayr 180
 
2402 hidnplayr 181
        pusha
182
        lea     ecx, [eax + SOCKET.mutex]
183
        call    mutex_lock
184
        popa
1337 hidnplayr 185
 
1514 hidnplayr 186
  .updatesock:
2891 hidnplayr 187
        inc     [UDP_PACKETS_RX]        ; Fixme: correct interface?
188
 
2369 hidnplayr 189
        movzx   ecx, [esi + UDP_header.Length]
2310 hidnplayr 190
        sub     ecx, sizeof.UDP_header
2369 hidnplayr 191
        add     esi, sizeof.UDP_header
1159 hidnplayr 192
 
2308 hidnplayr 193
        jmp     SOCKET_input
1159 hidnplayr 194
 
1335 hidnplayr 195
  .updateport:
2402 hidnplayr 196
        pusha
197
        lea     ecx, [eax + SOCKET.mutex]
198
        call    mutex_lock
199
        popa
1337 hidnplayr 200
 
2891 hidnplayr 201
        DEBUGF  1,"UDP_input: new remote port=%u\n", cx
2311 hidnplayr 202
        mov     [eax + UDP_SOCKET.RemotePort], cx
2308 hidnplayr 203
        inc     [eax + UDP_SOCKET.firstpacket]
1335 hidnplayr 204
 
2308 hidnplayr 205
        jmp     .updatesock
1335 hidnplayr 206
 
1483 hidnplayr 207
 
1473 hidnplayr 208
  .checksum_mismatch:
2891 hidnplayr 209
        DEBUGF  2,"UDP_input: checksum mismatch\n"
1473 hidnplayr 210
 
1206 hidnplayr 211
  .dump:
2308 hidnplayr 212
        call    kernel_free
213
        add     esp, 4 ; pop (balance stack)
2891 hidnplayr 214
        DEBUGF  2,"UDP_input: dumping\n"
1159 hidnplayr 215
 
2308 hidnplayr 216
        ret
1159 hidnplayr 217
 
218
 
219
 
220
 
221
;-----------------------------------------------------------------
222
;
1514 hidnplayr 223
; UDP_output
1159 hidnplayr 224
;
1249 hidnplayr 225
; IN: eax = socket pointer
226
;     ecx = number of bytes to send
227
;     esi = pointer to data
1159 hidnplayr 228
;
229
;-----------------------------------------------------------------
230
 
1249 hidnplayr 231
align 4
1514 hidnplayr 232
UDP_output:
1159 hidnplayr 233
 
2891 hidnplayr 234
        DEBUGF  1,"UDP_output: socket=%x bytes=%u data_ptr=%x\n", eax, ecx, esi
1249 hidnplayr 235
 
2308 hidnplayr 236
        mov     dx, [eax + UDP_SOCKET.RemotePort]
2891 hidnplayr 237
        DEBUGF  1,"UDP_output: remote port=%u, ", dx
2308 hidnplayr 238
        rol     dx, 8
239
        rol     edx, 16
240
        mov     dx, [eax + UDP_SOCKET.LocalPort]
2891 hidnplayr 241
        DEBUGF  1,"local port=%u\n", dx
2308 hidnplayr 242
        rol     dx, 8
1159 hidnplayr 243
 
2877 hidnplayr 244
        sub     esp, 8                                          ; Data ptr and data size will be placed here
245
        push    edx esi
246
        mov     ebx, [eax + SOCKET.device]
247
        mov     edx, [eax + IP_SOCKET.LocalIP]
2308 hidnplayr 248
        mov     eax, [eax + IP_SOCKET.RemoteIP]
249
        mov     di, IP_PROTO_UDP shl 8 + 128
2310 hidnplayr 250
        add     ecx, sizeof.UDP_header
2308 hidnplayr 251
        call    IPv4_output
252
        jz      .fail
253
        mov     [esp + 8], eax                                  ; pointer to buffer start
254
        mov     [esp + 8 + 4], edx                              ; buffer size
1159 hidnplayr 255
 
2310 hidnplayr 256
        mov     [edi + UDP_header.Length], cx
257
        rol     [edi + UDP_header.Length], 8
1249 hidnplayr 258
 
2308 hidnplayr 259
        pop     esi
260
        push    edi ecx
2310 hidnplayr 261
        sub     ecx, sizeof.UDP_header
262
        add     edi, sizeof.UDP_header
2308 hidnplayr 263
        shr     ecx, 2
264
        rep     movsd
265
        mov     ecx, [esp]
266
        and     ecx, 3
267
        rep     movsb
268
        pop     ecx edi
1159 hidnplayr 269
 
2310 hidnplayr 270
        pop     dword [edi + UDP_header.SourcePort]
1159 hidnplayr 271
 
1482 hidnplayr 272
; Checksum
2308 hidnplayr 273
        mov     esi, edi
2310 hidnplayr 274
        mov     [edi + UDP_header.Checksum], 0
2890 hidnplayr 275
        UDP_checksum (edi-4), (edi-8)                           ; FIXME: IPv4 packet could have options..
1159 hidnplayr 276
 
2980 hidnplayr 277
        DEBUGF  1,"UDP_output: sending with device %x\n", ebx
278
        call    [ebx + NET_DEVICE.transmit]
279
        test    eax, eax
280
        jnz     @f
2890 hidnplayr 281
        inc     [UDP_PACKETS_TX]                                ; FIXME: correct device?
2980 hidnplayr 282
       @@:
1206 hidnplayr 283
 
2308 hidnplayr 284
        ret
1529 hidnplayr 285
 
1206 hidnplayr 286
  .fail:
2308 hidnplayr 287
        DEBUGF  1,"UDP_output: failed\n"
288
        add     esp, 4+4+8
2390 hidnplayr 289
        or      eax, -1
2308 hidnplayr 290
        ret
1159 hidnplayr 291
 
292
 
1206 hidnplayr 293
 
1159 hidnplayr 294
;---------------------------------------------------------------------------
295
;
296
; UDP_API
297
;
298
; This function is called by system function 75
299
;
300
; IN:  subfunction number in bl
301
;      device number in bh
302
;      ecx, edx, .. depends on subfunction
303
;
304
; OUT:
305
;
306
;---------------------------------------------------------------------------
307
 
308
align 4
2614 hidnplayr 309
UDP_api:
1159 hidnplayr 310
 
2308 hidnplayr 311
        movzx   eax, bh
312
        shl     eax, 2
1159 hidnplayr 313
 
2308 hidnplayr 314
        test    bl, bl
315
        jz      .packets_tx     ; 0
316
        dec     bl
317
        jz      .packets_rx     ; 1
1159 hidnplayr 318
 
2614 hidnplayr 319
  .error:
2308 hidnplayr 320
        mov     eax, -1
321
        ret
1159 hidnplayr 322
 
2614 hidnplayr 323
  .packets_tx:
2311 hidnplayr 324
        mov     eax, [UDP_PACKETS_TX + eax]
2308 hidnplayr 325
        ret
1159 hidnplayr 326
 
2614 hidnplayr 327
  .packets_rx:
2311 hidnplayr 328
        mov     eax, [UDP_PACKETS_RX + eax]
2308 hidnplayr 329
        ret