0,0 → 1,286 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2009-2012. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; Clevermouse & hidnplayr ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|
|
struct PPPoE_header |
|
VersionAndType db ? |
Code db ? |
SessionID dw ? |
Length dw ? ; Length of payload, does NOT include the length PPPoE header. |
|
ends |
|
struct PPPoE_connection |
|
next dd ? ; pointer to next connection |
prev dd ? ; pointer to previous connection |
|
pid dd ? ; identifier of base application |
|
datalen dd ? ; length of received data |
recvbuf rb 1500 ; buffer for received data |
sendbuf rb 1500 ; buffer for data to send |
|
ends |
|
iglobal |
align 4 |
PPPoE.head dd PPPoE.head |
PPPoE.tail dd PPPoE.head |
endg |
|
uglobal |
PPPoE.cur_receiver dd ? |
PPPoE.cur_receiver_ptr dd ? |
PPPoE.cur_receiver_len dd ? |
endg |
|
|
; Allocates internal structure for future PPPoE actions. |
align 4 |
PPPoE_alloc_connection: |
|
; 1. Allocate memory in the kernel area. |
stdcall kernel_alloc, sizeof.PPPoE_connection |
|
; 1a. If memory allocation failed, return NULL. |
test eax, eax |
jz .nothing |
|
; 2. Copy PID of caller to the structure. |
mov edx, [CURRENT_TASK] |
mov [eax + PPPoE_connection.pid], edx |
|
; 3. Insert the structure to the list of all connections. |
mov [eax + PPPoE_connection.next], PPPoE.head |
mov edx, [PPPoE.tail] |
mov [eax + PPPoE_connection.prev], edx |
mov [edx + PPPoE_connection.next], eax |
mov [PPPoE.tail], eax |
|
.nothing: |
ret |
|
|
align 4 |
PPPoE_free_connection: |
|
; 1. Check that the caller is the owner of this connection. |
mov eax, [CURRENT_TASK] |
cmp [ebx+PPPoE_connection.pid], eax |
jnz .nothing |
|
; 2. Delete the structure from the list of all connections. |
mov eax, [ebx+PPPoE_connection.next] |
mov edx, [ebx+PPPoE_connection.prev] |
mov [eax+PPPoE_connection.prev], edx |
mov [edx+PPPoE_connection.next], eax |
|
; 3. Free the memory. |
stdcall kernel_free, ebx |
|
.nothing: |
ret |
|
|
; Send PADI packet |
|
; ebx (ecx in app) = size of buffer for PPPoE offers, must be at least 1514 |
; ecx (edx in app) = size of tags, 0 means "use default" |
; edx (esi in app) = pointer to buffer for PPPoE offers |
; esi (edi in app) = pointer to tags, ignored if 'size of tags' == 0 |
align 4 |
PPPoE_send_init: |
|
; 1. Check length. |
cmp ebi, 1514 |
jb .bad |
|
; RFC2516: An entire PADI packet (including the PPPoE header) MUST NOT |
; exceed 1484 octets. |
; PPPoE header is 6 bytes long, so maximum length of tags is 1478. |
cmp ecx, 1478 |
ja .bad |
|
; 2. Check that no one listen for offers. |
cmp [PPPoE.cur_receiver], 0 |
jnz .bad |
|
; 3. Remember PID and data pointer of current listener. |
push [CURRENT_TASK] |
pop [PPPoE.cur_receiver] |
mov [PPPoE.cur_receiver_ptr], edx |
mov [PPPoE.cur_receiver_len], ebx |
and dword [edx], 0 ; no offers yet |
|
; 4. Create packet. |
test ecx, ecx |
jnz @f |
mov esi, .default_payload |
mov ecx, .default_payload_length |
@@: |
|
mov edx, [NET_DRV_LIST] ;;;; FIXME |
lea eax, [ebx + ETH_DEVICE.mac] ; Source Address |
mov edx, ETH_BROADCAST ; Destination Address |
add ecx, sizeof.PPPoE_header ; Data size |
mov di, ETHER_PPP_DISCOVERY ; Protocol |
call ETH_output |
jz .eth_error |
|
push edx eax |
|
; 4b. Set ver=1, type=1 (=> first byte 0x11), code=9 (PADI packet), session=0 |
mov dword [edi], (0x09 shl 8) + 0x11 |
|
; 4c. Set payload length. |
mov [edi+4], ch |
mov [edi+5], cl |
|
; 4e. Copy given tags. |
rep movsb |
|
; 5. Send packet. |
call [ebx + NET_DEVICE.transmit] |
; 6. Return. |
xor eax, eax |
ret |
|
.bad: |
or eax, -1 |
ret |
|
.default_payload: |
; Service-Name tag with zero length |
dw 0x0101, 0x0000 |
.default_payload_length = $ - .default_payload |
|
|
; Stop receiving PADO packets |
align 4 |
PPPoE_stop_offers: |
|
; Only the listener can stop listen. ;;; TODO: make sure this function is called when process gets terminated |
mov eax, [CURRENT_TASK] |
cmp [PPPoE.cur_receiver], eax |
jnz .bad |
xor eax, eax |
mov [PPPoE.cur_receiver_ptr], eax |
mov [PPPoE.cur_receiver], eax |
ret |
|
.bad: |
or eax, -1 |
ret |
|
; Send PPPoE data in Discovery stage |
align 4 |
PPPoE_send_discovery: |
ret |
|
; Receive PPPoE data in Discovery stage |
align 4 |
PPPoE_receive_discovery: |
ret |
|
|
|
;----------------------------------------------------------------- |
; |
; PPPoE discovery input |
; |
; Handler of received Ethernet packet with type = Discovery |
; |
; |
; IN: Pointer to buffer in [esp] |
; size of buffer in [esp+4] |
; pointer to device struct in ebx |
; pointer to PPP header in edx |
; size of PPP packet in ecx |
; OUT: / |
; |
;----------------------------------------------------------------- |
align 4 |
PPPoE_discovery_input: |
|
; 1. Minimum 6 bytes for PPPoE header. |
cmp ecx, sizeof.PPPoE_header |
jb .bad |
|
; 1. Ignore packets with ver<>1 and/or type<>1. |
cmp [edx + PPPoE_header.VersionAndType], 0x11 |
jnz .bad |
|
; 2. Code must be either 7 for Offer, |
; or 0x65 for Session-Confirmation, or 0xa7 for Terminate. |
; Because only Initiation/Offers are supported, we expect only value 7. |
cmp [edx + PPPoE_header.Code], 7 |
jnz .bad |
|
; 3. Session ID must be zero for Offers. |
cmp [edx + PPPoE_header.SessionID], 0 |
jnz .bad |
|
; 4. Payload length |
rol [edx + PPPoE_header.Length], 8 ; Convert INET byte order to intel |
|
; 5. Ignore packet if nobody is listening. |
cmp [PPPoE.cur_receiver], 0 |
jz .bad |
|
; 6. Good, now copy the received packet to the buffer of listener. |
|
;;; TODO |
|
.bad: |
DEBUGF 1,'K : PPPoE - dumped\n' |
call kernel_free |
add esp, 4 ; pop (balance stack) |
ret |
|
|
|
|
;--------------------------------------------------------------------------- |
; |
; PPPoE API |
; |
; This function is called by system function 75 |
; |
; IN: subfunction number in bl |
; device number in bh |
; ecx, edx, .. depends on subfunction |
; |
; OUT: |
; |
;--------------------------------------------------------------------------- |
align 4 |
PPPoE_api: |
|
movzx eax, bh |
shl eax, 2 |
|
and ebx, 0xff |
cmp ebx, .number |
ja .error |
jmp dword [.table + 4*ebx] |
|
.table: |
dd PPPoE_send_init ; 0 |
dd PPPoE_stop_offers ; 1 |
dd PPPoE_alloc_connection ; 3 |
dd PPPoE_free_connection ; 4 |
dd PPPoE_send_discovery ; 5 |
dd PPPoE_receive_discovery ; 6 |
.number = ($ - .table) / 4 - 1 |
|
.error: |
mov eax, -1 |
ret |