Rev 7679 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 7679 | Rev 9049 | ||
---|---|---|---|
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
2 | ;; ;; |
3 | ;; Copyright (C) KolibriOS team 2012-2019. All rights reserved. ;; |
3 | ;; Copyright (C) KolibriOS team 2012-2021. 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 | ;; PPPoE.INC ;; |
6 | ;; PPPoE.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: 7679 $ |
17 | $Revision: 9049 $ |
18 | 18 | ||
19 | 19 | ||
20 | struct PPPoE_frame |
20 | struct PPPoE_frame |
21 | VersionAndType db ? |
21 | VersionAndType db ? |
22 | Code db ? |
22 | Code db ? |
23 | SessionID dw ? |
23 | SessionID dw ? |
24 | Length dw ? ; Length of payload, does NOT include the length PPPoE header. |
24 | Length dw ? ; Length of payload, does NOT include the length PPPoE header. |
25 | Payload rb 0 |
25 | Payload rb 0 |
26 | ends |
26 | ends |
27 | 27 | ||
28 | uglobal |
28 | uglobal |
29 | align 4 |
29 | align 4 |
30 | 30 | ||
31 | PPPoE_SID dw ? |
31 | PPPoE_SID dw ? |
32 | PPPoE_MAC dp ? |
32 | PPPoE_MAC dp ? |
33 | 33 | ||
34 | endg |
34 | endg |
35 | 35 | ||
36 | ;-----------------------------------------------------------------; |
36 | ;-----------------------------------------------------------------; |
37 | ; ; |
37 | ; ; |
38 | ; pppoe_init: Reset all pppoe variables ; |
38 | ; pppoe_init: Reset all pppoe variables ; |
39 | ; ; |
39 | ; ; |
40 | ;-----------------------------------------------------------------; |
40 | ;-----------------------------------------------------------------; |
41 | macro pppoe_init { |
41 | macro pppoe_init { |
42 | 42 | ||
43 | call pppoe_stop_connection |
43 | call pppoe_stop_connection |
44 | 44 | ||
45 | } |
45 | } |
46 | 46 | ||
47 | 47 | ||
48 | ;-----------------------------------------------------------------; |
48 | ;-----------------------------------------------------------------; |
49 | ; ; |
49 | ; ; |
50 | ; pppoe_discovery_input ; |
50 | ; pppoe_discovery_input ; |
51 | ; ; |
51 | ; ; |
52 | ; IN: [esp] = ptr to buffer ; |
52 | ; IN: [esp] = ptr to buffer ; |
53 | ; [esp+4] = size of buffer ; |
53 | ; [esp+4] = size of buffer ; |
54 | ; ebx = ptr to device struct ; |
54 | ; ebx = ptr to device struct ; |
55 | ; ecx = size of PPP packet ; |
55 | ; ecx = size of PPP packet ; |
56 | ; edx = ptr to PPP header ; |
56 | ; edx = ptr to PPP header ; |
57 | ; ; |
57 | ; ; |
58 | ; OUT: / ; |
58 | ; OUT: / ; |
59 | ; ; |
59 | ; ; |
60 | ;-----------------------------------------------------------------; |
60 | ;-----------------------------------------------------------------; |
61 | align 4 |
61 | align 4 |
62 | pppoe_discovery_input: |
62 | pppoe_discovery_input: |
63 | 63 | ||
64 | DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_discovery_input\n" |
64 | DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_discovery_input\n" |
65 | 65 | ||
66 | ; First, find open PPPoE socket |
66 | ; First, find open PPPoE socket |
67 | 67 | ||
68 | pusha |
68 | pusha |
69 | mov ecx, socket_mutex |
69 | mov ecx, socket_mutex |
70 | call mutex_lock |
70 | call mutex_lock |
71 | popa |
71 | popa |
72 | 72 | ||
73 | mov eax, net_sockets |
73 | mov eax, net_sockets |
74 | 74 | ||
75 | .next_socket: |
75 | .next_socket: |
76 | mov eax, [eax + SOCKET.NextPtr] |
76 | mov eax, [eax + SOCKET.NextPtr] |
77 | or eax, eax |
77 | or eax, eax |
78 | jz .dump |
78 | jz .dump |
79 | 79 | ||
80 | cmp [eax + SOCKET.Domain], AF_PPP |
80 | cmp [eax + SOCKET.Domain], AF_PPP |
81 | jne .next_socket |
81 | jne .next_socket |
82 | 82 | ||
83 | cmp [eax + SOCKET.Protocol], PPP_PROTO_ETHERNET |
83 | cmp [eax + SOCKET.Protocol], PPP_PROTO_ETHERNET |
84 | jne .next_socket |
84 | jne .next_socket |
85 | 85 | ||
86 | pusha |
86 | pusha |
87 | mov ecx, socket_mutex |
87 | mov ecx, socket_mutex |
88 | call mutex_unlock |
88 | call mutex_unlock |
89 | popa |
89 | popa |
90 | 90 | ||
91 | ; Now, send it to the this socket |
91 | ; Now, send it to the this socket |
92 | 92 | ||
93 | mov ecx, [esp + 4] |
93 | mov ecx, [esp + 4] |
94 | mov esi, [esp] |
94 | mov esi, [esp] |
95 | 95 | ||
96 | jmp socket_input |
96 | jmp socket_input |
97 | 97 | ||
98 | .dump: |
98 | .dump: |
99 | pusha |
99 | pusha |
100 | mov ecx, socket_mutex |
100 | mov ecx, socket_mutex |
101 | call mutex_unlock |
101 | call mutex_unlock |
102 | popa |
102 | popa |
103 | 103 | ||
104 | DEBUGF DEBUG_NETWORK_VERBOSE, 'PPPoE_discovery_input: dumping\n' |
104 | DEBUGF DEBUG_NETWORK_VERBOSE, 'PPPoE_discovery_input: dumping\n' |
105 | call net_buff_free |
105 | call net_buff_free |
106 | ret |
106 | ret |
107 | 107 | ||
108 | 108 | ||
109 | ;-----------------------------------------------------------------; |
109 | ;-----------------------------------------------------------------; |
110 | ; ; |
110 | ; ; |
111 | ; pppoe_discovery_output ; |
111 | ; pppoe_discovery_output ; |
112 | ; ; |
112 | ; ; |
113 | ; IN: eax = socket pointer ; |
113 | ; IN: eax = socket pointer ; |
114 | ; ecx = number of bytes to send ; |
114 | ; ecx = number of bytes to send ; |
115 | ; esi = pointer to data ; |
115 | ; esi = pointer to data ; |
116 | ; ; |
116 | ; ; |
117 | ;-----------------------------------------------------------------; |
117 | ;-----------------------------------------------------------------; |
118 | align 4 |
118 | align 4 |
119 | pppoe_discovery_output: |
119 | pppoe_discovery_output: |
120 | 120 | ||
121 | DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_discovery_output: socket=%x buffer=%x size=%d\n", eax, esi, ecx |
121 | DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_discovery_output: socket=%x buffer=%x size=%d\n", eax, esi, ecx |
122 | 122 | ||
123 | ; RFC2516: An entire PADI packet (including the PPPoE header) MUST NOT |
123 | ; RFC2516: An entire PADI packet (including the PPPoE header) MUST NOT |
124 | ; exceed 1484 octets. |
124 | ; exceed 1484 octets. |
125 | cmp ecx, 1484 + 14 |
125 | cmp ecx, 1484 + 14 |
126 | ja .bad |
126 | ja .bad |
127 | 127 | ||
128 | ; Check that device exists and is ethernet device |
128 | ; Check that device exists and is ethernet device |
129 | mov ebx, [eax + SOCKET.device] |
129 | mov ebx, [eax + SOCKET.device] |
130 | 130 | ||
131 | cmp ebx, NET_DEVICES_MAX |
131 | cmp ebx, NET_DEVICES_MAX |
132 | ja .bad |
132 | ja .bad |
133 | 133 | ||
134 | mov ebx, [net_device_list + 4*ebx] |
134 | mov ebx, [net_device_list + 4*ebx] |
135 | test ebx, ebx |
135 | test ebx, ebx |
136 | jz .bad |
136 | jz .bad |
137 | 137 | ||
138 | cmp [ebx + NET_DEVICE.device_type], NET_DEVICE_ETH |
138 | cmp [ebx + NET_DEVICE.device_type], NET_DEVICE_ETH |
139 | jne .bad |
139 | jne .bad |
140 | 140 | ||
141 | DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_discovery_output: device=%x\n", ebx |
141 | DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_discovery_output: device=%x\n", ebx |
142 | 142 | ||
143 | ; Create packet. |
143 | ; Create packet. |
144 | push ecx esi |
- | |
145 | ;;;; FIXME stdcall kernel_alloc, 1500 |
144 | stdcall net_buff_alloc, 1514 + NET_BUFF.data |
146 | pop esi ecx |
- | |
147 | test eax, eax |
145 | test eax, eax |
148 | jz .bad |
146 | jz .bad |
- | 147 | ||
- | 148 | ; Net buffer header |
|
- | 149 | mov [eax + NET_BUFF.type], NET_BUFF_ETH |
|
- | 150 | mov [eax + NET_BUFF.device], ebx |
|
- | 151 | mov [eax + NET_BUFF.offset], NET_BUFF.data |
|
- | 152 | ||
149 | 153 | ; Packet data |
|
150 | mov edx, ecx |
154 | mov edx, ecx |
151 | mov edi, eax |
155 | lea edi, [eax + NET_BUFF.data] |
- | 156 | rep movsb |
|
152 | rep movsb |
157 | |
153 | 158 | ; Packet size |
|
154 | cmp edx, 60 ; Min ETH size |
159 | cmp edx, 60 |
155 | ja @f |
160 | ja @f |
156 | mov edx, 60 |
161 | mov edx, 60 |
157 | @@: |
162 | @@: |
- | 163 | mov [eax + NET_BUFF.length], edx |
|
158 | - | ||
159 | push edx eax ; size and packet ptr for driver send proc |
- | |
160 | 164 | ||
161 | ; Overwrite source MAC and protocol type |
- | |
162 | lea edi, [eax + ETH_header.SrcMAC] |
165 | ; Overwrite ETH source MAC with our own |
- | 166 | lea esi, [ebx + ETH_DEVICE.mac] |
|
163 | lea esi, [ebx + ETH_DEVICE.mac] |
167 | lea edi, [eax + NET_BUFF.data + ETH_header.SrcMAC] |
164 | movsd |
168 | movsd |
- | 169 | movsw |
|
- | 170 | ||
165 | movsw |
171 | ; Allow only PPP_discovery, or LCP |
166 | cmp word[edi], ETHER_PROTO_PPP_SESSION ; Allow only PPP_discovery, or LCP |
172 | cmp word[edi], ETHER_PROTO_PPP_SESSION |
167 | je @f |
173 | je @f |
168 | mov ax, ETHER_PROTO_PPP_DISCOVERY |
- | |
169 | stosw |
174 | mov word[edi], ETHER_PROTO_PPP_DISCOVERY |
170 | @@: |
175 | @@: |
171 | 176 | ||
172 | ; And send the packet |
177 | ; And send the packet |
173 | call [ebx + NET_DEVICE.transmit] |
178 | stdcall [ebx + NET_DEVICE.transmit], eax |
174 | - | ||
175 | xor eax, eax |
- | |
176 | ret |
179 | ret |
177 | 180 | ||
178 | .bad: |
181 | .bad: |
179 | or eax, -1 |
182 | or eax, -1 |
180 | ret |
183 | ret |
181 | 184 | ||
182 | 185 | ||
183 | ;-----------------------------------------------------------------; |
186 | ;-----------------------------------------------------------------; |
184 | ; ; |
187 | ; ; |
185 | ; pppoe_session_input ; |
188 | ; pppoe_session_input ; |
186 | ; ; |
189 | ; ; |
187 | ; IN: [esp] = ptr to buffer ; |
190 | ; IN: [esp] = ptr to buffer ; |
188 | ; [esp+4] = size of buffer ; |
191 | ; [esp+4] = size of buffer ; |
189 | ; ebx = ptr to device struct ; |
192 | ; ebx = ptr to device struct ; |
190 | ; edx = ptr to PPP header ; |
193 | ; edx = ptr to PPP header ; |
191 | ; ecx = size of PPP packet ; |
194 | ; ecx = size of PPP packet ; |
192 | ; ; |
195 | ; ; |
193 | ; OUT: / ; |
196 | ; OUT: / ; |
194 | ; ; |
197 | ; ; |
195 | ;-----------------------------------------------------------------; |
198 | ;-----------------------------------------------------------------; |
196 | align 4 |
199 | align 4 |
197 | pppoe_session_input: |
200 | pppoe_session_input: |
198 | 201 | ||
199 | cmp [edx + PPPoE_frame.VersionAndType], 0x11 |
202 | cmp [edx + PPPoE_frame.VersionAndType], 0x11 |
200 | jne .dump |
203 | jne .dump |
201 | 204 | ||
202 | cmp [edx + PPPoE_frame.Code], 0x00 |
205 | cmp [edx + PPPoE_frame.Code], 0x00 |
203 | jne .dump |
206 | jne .dump |
204 | 207 | ||
205 | movzx ecx, [edx + PPPoE_frame.Length] |
208 | movzx ecx, [edx + PPPoE_frame.Length] |
206 | xchg cl, ch |
209 | xchg cl, ch |
207 | 210 | ||
208 | mov ax, [edx + PPPoE_frame.SessionID] |
211 | mov ax, [edx + PPPoE_frame.SessionID] |
209 | DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_input: session ID=%x, length=%u\n", ax, cx |
212 | DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_input: session ID=%x, length=%u\n", ax, cx |
210 | cmp ax, [PPPoE_SID] |
213 | cmp ax, [PPPoE_SID] |
211 | jne .dump |
214 | jne .dump |
212 | 215 | ||
213 | mov ax, word [edx + PPPoE_frame.Payload] |
216 | mov ax, word [edx + PPPoE_frame.Payload] |
214 | add edx, PPPoE_frame.Payload + 2 |
217 | add edx, PPPoE_frame.Payload + 2 |
215 | 218 | ||
216 | cmp ax, PPP_PROTO_IPv4 |
219 | cmp ax, PPP_PROTO_IPv4 |
217 | je ipv4_input |
220 | je ipv4_input |
218 | 221 | ||
219 | ; cmp ax, PPP_PROTO_IPv6 |
222 | ; cmp ax, PPP_PROTO_IPv6 |
220 | ; je ipv6_input |
223 | ; je ipv6_input |
221 | 224 | ||
222 | jmp pppoe_discovery_input ; Send LCP,CHAP,CBCP,... packets to the PPP dialer |
225 | jmp pppoe_discovery_input ; Send LCP,CHAP,CBCP,... packets to the PPP dialer |
223 | DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_input: Unknown protocol=%x\n", ax |
226 | DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_input: Unknown protocol=%x\n", ax |
224 | 227 | ||
225 | .dump: |
228 | .dump: |
226 | DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_input: dumping\n" |
229 | DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_input: dumping\n" |
227 | call net_buff_free |
230 | call net_buff_free |
228 | ret |
231 | ret |
229 | 232 | ||
230 | 233 | ||
231 | 234 | ||
232 | ;-----------------------------------------------------------------; |
235 | ;-----------------------------------------------------------------; |
233 | ; ; |
236 | ; ; |
234 | ; pppoe_output ; |
237 | ; pppoe_output ; |
235 | ; ; |
238 | ; ; |
236 | ; IN: ax = protocol ; |
239 | ; IN: ax = protocol ; |
237 | ; ebx = device ptr ; |
240 | ; ebx = device ptr ; |
238 | ; ecx = packet size ; |
241 | ; ecx = packet size ; |
239 | ; ; |
242 | ; ; |
240 | ; OUT: eax = buffer start ; |
243 | ; OUT: eax = buffer start ; |
241 | ; eax = 0 on error ; |
244 | ; eax = 0 on error ; |
242 | ; ebx = device ptr ; |
245 | ; ebx = device ptr ; |
243 | ; ecx = packet size ; |
246 | ; ecx = packet size ; |
244 | ; edx = size of complete buffer ; |
247 | ; edx = size of complete buffer ; |
245 | ; edi = start of PPP payload ; |
248 | ; edi = start of PPP payload ; |
246 | ; ; |
249 | ; ; |
247 | ;-----------------------------------------------------------------; |
250 | ;-----------------------------------------------------------------; |
248 | align 4 |
251 | align 4 |
249 | pppoe_output: |
252 | pppoe_output: |
250 | 253 | ||
251 | DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_output: size=%u device=%x\n", ecx, ebx |
254 | DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_output: size=%u device=%x\n", ecx, ebx |
252 | 255 | ||
253 | pushw ax |
256 | pushw ax |
254 | pushw [PPPoE_SID] |
257 | pushw [PPPoE_SID] |
255 | 258 | ||
256 | mov ax, ETHER_PROTO_PPP_SESSION |
259 | mov ax, ETHER_PROTO_PPP_SESSION |
257 | add ecx, PPPoE_frame.Payload + 2 |
260 | add ecx, PPPoE_frame.Payload + 2 |
258 | lea edx, [PPPoE_MAC] |
261 | lea edx, [PPPoE_MAC] |
259 | call eth_output |
262 | call eth_output |
260 | jz .eth_error |
263 | jz .eth_error |
261 | 264 | ||
262 | sub ecx, PPPoE_frame.Payload |
265 | sub ecx, PPPoE_frame.Payload |
263 | mov [edi + PPPoE_frame.VersionAndType], 0x11 |
266 | mov [edi + PPPoE_frame.VersionAndType], 0x11 |
264 | mov [edi + PPPoE_frame.Code], 0 |
267 | mov [edi + PPPoE_frame.Code], 0 |
265 | popw [edi + PPPoE_frame.SessionID] |
268 | popw [edi + PPPoE_frame.SessionID] |
266 | xchg cl, ch |
269 | xchg cl, ch |
267 | mov [edi + PPPoE_frame.Length], cx |
270 | mov [edi + PPPoE_frame.Length], cx |
268 | xchg cl, ch |
271 | xchg cl, ch |
269 | 272 | ||
270 | pop word [edi + PPPoE_frame.Payload] |
273 | pop word [edi + PPPoE_frame.Payload] |
271 | 274 | ||
272 | sub ecx, 2 |
275 | sub ecx, 2 |
273 | add edi, PPPoE_frame.Payload + 2 |
276 | add edi, PPPoE_frame.Payload + 2 |
274 | 277 | ||
275 | DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_output: success!\n" |
278 | DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_output: success!\n" |
276 | ret |
279 | ret |
277 | 280 | ||
278 | 281 | ||
279 | .eth_error: |
282 | .eth_error: |
280 | add esp, 4 |
283 | add esp, 4 |
281 | xor eax, eax |
284 | xor eax, eax |
282 | ret |
285 | ret |
283 | 286 | ||
284 | align 4 |
287 | align 4 |
285 | pppoe_start_connection: |
288 | pppoe_start_connection: |
286 | 289 | ||
287 | DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_start_connection: %x\n", cx |
290 | DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_start_connection: %x\n", cx |
288 | 291 | ||
289 | cmp [PPPoE_SID], 0 |
292 | cmp [PPPoE_SID], 0 |
290 | jne .fail |
293 | jne .fail |
291 | 294 | ||
292 | mov [PPPoE_SID], cx |
295 | mov [PPPoE_SID], cx |
293 | mov dword [PPPoE_MAC], edx |
296 | mov dword [PPPoE_MAC], edx |
294 | mov word [PPPoE_MAC + 4], si |
297 | mov word [PPPoE_MAC + 4], si |
295 | 298 | ||
296 | xor eax, eax |
299 | xor eax, eax |
297 | ret |
300 | ret |
298 | 301 | ||
299 | .fail: |
302 | .fail: |
300 | or eax, -1 |
303 | or eax, -1 |
301 | ret |
304 | ret |
302 | 305 | ||
303 | 306 | ||
304 | align 4 |
307 | align 4 |
305 | pppoe_stop_connection: |
308 | pppoe_stop_connection: |
306 | 309 | ||
307 | DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_stop_connection\n" |
310 | DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_stop_connection\n" |
308 | 311 | ||
309 | xor eax, eax |
312 | xor eax, eax |
310 | mov [PPPoE_SID], ax |
313 | mov [PPPoE_SID], ax |
311 | mov dword [PPPoE_MAC], eax |
314 | mov dword [PPPoE_MAC], eax |
312 | mov word [PPPoE_MAC + 4], ax |
315 | mov word [PPPoE_MAC + 4], ax |
313 | 316 | ||
314 | ret |
317 | ret |
315 | 318 | ||
316 | 319 | ||
317 | ;-----------------------------------------------------------------; |
320 | ;-----------------------------------------------------------------; |
318 | ; ; |
321 | ; ; |
319 | ; pppoe_api: Part of system function 76 ; |
322 | ; pppoe_api: Part of system function 76 ; |
320 | ; ; |
323 | ; ; |
321 | ; IN: subfunction number in bl ; |
324 | ; IN: subfunction number in bl ; |
322 | ; device number in bh ; |
325 | ; device number in bh ; |
323 | ; ecx, edx, .. depends on subfunction ; |
326 | ; ecx, edx, .. depends on subfunction ; |
324 | ; ; |
327 | ; ; |
325 | ; OUT: ; |
328 | ; OUT: ; |
326 | ; ; |
329 | ; ; |
327 | ;-----------------------------------------------------------------; |
330 | ;-----------------------------------------------------------------; |
328 | align 4 |
331 | align 4 |
329 | pppoe_api: |
332 | pppoe_api: |
330 | 333 | ||
331 | movzx eax, bh |
334 | movzx eax, bh |
332 | shl eax, 2 |
335 | shl eax, 2 |
333 | 336 | ||
334 | and ebx, 0xff |
337 | and ebx, 0xff |
335 | cmp ebx, .number |
338 | cmp ebx, .number |
336 | ja .error |
339 | ja .error |
337 | jmp dword [.table + 4*ebx] |
340 | jmp dword [.table + 4*ebx] |
338 | 341 | ||
339 | .table: |
342 | .table: |
340 | dd pppoe_start_connection ; 0 |
343 | dd pppoe_start_connection ; 0 |
341 | dd pppoe_stop_connection ; 1 |
344 | dd pppoe_stop_connection ; 1 |
342 | .number = ($ - .table) / 4 - 1 |
345 | .number = ($ - .table) / 4 - 1 |
343 | 346 | ||
344 | .error: |
347 | .error: |
345 | mov eax, -1 |
348 | mov eax, -1 |
346 | ret |
349 | ret |