Subversion Repositories Kolibri OS

Rev

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

Rev 1519 Rev 1529
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved.    ;;
3
;; Copyright (C) KolibriOS team 2004-2010. 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: 1519 $
17
$Revision: 1529 $
18
 
18
 
19
 
19
 
20
struct	UDP_Packet
20
struct	UDP_Packet
21
	.SourcePort		dw  ?
21
	.SourcePort		dw  ?
22
	.DestinationPort	dw  ?
22
	.DestinationPort	dw  ?
23
	.Length 		dw  ?  ; Length of (UDP Header + Data)
23
	.Length 		dw  ?  ; Length of (UDP Header + Data)
24
	.Checksum		dw  ?
24
	.Checksum		dw  ?
25
	.Data:
25
	.Data:
26
 
26
 
27
ends
27
ends
28
 
28
 
29
 
29
 
30
align 4
30
align 4
31
uglobal
31
uglobal
32
	UDP_PACKETS_TX		rd  MAX_IP
32
	UDP_PACKETS_TX		rd  MAX_IP
33
	UDP_PACKETS_RX		rd  MAX_IP
33
	UDP_PACKETS_RX		rd  MAX_IP
34
endg
34
endg
35
 
35
 
36
 
36
 
37
;-----------------------------------------------------------------
37
;-----------------------------------------------------------------
38
;
38
;
39
; UDP_init
39
; UDP_init
40
;
40
;
41
;  This function resets all UDP variables
41
;  This function resets all UDP variables
42
;
42
;
43
;  IN:  /
-
 
44
;  OUT: /
-
 
45
;
-
 
46
;-----------------------------------------------------------------
43
;-----------------------------------------------------------------
47
align 4
-
 
48
UDP_init:
44
macro	UDP_init {
49
 
45
 
50
	xor	eax, eax
46
	xor	eax, eax
51
	mov	edi, UDP_PACKETS_TX
47
	mov	edi, UDP_PACKETS_TX
52
	mov	ecx, 2*MAX_IP
48
	mov	ecx, 2*MAX_IP
53
	rep	stosd
49
	rep	stosd
-
 
50
}
-
 
51
 
-
 
52
 
-
 
53
 
-
 
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+4]
-
 
61
	adc	dh, [IP1+0+4]
-
 
62
	adc	dl, [IP1+3+4]
-
 
63
	adc	dh, [IP1+2+4]
-
 
64
 
-
 
65
	adc	dl, [IP2+1+8]
-
 
66
	adc	dh, [IP2+0+8]
-
 
67
	adc	dl, [IP2+3+8]
-
 
68
	adc	dh, [IP2+2+8]
-
 
69
 
-
 
70
	adc	dl, cl ; byte[esi+UDP_Packet.Length+1]
-
 
71
	adc	dh, ch ; byte[esi+UDP_Packet.Length+0]
-
 
72
 
-
 
73
; Done with pseudoheader, now do real header
-
 
74
	adc	dl, byte[esi+UDP_Packet.SourcePort+1]
-
 
75
	adc	dh, byte[esi+UDP_Packet.SourcePort+0]
-
 
76
 
-
 
77
	adc	dl, byte[esi+UDP_Packet.DestinationPort+1]
-
 
78
	adc	dh, byte[esi+UDP_Packet.DestinationPort+0]
-
 
79
 
-
 
80
	adc	dl, byte[esi+UDP_Packet.Length+1]
-
 
81
	adc	dh, byte[esi+UDP_Packet.Length+0]
-
 
82
 
-
 
83
	adc	edx, 0
-
 
84
 
-
 
85
; Done with header, now do data
-
 
86
	push	esi
-
 
87
	movzx	ecx, [esi+UDP_Packet.Length]
-
 
88
	rol	cx , 8
-
 
89
	sub	cx , UDP_Packet.Data
-
 
90
	add	esi, UDP_Packet.Data
-
 
91
 
-
 
92
	call	checksum_1
54
 
93
	call	checksum_2
-
 
94
	pop	esi
-
 
95
 
-
 
96
	add	[esi+UDP_Packet.Checksum], dx	; this final instruction will set or clear ZF :)
-
 
97
 
55
	ret
98
}
56
 
99
 
57
 
100
 
58
;-----------------------------------------------------------------
101
;-----------------------------------------------------------------
59
;
102
;
60
; UDP_input:
103
; UDP_input:
61
;
104
;
62
;  Called by IPv4_input,
105
;  Called by IPv4_input,
63
;  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.
64
;
107
;
65
;  IN:  Pointer to buffer in [esp]
108
;  IN:   [esp]  = Pointer to buffer
66
;       size of buffer in [esp+4]
109
;       [esp+4] = size of buffer
67
;       pointer to device struct in ebx
110
;       ebx = ptr to device struct
68
;       UDP Packet size in ecx
111
;       ecx = UDP Packet size
69
;       pointer to UDP Packet in edx
112
;       edx = ptr to UDP header
70
;
113
;
71
;       esi = ipv4 source address
114
;       esi = ipv4 source address
72
;       edi = ipv4 dest   address
115
;       edi = ipv4 dest   address
73
;
116
;
74
;  OUT: /
117
;  OUT: /
75
;
118
;
76
;-----------------------------------------------------------------
119
;-----------------------------------------------------------------
77
align 4
120
align 4
78
UDP_input:
121
UDP_input:
79
 
122
 
80
	DEBUGF	1,"UDP_input, size:%u\n", ecx
123
	DEBUGF	1,"UDP_input, size:%u\n", ecx
81
 
124
 
82
; First validate, checksum:
125
; First validate, checksum:
83
	cmp	[edx + UDP_Packet.Checksum], 0
126
	neg	[esi+UDP_Packet.Checksum]	; substract chechksum from 0
84
	jz	.no_checksum
127
	jz	.no_checksum			; if checksum is zero, it is considered valid and we continue processing
85
 
-
 
86
	xchg	edi, esi	; save ipv4 source address to edi so we can use it later
128
						; otherwise, we will re-calculate the checksum and add it to this value, thus creating 0 when it is correct
87
 
129
 
-
 
130
	push	edx
88
	push	edx
131
	push	edi
89
	push	esi edi
132
	push	esi
-
 
133
	mov	esi, edx
-
 
134
	UDP_checksum (esp), (esp+4)
90
	mov	esi, edx
135
	pop	edi
91
	call	UDP_checksum	; this destroys edx, ecx and esi (but not edi...)
136
	pop	esi	; we dont need it, but it is smaller then add esp, 4
92
	pop	edx
-
 
93
 
-
 
94
	cmp	[edx + UDP_Packet.Checksum], 0
137
	pop	edx
95
	jnz	.checksum_mismatch
138
	jnz	.checksum_mismatch
96
 
139
 
97
  .no_checksum:
140
  .no_checksum:
98
	DEBUGF	1,"UDP Checksum is correct\n"
141
	DEBUGF	1,"UDP Checksum is correct\n"
99
 
142
 
100
	; Look for a socket where
143
	; Look for a socket where
101
	; IP Packet UDP Destination Port = local Port
144
	; IP Packet UDP Destination Port = local Port
102
	; IP Packet SA = Remote IP
145
	; IP Packet SA = Remote IP
103
 
146
 
104
	mov	eax, net_sockets
147
	mov	eax, net_sockets
105
  .try_more:
148
  .try_more:
106
	mov	si , [edx + UDP_Packet.DestinationPort]   ; get the local port from the IP Packet's UDP header
149
	mov	si , [edx + UDP_Packet.DestinationPort]   ; get the local port from the IP Packet's UDP header
107
	rol	si , 8
150
	rol	si , 8
108
  .next_socket:
151
  .next_socket:
109
	mov	eax, [eax + SOCKET.NextPtr]
152
	mov	eax, [eax + SOCKET.NextPtr]
110
	or	eax, eax
153
	or	eax, eax
111
	jz	.dump
154
	jz	.dump
112
	cmp	[eax + SOCKET.Domain], AF_INET4
155
	cmp	[eax + SOCKET.Domain], AF_INET4
113
	jne	.next_socket
156
	jne	.next_socket
114
	cmp	[eax + SOCKET.Type], IP_PROTO_UDP
157
	cmp	[eax + SOCKET.Type], IP_PROTO_UDP
115
	jne	.next_socket
158
	jne	.next_socket
116
	cmp	[eax + UDP_SOCKET.LocalPort], si
159
	cmp	[eax + UDP_SOCKET.LocalPort], si
117
	jne	.next_socket
160
	jne	.next_socket
118
 
161
 
119
	DEBUGF	1,"using socket: %x\n", eax
162
	DEBUGF	1,"using socket: %x\n", eax
120
 
163
 
121
	;;; TODO: when packet is processed, check more sockets!
164
	;;; TODO: when packet is processed, check more sockets!
122
 
165
 
123
	cmp	[eax + IP_SOCKET.RemoteIP], 0xffffffff
166
	cmp	[eax + IP_SOCKET.RemoteIP], 0xffffffff
124
	je	@f
167
	je	@f
125
	cmp	[eax + IP_SOCKET.RemoteIP], edi 	; edi is the packets source address
168
	cmp	[eax + IP_SOCKET.RemoteIP], edi 	; edi is the packets source address
126
	jne	.try_more
169
	jne	.try_more
127
       @@:
170
       @@:
128
 
171
 
129
	cmp	[eax + UDP_SOCKET.firstpacket], 0
172
	cmp	[eax + UDP_SOCKET.firstpacket], 0
130
	jz	.updateport
173
	jz	.updateport
131
 
174
 
132
	mov	si, [edx + UDP_Packet.SourcePort]
175
	mov	si, [edx + UDP_Packet.SourcePort]
133
	rol	si, 8
176
	rol	si, 8
134
	cmp	[eax + UDP_SOCKET.RemotePort], si
177
	cmp	[eax + UDP_SOCKET.RemotePort], si
135
	jne	.dump
178
	jne	.dump
136
 
179
 
137
	push	ebx
180
	push	ebx
138
	lea	ebx, [eax + SOCKET.lock]
181
	lea	ebx, [eax + SOCKET.lock]
139
	call	wait_mutex
182
	call	wait_mutex
140
	pop	ebx
183
	pop	ebx
141
 
184
 
142
  .updatesock:
185
  .updatesock:
143
	inc	[UDP_PACKETS_RX]
186
	inc	[UDP_PACKETS_RX]
144
	DEBUGF	1,"Found valid UDP packet for socket %x\n", eax
187
	DEBUGF	1,"Found valid UDP packet for socket %x\n", eax
145
	lea	esi, [edx + UDP_Packet.Data]
188
	lea	esi, [edx + UDP_Packet.Data]
146
	movzx	ecx, [edx + UDP_Packet.Length]
189
	movzx	ecx, [edx + UDP_Packet.Length]
147
	rol	cx , 8
190
	rol	cx , 8
148
	sub	cx , UDP_Packet.Data
191
	sub	cx , UDP_Packet.Data
149
 
192
 
150
	jmp	SOCKET_input
193
	jmp	SOCKET_input
151
 
194
 
152
  .updateport:
195
  .updateport:
153
	push	ebx
196
	push	ebx
154
	lea	ebx, [eax + SOCKET.lock]
197
	lea	ebx, [eax + SOCKET.lock]
155
	call	wait_mutex
198
	call	wait_mutex
156
	pop	ebx
199
	pop	ebx
157
 
200
 
158
	mov	si, [edx + UDP_Packet.SourcePort]
201
	mov	si, [edx + UDP_Packet.SourcePort]
159
	rol	si, 8
202
	rol	si, 8
160
	DEBUGF	1,"Changing remote port to: %u\n", si
203
	DEBUGF	1,"Changing remote port to: %u\n", si
161
	mov	[eax + UDP_SOCKET.RemotePort], si
204
	mov	[eax + UDP_SOCKET.RemotePort], si
162
	inc	[eax + UDP_SOCKET.firstpacket]
205
	inc	[eax + UDP_SOCKET.firstpacket]
163
 
206
 
164
	jmp	.updatesock
207
	jmp	.updatesock
165
 
208
 
166
 
209
 
167
  .checksum_mismatch:
210
  .checksum_mismatch:
168
 
211
 
169
	DEBUGF	2,"UDP_Handler - checksum mismatch\n"
212
	DEBUGF	2,"UDP_Handler - checksum mismatch\n"
170
 
-
 
171
;        mov     esi, edx
-
 
172
;       @@:                         ;
-
 
173
;        lodsb                      ;
-
 
174
;        DEBUGF  2,"%x ", eax:2     ;
-
 
175
;        loop    @r                 ;
-
 
176
 
213
 
177
  .dump:
214
  .dump:
178
	call	kernel_free
215
	call	kernel_free
179
	add	esp, 4 ; pop (balance stack)
216
	add	esp, 4 ; pop (balance stack)
180
	DEBUGF	2,"UDP_Handler - dumping\n"
217
	DEBUGF	2,"UDP_Handler - dumping\n"
181
 
218
 
182
	ret
219
	ret
183
 
220
 
184
 
221
 
185
 
222
 
186
 
223
 
187
;-----------------------------------------------------------------
224
;-----------------------------------------------------------------
188
;
225
;
189
; UDP_output
226
; UDP_output
190
;
227
;
191
; IN: eax = socket pointer
228
; IN: eax = socket pointer
192
;     ecx = number of bytes to send
229
;     ecx = number of bytes to send
193
;     esi = pointer to data
230
;     esi = pointer to data
194
;
231
;
195
;-----------------------------------------------------------------
232
;-----------------------------------------------------------------
196
 
233
 
197
align 4
234
align 4
198
UDP_output:
235
UDP_output:
199
 
236
 
200
	DEBUGF	1,"UDP_output: socket:%x, bytes: %u, data ptr: %x\n", eax, ecx, esi
237
	DEBUGF	1,"UDP_output: socket:%x, bytes: %u, data ptr: %x\n", eax, ecx, esi
201
 
238
 
202
	mov	dx, [eax + UDP_SOCKET.RemotePort]
239
	mov	dx, [eax + UDP_SOCKET.RemotePort]
203
	DEBUGF	1,"remote port: %u\n", dx
240
	DEBUGF	1,"remote port: %u\n", dx
204
	rol	dx, 8
241
	rol	dx, 8
205
	rol	edx, 16
242
	rol	edx, 16
206
	mov	dx, [eax + UDP_SOCKET.LocalPort]
243
	mov	dx, [eax + UDP_SOCKET.LocalPort]
207
	DEBUGF	1,"local port: %u\n", dx
244
	DEBUGF	1,"local port: %u\n", dx
208
	rol	dx, 8
245
	rol	dx, 8
209
 
-
 
210
 
246
 
211
	mov	ebx, [eax + IP_SOCKET.LocalIP]
247
	mov	ebx, [eax + IP_SOCKET.LocalIP]
212
	mov	eax, [eax + IP_SOCKET.RemoteIP]
248
	mov	eax, [eax + IP_SOCKET.RemoteIP]
213
 
249
 
214
	mov	di , IP_PROTO_UDP
250
	mov	di, IP_PROTO_UDP shl 8 + 128
215
	sub	esp, 8						; Data ptr and data size will be placed here
251
	sub	esp, 8						; Data ptr and data size will be placed here
216
	add	ecx, UDP_Packet.Data
252
	add	ecx, UDP_Packet.Data
217
 
253
 
218
;;; TODO: fragment id
254
;;; TODO: fragment id
219
 
-
 
220
	push	edx esi
255
	push	edx esi
221
	call	IPv4_create_packet
256
	call	IPv4_output
222
	jz	.fail
257
	jz	.fail
223
 
258
 
224
	mov	[esp + 8], eax					; pointer to buffer start
259
	mov	[esp + 8], eax					; pointer to buffer start
225
	mov	[esp + 8 + 4], edx				; buffer size
260
	mov	[esp + 8 + 4], edx				; buffer size
226
 
-
 
227
	rol	cx, 8
261
 
228
	mov	[edi + UDP_Packet.Length], cx
262
	mov	[edi + UDP_Packet.Length], cx
229
	ror	cx, 8
263
	rol	[edi + UDP_Packet.Length], 8
230
 
264
 
231
	pop	esi
265
	pop	esi
232
	push	edi ecx
266
	push	edi ecx
233
	sub	ecx, UDP_Packet.Data
267
	sub	ecx, UDP_Packet.Data
234
	add	edi, UDP_Packet.Data
268
	add	edi, UDP_Packet.Data
235
	shr	ecx, 2
269
	shr	ecx, 2
236
	rep	movsd
270
	rep	movsd
237
	mov	ecx, [esp]
271
	mov	ecx, [esp]
238
	and	ecx, 3
272
	and	ecx, 3
239
	rep	movsb
273
	rep	movsb
240
	pop	ecx edi
274
	pop	ecx edi
241
 
275
 
242
	pop	dword [edi + UDP_Packet.SourcePort]
276
	pop	dword [edi + UDP_Packet.SourcePort]
243
	mov	[edi + UDP_Packet.Checksum], 0			; set it to zero, to calculate checksum
-
 
244
 
277
 
245
; Checksum
278
; Checksum
246
	mov	esi, edi
279
	mov	esi, edi
-
 
280
	mov	[edi + UDP_Packet.Checksum], 0
247
	pushd	[edi-4] ; destination address                   ; TODO: fix this, IPv4 packet could have options..
281
	UDP_checksum (edi-4), (edi-8)				; TODO: fix this, IPv4 packet could have options..
248
	pushd	[edi-8] ; source address
-
 
249
	call	UDP_checksum
-
 
250
 
282
 
251
	inc	[UDP_PACKETS_TX]
283
	inc	[UDP_PACKETS_TX]
252
 
284
 
253
	DEBUGF	1,"Sending UDP Packet to device %x\n", ebx
285
	DEBUGF	1,"Sending UDP Packet to device %x\n", ebx
254
 
286
 
255
	call	[ebx + NET_DEVICE.transmit]
287
	call	[ebx + NET_DEVICE.transmit]
256
	ret
288
	ret
-
 
289
 
257
  .fail:
290
  .fail:
-
 
291
	DEBUGF	1,"UDP_output: failed\n"
258
	add	esp, 8+8
292
	add	esp, 4+4+8
-
 
293
	xor	eax, eax
259
	ret
294
	ret
260
 
-
 
261
 
-
 
262
 
-
 
263
 
-
 
264
;-----------------------------------------------------------------
-
 
265
;
-
 
266
; UDP_checksum
-
 
267
;
-
 
268
; This is the fast procedure to create or check a UDP header
-
 
269
;  - To create a new checksum, the checksum field must be set to 0 before computation
-
 
270
;  - To check an existing checksum, leave the checksum as is,
-
 
271
;     and it will be 0 after this procedure, if it was correct
-
 
272
;
-
 
273
;  IN:  push source ip
-
 
274
;       push dest ip
-
 
275
;       esi = packet ptr
-
 
276
;
-
 
277
;  OUT: checksum is filled in in packet! (but also in dx)
-
 
278
;
-
 
279
;-----------------------------------------------------------------
-
 
280
 
-
 
281
align 4
-
 
282
UDP_checksum:
-
 
283
 
-
 
284
; Pseudoheader
-
 
285
	mov	edx, IP_PROTO_UDP		; NO shl 8 here ! (it took me ages to figure this one out)
-
 
286
 
-
 
287
	add	dl, [esp+1+4]
-
 
288
	adc	dh, [esp+0+4]
-
 
289
	adc	dl, [esp+3+4]
-
 
290
	adc	dh, [esp+2+4]
-
 
291
 
-
 
292
	adc	dl, [esp+1+8]
-
 
293
	adc	dh, [esp+0+8]
-
 
294
	adc	dl, [esp+3+8]
-
 
295
	adc	dh, [esp+2+8]
-
 
296
 
-
 
297
 
-
 
298
	adc	dl, cl ; byte[esi+UDP_Packet.Length+1]
-
 
299
	adc	dh, ch ; byte[esi+UDP_Packet.Length+0]
-
 
300
 
-
 
301
; Done with pseudoheader, now do real header
-
 
302
	adc	dl, byte[esi+UDP_Packet.SourcePort+1]
-
 
303
	adc	dh, byte[esi+UDP_Packet.SourcePort+0]
-
 
304
 
-
 
305
	adc	dl, byte[esi+UDP_Packet.DestinationPort+1]
-
 
306
	adc	dh, byte[esi+UDP_Packet.DestinationPort+0]
-
 
307
 
-
 
308
	adc	dl, byte[esi+UDP_Packet.Length+1]
-
 
309
	adc	dh, byte[esi+UDP_Packet.Length+0]
-
 
310
 
-
 
311
	adc	edx, 0
-
 
312
 
-
 
313
; Done with header, now do data
-
 
314
	push	esi
-
 
315
	movzx	ecx, [esi+UDP_Packet.Length]
-
 
316
	rol	cx , 8
-
 
317
	sub	cx , UDP_Packet.Data
-
 
318
	add	esi, UDP_Packet.Data
-
 
319
 
-
 
320
	call	checksum_1
-
 
321
	call	checksum_2
-
 
322
	pop	esi
-
 
323
 
-
 
324
	neg	[esi+UDP_Packet.Checksum]	    ; zero will stay zero so we just get the checksum
-
 
325
	add	[esi+UDP_Packet.Checksum], dx	    ;  , else we will get (new checksum - old checksum) in the end, wich should be 0 :)
-
 
326
 
-
 
327
	ret	8
-
 
328
 
-
 
329
 
295
 
330
 
296
 
331
 
297
 
332
;---------------------------------------------------------------------------
298
;---------------------------------------------------------------------------
333
;
299
;
334
; UDP_API
300
; UDP_API
335
;
301
;
336
; This function is called by system function 75
302
; This function is called by system function 75
337
;
303
;
338
; IN:  subfunction number in bl
304
; IN:  subfunction number in bl
339
;      device number in bh
305
;      device number in bh
340
;      ecx, edx, .. depends on subfunction
306
;      ecx, edx, .. depends on subfunction
341
;
307
;
342
; OUT:
308
; OUT:
343
;
309
;
344
;---------------------------------------------------------------------------
310
;---------------------------------------------------------------------------
345
 
311
 
346
align 4
312
align 4
347
UDP_API:
313
UDP_API:
348
 
314
 
349
	movzx	eax, bh
315
	movzx	eax, bh
350
	shl	eax, 2
316
	shl	eax, 2
351
 
317
 
352
	test	bl, bl
318
	test	bl, bl
353
	jz	.packets_tx	; 0
319
	jz	.packets_tx	; 0
354
	dec	bl
320
	dec	bl
355
	jz	.packets_rx	; 1
321
	jz	.packets_rx	; 1
356
 
322
 
357
.error:
323
.error:
358
	mov	eax, -1
324
	mov	eax, -1
359
	ret
325
	ret
360
 
326
 
361
.packets_tx:
327
.packets_tx:
362
	add	eax, UDP_PACKETS_TX
328
	add	eax, UDP_PACKETS_TX
363
	mov	eax, [eax]
329
	mov	eax, [eax]
364
	ret
330
	ret
365
 
331
 
366
.packets_rx:
332
.packets_rx:
367
	add	eax, UDP_PACKETS_RX
333
	add	eax, UDP_PACKETS_RX
368
	mov	eax, [eax]
334
	mov	eax, [eax]
369
	ret
335
	ret