Subversion Repositories Kolibri OS

Rev

Rev 3711 | Rev 3861 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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