forked from KolibriOS/kolibrios
287 lines
7.8 KiB
PHP
287 lines
7.8 KiB
PHP
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
;; ;;
|
||
|
;; 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
|