Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2614 | hidnplayr | 1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
||
3 | ;; Copyright (C) KolibriOS team 2009-2012. All rights reserved. ;; |
||
4 | ;; Distributed under terms of the GNU General Public License ;; |
||
5 | ;; ;; |
||
6 | ;; Clevermouse & hidnplayr ;; |
||
7 | ;; ;; |
||
8 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||
9 | |||
10 | |||
11 | struct PPPoE_header |
||
12 | |||
13 | VersionAndType db ? |
||
14 | Code db ? |
||
15 | SessionID dw ? |
||
16 | Length dw ? ; Length of payload, does NOT include the length PPPoE header. |
||
17 | |||
18 | ends |
||
19 | |||
20 | struct PPPoE_connection |
||
21 | |||
22 | next dd ? ; pointer to next connection |
||
23 | prev dd ? ; pointer to previous connection |
||
24 | |||
25 | pid dd ? ; identifier of base application |
||
26 | |||
27 | datalen dd ? ; length of received data |
||
28 | recvbuf rb 1500 ; buffer for received data |
||
29 | sendbuf rb 1500 ; buffer for data to send |
||
30 | |||
31 | ends |
||
32 | |||
33 | iglobal |
||
34 | align 4 |
||
35 | PPPoE.head dd PPPoE.head |
||
36 | PPPoE.tail dd PPPoE.head |
||
37 | endg |
||
38 | |||
39 | uglobal |
||
40 | PPPoE.cur_receiver dd ? |
||
41 | PPPoE.cur_receiver_ptr dd ? |
||
42 | PPPoE.cur_receiver_len dd ? |
||
43 | endg |
||
44 | |||
45 | |||
46 | ; Allocates internal structure for future PPPoE actions. |
||
47 | align 4 |
||
48 | PPPoE_alloc_connection: |
||
49 | |||
50 | ; 1. Allocate memory in the kernel area. |
||
51 | stdcall kernel_alloc, sizeof.PPPoE_connection |
||
52 | |||
53 | ; 1a. If memory allocation failed, return NULL. |
||
54 | test eax, eax |
||
55 | jz .nothing |
||
56 | |||
57 | ; 2. Copy PID of caller to the structure. |
||
58 | mov edx, [CURRENT_TASK] |
||
59 | mov [eax + PPPoE_connection.pid], edx |
||
60 | |||
61 | ; 3. Insert the structure to the list of all connections. |
||
62 | mov [eax + PPPoE_connection.next], PPPoE.head |
||
63 | mov edx, [PPPoE.tail] |
||
64 | mov [eax + PPPoE_connection.prev], edx |
||
65 | mov [edx + PPPoE_connection.next], eax |
||
66 | mov [PPPoE.tail], eax |
||
67 | |||
68 | .nothing: |
||
69 | ret |
||
70 | |||
71 | |||
72 | align 4 |
||
73 | PPPoE_free_connection: |
||
74 | |||
75 | ; 1. Check that the caller is the owner of this connection. |
||
76 | mov eax, [CURRENT_TASK] |
||
77 | cmp [ebx+PPPoE_connection.pid], eax |
||
78 | jnz .nothing |
||
79 | |||
80 | ; 2. Delete the structure from the list of all connections. |
||
81 | mov eax, [ebx+PPPoE_connection.next] |
||
82 | mov edx, [ebx+PPPoE_connection.prev] |
||
83 | mov [eax+PPPoE_connection.prev], edx |
||
84 | mov [edx+PPPoE_connection.next], eax |
||
85 | |||
86 | ; 3. Free the memory. |
||
87 | stdcall kernel_free, ebx |
||
88 | |||
89 | .nothing: |
||
90 | ret |
||
91 | |||
92 | |||
93 | ; Send PADI packet |
||
94 | |||
95 | ; ebx (ecx in app) = size of buffer for PPPoE offers, must be at least 1514 |
||
96 | ; ecx (edx in app) = size of tags, 0 means "use default" |
||
97 | ; edx (esi in app) = pointer to buffer for PPPoE offers |
||
98 | ; esi (edi in app) = pointer to tags, ignored if 'size of tags' == 0 |
||
99 | align 4 |
||
100 | PPPoE_send_init: |
||
101 | |||
102 | ; 1. Check length. |
||
103 | cmp ebi, 1514 |
||
104 | jb .bad |
||
105 | |||
106 | ; RFC2516: An entire PADI packet (including the PPPoE header) MUST NOT |
||
107 | ; exceed 1484 octets. |
||
108 | ; PPPoE header is 6 bytes long, so maximum length of tags is 1478. |
||
109 | cmp ecx, 1478 |
||
110 | ja .bad |
||
111 | |||
112 | ; 2. Check that no one listen for offers. |
||
113 | cmp [PPPoE.cur_receiver], 0 |
||
114 | jnz .bad |
||
115 | |||
116 | ; 3. Remember PID and data pointer of current listener. |
||
117 | push [CURRENT_TASK] |
||
118 | pop [PPPoE.cur_receiver] |
||
119 | mov [PPPoE.cur_receiver_ptr], edx |
||
120 | mov [PPPoE.cur_receiver_len], ebx |
||
121 | and dword [edx], 0 ; no offers yet |
||
122 | |||
123 | ; 4. Create packet. |
||
124 | test ecx, ecx |
||
125 | jnz @f |
||
126 | mov esi, .default_payload |
||
127 | mov ecx, .default_payload_length |
||
128 | @@: |
||
129 | |||
130 | mov edx, [NET_DRV_LIST] ;;;; FIXME |
||
131 | lea eax, [ebx + ETH_DEVICE.mac] ; Source Address |
||
132 | mov edx, ETH_BROADCAST ; Destination Address |
||
133 | add ecx, sizeof.PPPoE_header ; Data size |
||
134 | mov di, ETHER_PPP_DISCOVERY ; Protocol |
||
135 | call ETH_output |
||
136 | jz .eth_error |
||
137 | |||
138 | push edx eax |
||
139 | |||
140 | ; 4b. Set ver=1, type=1 (=> first byte 0x11), code=9 (PADI packet), session=0 |
||
141 | mov dword [edi], (0x09 shl 8) + 0x11 |
||
142 | |||
143 | ; 4c. Set payload length. |
||
144 | mov [edi+4], ch |
||
145 | mov [edi+5], cl |
||
146 | |||
147 | ; 4e. Copy given tags. |
||
148 | rep movsb |
||
149 | |||
150 | ; 5. Send packet. |
||
151 | call [ebx + NET_DEVICE.transmit] |
||
152 | ; 6. Return. |
||
153 | xor eax, eax |
||
154 | ret |
||
155 | |||
156 | .bad: |
||
157 | or eax, -1 |
||
158 | ret |
||
159 | |||
160 | .default_payload: |
||
161 | ; Service-Name tag with zero length |
||
162 | dw 0x0101, 0x0000 |
||
163 | .default_payload_length = $ - .default_payload |
||
164 | |||
165 | |||
166 | ; Stop receiving PADO packets |
||
167 | align 4 |
||
168 | PPPoE_stop_offers: |
||
169 | |||
170 | ; Only the listener can stop listen. ;;; TODO: make sure this function is called when process gets terminated |
||
171 | mov eax, [CURRENT_TASK] |
||
172 | cmp [PPPoE.cur_receiver], eax |
||
173 | jnz .bad |
||
174 | xor eax, eax |
||
175 | mov [PPPoE.cur_receiver_ptr], eax |
||
176 | mov [PPPoE.cur_receiver], eax |
||
177 | ret |
||
178 | |||
179 | .bad: |
||
180 | or eax, -1 |
||
181 | ret |
||
182 | |||
183 | ; Send PPPoE data in Discovery stage |
||
184 | align 4 |
||
185 | PPPoE_send_discovery: |
||
186 | ret |
||
187 | |||
188 | ; Receive PPPoE data in Discovery stage |
||
189 | align 4 |
||
190 | PPPoE_receive_discovery: |
||
191 | ret |
||
192 | |||
193 | |||
194 | |||
195 | ;----------------------------------------------------------------- |
||
196 | ; |
||
197 | ; PPPoE discovery input |
||
198 | ; |
||
199 | ; Handler of received Ethernet packet with type = Discovery |
||
200 | ; |
||
201 | ; |
||
202 | ; IN: Pointer to buffer in [esp] |
||
203 | ; size of buffer in [esp+4] |
||
204 | ; pointer to device struct in ebx |
||
205 | ; pointer to PPP header in edx |
||
206 | ; size of PPP packet in ecx |
||
207 | ; OUT: / |
||
208 | ; |
||
209 | ;----------------------------------------------------------------- |
||
210 | align 4 |
||
211 | PPPoE_discovery_input: |
||
212 | |||
213 | ; 1. Minimum 6 bytes for PPPoE header. |
||
214 | cmp ecx, sizeof.PPPoE_header |
||
215 | jb .bad |
||
216 | |||
217 | ; 1. Ignore packets with ver<>1 and/or type<>1. |
||
218 | cmp [edx + PPPoE_header.VersionAndType], 0x11 |
||
219 | jnz .bad |
||
220 | |||
221 | ; 2. Code must be either 7 for Offer, |
||
222 | ; or 0x65 for Session-Confirmation, or 0xa7 for Terminate. |
||
223 | ; Because only Initiation/Offers are supported, we expect only value 7. |
||
224 | cmp [edx + PPPoE_header.Code], 7 |
||
225 | jnz .bad |
||
226 | |||
227 | ; 3. Session ID must be zero for Offers. |
||
228 | cmp [edx + PPPoE_header.SessionID], 0 |
||
229 | jnz .bad |
||
230 | |||
231 | ; 4. Payload length |
||
232 | rol [edx + PPPoE_header.Length], 8 ; Convert INET byte order to intel |
||
233 | |||
234 | ; 5. Ignore packet if nobody is listening. |
||
235 | cmp [PPPoE.cur_receiver], 0 |
||
236 | jz .bad |
||
237 | |||
238 | ; 6. Good, now copy the received packet to the buffer of listener. |
||
239 | |||
240 | ;;; TODO |
||
241 | |||
242 | .bad: |
||
243 | DEBUGF 1,'K : PPPoE - dumped\n' |
||
244 | call kernel_free |
||
245 | add esp, 4 ; pop (balance stack) |
||
246 | ret |
||
247 | |||
248 | |||
249 | |||
250 | |||
251 | ;--------------------------------------------------------------------------- |
||
252 | ; |
||
253 | ; PPPoE API |
||
254 | ; |
||
255 | ; This function is called by system function 75 |
||
256 | ; |
||
257 | ; IN: subfunction number in bl |
||
258 | ; device number in bh |
||
259 | ; ecx, edx, .. depends on subfunction |
||
260 | ; |
||
261 | ; OUT: |
||
262 | ; |
||
263 | ;--------------------------------------------------------------------------- |
||
264 | align 4 |
||
265 | PPPoE_api: |
||
266 | |||
267 | movzx eax, bh |
||
268 | shl eax, 2 |
||
269 | |||
270 | and ebx, 0xff |
||
271 | cmp ebx, .number |
||
272 | ja .error |
||
273 | jmp dword [.table + 4*ebx] |
||
274 | |||
275 | .table: |
||
276 | dd PPPoE_send_init ; 0 |
||
277 | dd PPPoE_stop_offers ; 1 |
||
278 | dd PPPoE_alloc_connection ; 3 |
||
279 | dd PPPoE_free_connection ; 4 |
||
280 | dd PPPoE_send_discovery ; 5 |
||
281 | dd PPPoE_receive_discovery ; 6 |
||
282 | .number = ($ - .table) / 4 - 1 |
||
283 | |||
284 | .error: |
||
285 | mov eax, -1 |
||
286 | ret>> |