2007-08-16 18:12:20 +00:00
/*****************************************************************************
2012-08-18 20:40:19 +00:00
* pppoe . c - PPP Over Ethernet implementation for lwIP .
2007-08-16 18:12:20 +00:00
*
* Copyright ( c ) 2006 by Marc Boucher , Services Informatiques ( MBSI ) inc .
*
* The authors hereby grant permission to use , copy , modify , distribute ,
* and license this software and its documentation for any purpose , provided
* that existing copyright notices are retained in all copies and that this
* notice and the following disclaimer are included verbatim in any
* distributions . No written agreement , license , or royalty fee is required
* for any of the authorized uses .
*
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS * AS IS * AND ANY EXPRESS OR
* IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED .
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT ,
* INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT
* NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
* DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* REVISION HISTORY
*
* 06 - 01 - 01 Marc Boucher < marc @ mbsi . ca >
* Ported to lwIP .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* based on NetBSD: if_pppoe.c,v 1.64 2006/01/31 23:50:15 martin Exp */
/*-
* Copyright ( c ) 2002 The NetBSD Foundation , Inc .
* All rights reserved .
*
* This code is derived from software contributed to The NetBSD Foundation
* by Martin Husemann < martin @ NetBSD . org > .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* 2. Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement :
* This product includes software developed by the NetBSD
* Foundation , Inc . and its contributors .
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION , INC . AND CONTRIBUTORS
* ` ` AS IS ' ' AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED
* TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR
* CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS
* INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN
* CONTRACT , STRICT LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE )
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE .
*/
2007-11-29 22:19:56 +00:00
# include "lwip/opt.h"
2012-06-03 14:38:26 +00:00
# if PPP_SUPPORT && PPPOE_SUPPORT /* don't build if not configured for use in lwipopts.h */
2007-11-29 22:19:56 +00:00
2012-06-02 21:29:40 +00:00
#if 0 /* UNUSED */
# include <string.h>
# include <stdio.h>
# endif /* UNUSED */
2007-08-16 18:12:20 +00:00
2009-12-31 17:18:09 +00:00
# include "lwip/timers.h"
2010-05-16 14:34:16 +00:00
# include "lwip/memp.h"
2012-05-16 00:02:02 +00:00
# include "lwip/stats.h"
2015-11-12 20:25:42 +00:00
# include "lwip/snmp.h"
2007-11-30 17:22:20 +00:00
2012-08-18 20:40:19 +00:00
# include "netif/ppp/ppp_impl.h"
2015-02-15 10:25:37 +00:00
# include "netif/ppp/lcp.h"
2015-02-15 23:24:17 +00:00
# include "netif/ppp/ipcp.h"
2012-08-18 20:40:19 +00:00
# include "netif/ppp/pppoe.h"
2007-12-02 23:33:58 +00:00
2007-08-16 18:12:20 +00:00
/* Add a 16 bit unsigned value to a buffer pointed to by PTR */
2007-12-19 20:47:22 +00:00
# define PPPOE_ADD_16(PTR, VAL) \
2010-01-24 13:19:34 +00:00
* ( PTR ) + + = ( u8_t ) ( ( VAL ) / 256 ) ; \
* ( PTR ) + + = ( u8_t ) ( ( VAL ) % 256 )
2007-08-16 18:12:20 +00:00
/* Add a complete PPPoE header to the buffer pointed to by PTR */
2007-12-19 20:47:22 +00:00
# define PPPOE_ADD_HEADER(PTR, CODE, SESS, LEN) \
* ( PTR ) + + = PPPOE_VERTYPE ; \
* ( PTR ) + + = ( CODE ) ; \
PPPOE_ADD_16 ( PTR , SESS ) ; \
PPPOE_ADD_16 ( PTR , LEN )
2007-08-16 18:12:20 +00:00
2007-12-19 20:47:22 +00:00
# define PPPOE_DISC_TIMEOUT (5*1000) /* base for quick timeout calculation */
# define PPPOE_SLOW_RETRY (60*1000) /* persistent retry interval */
# define PPPOE_DISC_MAXPADI 4 /* retry PADI four times (quickly) */
# define PPPOE_DISC_MAXPADR 2 /* retry PADR twice */
2007-08-16 18:12:20 +00:00
# ifdef PPPOE_SERVER
2010-01-24 13:19:34 +00:00
# error "PPPOE_SERVER is not yet supported under lwIP!"
2007-08-16 18:12:20 +00:00
/* from if_spppsubr.c */
2007-12-19 20:47:22 +00:00
# define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */
2007-08-16 18:12:20 +00:00
# endif
2010-05-16 14:11:53 +00:00
# define PPPOE_ERRORSTRING_LEN 64
2007-08-16 18:12:20 +00:00
2015-02-15 10:04:09 +00:00
/* callbacks called from PPP core */
2015-02-19 22:51:33 +00:00
static err_t pppoe_write ( ppp_pcb * ppp , void * ctx , struct pbuf * p ) ;
static err_t pppoe_netif_output ( ppp_pcb * ppp , void * ctx , struct pbuf * p , u_short protocol ) ;
2015-02-19 22:25:21 +00:00
static err_t pppoe_connect ( ppp_pcb * ppp , void * ctx ) ;
static void pppoe_disconnect ( ppp_pcb * ppp , void * ctx ) ;
static err_t pppoe_destroy ( ppp_pcb * ppp , void * ctx ) ;
2015-02-15 09:18:02 +00:00
2007-08-16 18:12:20 +00:00
/* management routines */
static void pppoe_abort_connect ( struct pppoe_softc * ) ;
2015-03-01 23:16:25 +00:00
#if 0 /* UNUSED */
2007-08-16 18:12:20 +00:00
static void pppoe_clear_softc ( struct pppoe_softc * , const char * ) ;
2015-03-01 23:16:25 +00:00
# endif /* UNUSED */
2007-08-16 18:12:20 +00:00
/* internal timeout handling */
static void pppoe_timeout ( void * ) ;
/* sending actual protocol controll packets */
static err_t pppoe_send_padi ( struct pppoe_softc * ) ;
static err_t pppoe_send_padr ( struct pppoe_softc * ) ;
# ifdef PPPOE_SERVER
static err_t pppoe_send_pado ( struct pppoe_softc * ) ;
static err_t pppoe_send_pads ( struct pppoe_softc * ) ;
# endif
static err_t pppoe_send_padt ( struct netif * , u_int , const u8_t * ) ;
/* internal helper functions */
2015-02-15 10:04:09 +00:00
static err_t pppoe_xmit ( struct pppoe_softc * sc , struct pbuf * pb ) ;
2012-06-16 22:33:02 +00:00
static struct pppoe_softc * pppoe_find_softc_by_session ( u_int session , struct netif * rcvif ) ;
static struct pppoe_softc * pppoe_find_softc_by_hunique ( u8_t * token , size_t len , struct netif * rcvif ) ;
2007-08-16 18:12:20 +00:00
2010-05-16 14:24:40 +00:00
/** linked list of created pppoe interfaces */
static struct pppoe_softc * pppoe_softc_list ;
2007-08-16 18:12:20 +00:00
2015-02-19 22:25:21 +00:00
/* Callbacks structure for PPP core */
static const struct link_callbacks pppoe_callbacks = {
pppoe_connect ,
2015-02-28 21:41:18 +00:00
# if PPP_SERVER
NULL ,
# endif /* PPP_SERVER */
2015-02-19 22:25:21 +00:00
pppoe_disconnect ,
pppoe_destroy ,
2015-02-19 22:51:33 +00:00
pppoe_write ,
pppoe_netif_output ,
2015-02-19 22:47:10 +00:00
NULL ,
NULL
2015-02-19 22:25:21 +00:00
} ;
2015-02-15 10:15:07 +00:00
/*
* Create a new PPP Over Ethernet ( PPPoE ) connection .
*
* Return 0 on success , an error code on failure .
*/
2015-02-17 21:51:35 +00:00
ppp_pcb * pppoe_create ( struct netif * pppif ,
struct netif * ethif ,
const char * service_name , const char * concentrator_name ,
ppp_link_status_cb_fn link_status_cb , void * ctx_cb )
2007-08-16 18:12:20 +00:00
{
2015-02-14 22:50:38 +00:00
ppp_pcb * ppp ;
2007-12-19 20:47:22 +00:00
struct pppoe_softc * sc ;
2015-02-15 10:15:07 +00:00
LWIP_UNUSED_ARG ( service_name ) ;
LWIP_UNUSED_ARG ( concentrator_name ) ;
2007-08-16 18:12:20 +00:00
2015-09-13 16:21:14 +00:00
sc = ( struct pppoe_softc * ) memp_malloc ( MEMP_PPPOE_IF ) ;
if ( sc = = NULL ) {
2015-02-14 22:50:38 +00:00
return NULL ;
}
2015-09-13 16:28:06 +00:00
ppp = ppp_new ( pppif , & pppoe_callbacks , sc , link_status_cb , ctx_cb ) ;
2015-09-13 16:21:14 +00:00
if ( ppp = = NULL ) {
memp_free ( MEMP_PPPOE_IF , sc ) ;
2015-02-14 22:50:38 +00:00
return NULL ;
2007-12-19 20:47:22 +00:00
}
2007-08-16 18:12:20 +00:00
2015-09-13 16:21:14 +00:00
memset ( sc , 0 , sizeof ( struct pppoe_softc ) ) ;
2007-12-19 20:47:22 +00:00
/* changed to real address later */
2008-01-26 16:11:39 +00:00
MEMCPY ( & sc - > sc_dest , ethbroadcast . addr , sizeof ( sc - > sc_dest ) ) ;
2015-02-14 22:50:38 +00:00
sc - > pcb = ppp ;
2007-12-19 20:47:22 +00:00
sc - > sc_ethif = ethif ;
2010-05-16 14:24:40 +00:00
/* put the new interface at the head of the list */
sc - > next = pppoe_softc_list ;
pppoe_softc_list = sc ;
2015-02-14 22:50:38 +00:00
return ppp ;
2007-08-16 18:12:20 +00:00
}
2015-02-15 09:18:02 +00:00
/* Called by PPP core */
2015-02-19 22:51:33 +00:00
static err_t pppoe_write ( ppp_pcb * ppp , void * ctx , struct pbuf * p ) {
2015-02-19 22:25:21 +00:00
struct pppoe_softc * sc = ( struct pppoe_softc * ) ctx ;
2015-02-15 10:04:09 +00:00
struct pbuf * ph ; /* Ethernet + PPPoE header */
2015-02-20 19:51:37 +00:00
err_t ret ;
2015-09-08 07:47:30 +00:00
# if MIB2_STATS
2015-02-15 10:04:09 +00:00
u16_t tot_len ;
2015-09-08 07:47:30 +00:00
# else /* MIB2_STATS */
2015-03-14 12:59:44 +00:00
LWIP_UNUSED_ARG ( ppp ) ;
2015-09-08 07:47:30 +00:00
# endif /* MIB2_STATS */
2015-02-15 10:04:09 +00:00
/* skip address & flags */
pbuf_header ( p , - ( s16_t ) 2 ) ;
ph = pbuf_alloc ( PBUF_LINK , ( u16_t ) ( PPPOE_HEADERLEN ) , PBUF_RAM ) ;
if ( ! ph ) {
LINK_STATS_INC ( link . memerr ) ;
LINK_STATS_INC ( link . proterr ) ;
2015-09-08 07:47:30 +00:00
MIB2_STATS_NETIF_INC ( ppp - > netif , ifoutdiscards ) ;
2015-02-15 10:04:09 +00:00
pbuf_free ( p ) ;
2015-02-20 19:51:37 +00:00
return ERR_MEM ;
2015-02-15 10:04:09 +00:00
}
pbuf_header ( ph , - ( s16_t ) PPPOE_HEADERLEN ) ; /* hide PPPoE header */
pbuf_cat ( ph , p ) ;
2015-09-08 07:47:30 +00:00
# if MIB2_STATS
2015-02-15 10:04:09 +00:00
tot_len = ph - > tot_len ;
2015-09-08 07:47:30 +00:00
# endif /* MIB2_STATS */
2015-02-15 10:04:09 +00:00
2015-02-20 19:51:37 +00:00
ret = pppoe_xmit ( sc , ph ) ;
if ( ret ! = ERR_OK ) {
2015-02-15 10:04:09 +00:00
LINK_STATS_INC ( link . err ) ;
2015-09-08 07:47:30 +00:00
MIB2_STATS_NETIF_INC ( ppp - > netif , ifoutdiscards ) ;
2015-02-20 19:51:37 +00:00
return ret ;
2015-02-15 10:04:09 +00:00
}
2015-09-08 07:47:30 +00:00
MIB2_STATS_NETIF_ADD ( ppp - > netif , ifoutoctets , ( u16_t ) tot_len ) ;
MIB2_STATS_NETIF_INC ( ppp - > netif , ifoutucastpkts ) ;
2015-02-15 10:04:09 +00:00
LINK_STATS_INC ( link . xmit ) ;
2015-02-20 19:51:37 +00:00
return ERR_OK ;
2015-02-15 10:04:09 +00:00
}
/* Called by PPP core */
2015-02-19 22:51:33 +00:00
static err_t pppoe_netif_output ( ppp_pcb * ppp , void * ctx , struct pbuf * p , u_short protocol ) {
2015-02-19 22:25:21 +00:00
struct pppoe_softc * sc = ( struct pppoe_softc * ) ctx ;
2015-02-15 10:04:09 +00:00
struct pbuf * pb ;
2015-03-10 22:34:11 +00:00
u8_t * pl ;
2015-03-14 12:59:44 +00:00
err_t err ;
2015-09-08 07:47:30 +00:00
# if MIB2_STATS
2015-02-15 10:04:09 +00:00
u16_t tot_len ;
2015-09-08 07:47:30 +00:00
# else /* MIB2_STATS */
2015-03-14 12:59:44 +00:00
LWIP_UNUSED_ARG ( ppp ) ;
2015-09-08 07:47:30 +00:00
# endif /* MIB2_STATS */
2015-02-15 10:04:09 +00:00
/* @todo: try to use pbuf_header() here! */
pb = pbuf_alloc ( PBUF_LINK , PPPOE_HEADERLEN + sizeof ( protocol ) , PBUF_RAM ) ;
if ( ! pb ) {
LINK_STATS_INC ( link . memerr ) ;
LINK_STATS_INC ( link . proterr ) ;
2015-09-08 07:47:30 +00:00
MIB2_STATS_NETIF_INC ( ppp - > netif , ifoutdiscards ) ;
2015-02-15 10:04:09 +00:00
return ERR_MEM ;
}
pbuf_header ( pb , - ( s16_t ) PPPOE_HEADERLEN ) ;
2015-03-10 22:34:11 +00:00
pl = ( u8_t * ) pb - > payload ;
PUTSHORT ( protocol , pl ) ;
2015-02-15 10:04:09 +00:00
pbuf_chain ( pb , p ) ;
2015-09-08 07:47:30 +00:00
# if MIB2_STATS
2015-02-15 10:04:09 +00:00
tot_len = pb - > tot_len ;
2015-09-08 07:47:30 +00:00
# endif /* MIB2_STATS */
2015-02-15 10:04:09 +00:00
if ( ( err = pppoe_xmit ( sc , pb ) ) ! = ERR_OK ) {
LINK_STATS_INC ( link . err ) ;
2015-09-08 07:47:30 +00:00
MIB2_STATS_NETIF_INC ( ppp - > netif , ifoutdiscards ) ;
2015-02-15 10:04:09 +00:00
return err ;
}
2015-09-08 07:47:30 +00:00
MIB2_STATS_NETIF_ADD ( ppp - > netif , ifoutoctets , tot_len ) ;
MIB2_STATS_NETIF_INC ( ppp - > netif , ifoutucastpkts ) ;
2015-02-15 10:04:09 +00:00
LINK_STATS_INC ( link . xmit ) ;
return ERR_OK ;
}
2015-02-15 09:18:02 +00:00
static err_t
2015-02-19 22:25:21 +00:00
pppoe_destroy ( ppp_pcb * ppp , void * ctx )
2007-08-16 18:12:20 +00:00
{
2015-02-19 22:25:21 +00:00
struct pppoe_softc * sc = ( struct pppoe_softc * ) ctx ;
2015-02-17 20:32:24 +00:00
struct pppoe_softc * * copp , * freep ;
2015-02-19 22:25:21 +00:00
LWIP_UNUSED_ARG ( ppp ) ;
2007-12-19 20:47:22 +00:00
2009-12-31 17:18:09 +00:00
sys_untimeout ( pppoe_timeout , sc ) ;
2015-02-17 20:32:24 +00:00
/* remove interface from list */
for ( copp = & pppoe_softc_list ; ( freep = * copp ) ; copp = & freep - > next ) {
if ( freep = = sc ) {
* copp = freep - > next ;
break ;
}
2010-05-16 14:24:40 +00:00
}
2007-12-19 20:47:22 +00:00
2010-05-16 14:11:53 +00:00
# ifdef PPPOE_TODO
2007-12-19 20:47:22 +00:00
if ( sc - > sc_concentrator_name ) {
mem_free ( sc - > sc_concentrator_name ) ;
}
if ( sc - > sc_service_name ) {
mem_free ( sc - > sc_service_name ) ;
}
2010-05-16 14:11:53 +00:00
# endif /* PPPOE_TODO */
2010-05-16 14:34:16 +00:00
memp_free ( MEMP_PPPOE_IF , sc ) ;
2007-12-19 20:47:22 +00:00
return ERR_OK ;
2007-08-16 18:12:20 +00:00
}
/*
* Find the interface handling the specified session .
* Note : O ( number of sessions open ) , this is a client - side only , mean
* and lean implementation , so number of open sessions typically should
* be 1.
*/
2012-06-16 22:33:02 +00:00
static struct pppoe_softc * pppoe_find_softc_by_session ( u_int session , struct netif * rcvif ) {
2007-12-19 20:47:22 +00:00
struct pppoe_softc * sc ;
if ( session = = 0 ) {
return NULL ;
}
2010-05-16 14:24:40 +00:00
for ( sc = pppoe_softc_list ; sc ! = NULL ; sc = sc - > next ) {
2007-12-19 20:47:22 +00:00
if ( sc - > sc_state = = PPPOE_STATE_SESSION
2012-06-16 22:33:02 +00:00
& & sc - > sc_session = = session
& & sc - > sc_ethif = = rcvif ) {
return sc ;
2007-12-19 20:47:22 +00:00
}
}
return NULL ;
2007-08-16 18:12:20 +00:00
}
/* Check host unique token passed and return appropriate softc pointer,
* or NULL if token is bogus . */
2012-06-16 22:33:02 +00:00
static struct pppoe_softc * pppoe_find_softc_by_hunique ( u8_t * token , size_t len , struct netif * rcvif ) {
2007-12-19 20:47:22 +00:00
struct pppoe_softc * sc , * t ;
2010-05-16 14:24:40 +00:00
if ( pppoe_softc_list = = NULL ) {
2007-12-19 20:47:22 +00:00
return NULL ;
}
if ( len ! = sizeof sc ) {
return NULL ;
}
2008-01-26 16:11:39 +00:00
MEMCPY ( & t , token , len ) ;
2007-12-19 20:47:22 +00:00
2010-05-16 14:24:40 +00:00
for ( sc = pppoe_softc_list ; sc ! = NULL ; sc = sc - > next ) {
2007-12-19 20:47:22 +00:00
if ( sc = = t ) {
break ;
}
}
if ( sc = = NULL ) {
2010-02-22 20:16:39 +00:00
PPPDEBUG ( LOG_DEBUG , ( " pppoe: alien host unique tag, no session found \n " ) ) ;
2007-12-19 20:47:22 +00:00
return NULL ;
}
/* should be safe to access *sc now */
if ( sc - > sc_state < PPPOE_STATE_PADI_SENT | | sc - > sc_state > = PPPOE_STATE_SESSION ) {
2012-05-16 00:02:02 +00:00
PPPDEBUG ( LOG_DEBUG , ( " %c%c% " U16_F " : host unique tag found, but it belongs to a connection in state %d \n " ,
sc - > sc_ethif - > name [ 0 ] , sc - > sc_ethif - > name [ 1 ] , sc - > sc_ethif - > num , sc - > sc_state ) ) ;
2007-12-19 20:47:22 +00:00
return NULL ;
}
if ( sc - > sc_ethif ! = rcvif ) {
2012-05-16 00:02:02 +00:00
PPPDEBUG ( LOG_DEBUG , ( " %c%c% " U16_F " : wrong interface, not accepting host unique \n " ,
sc - > sc_ethif - > name [ 0 ] , sc - > sc_ethif - > name [ 1 ] , sc - > sc_ethif - > num ) ) ;
2007-12-19 20:47:22 +00:00
return NULL ;
}
return sc ;
2007-08-16 18:12:20 +00:00
}
/* analyze and handle a single received packet while not in session state */
2012-07-15 13:12:40 +00:00
void
pppoe_disc_input ( struct netif * netif , struct pbuf * pb )
2007-08-16 18:12:20 +00:00
{
2007-12-19 20:47:22 +00:00
u16_t tag , len ;
u16_t session , plen ;
struct pppoe_softc * sc ;
2015-03-15 16:57:16 +00:00
# if PPP_DEBUG
const char * err_msg = NULL ;
# endif /* PPP_DEBUG */
2007-12-19 20:47:22 +00:00
u8_t * ac_cookie ;
2010-02-04 18:47:44 +00:00
u16_t ac_cookie_len ;
2007-08-16 18:12:20 +00:00
# ifdef PPPOE_SERVER
2007-12-19 20:47:22 +00:00
u8_t * hunique ;
size_t hunique_len ;
2007-08-16 18:12:20 +00:00
# endif
2007-12-19 20:47:22 +00:00
struct pppoehdr * ph ;
struct pppoetag pt ;
2012-05-16 00:02:02 +00:00
int off , err ;
2007-12-19 20:47:22 +00:00
struct eth_hdr * ethhdr ;
2012-07-15 13:12:40 +00:00
/* don't do anything if there is not a single PPPoE instance */
if ( pppoe_softc_list = = NULL ) {
pbuf_free ( pb ) ;
return ;
}
2012-06-02 23:46:46 +00:00
pb = ppp_singlebuf ( pb ) ;
2007-12-19 20:47:22 +00:00
if ( pb - > len < sizeof ( * ethhdr ) ) {
goto done ;
}
ethhdr = ( struct eth_hdr * ) pb - > payload ;
2009-12-06 10:14:46 +00:00
off = sizeof ( * ethhdr ) ;
2007-12-19 20:47:22 +00:00
ac_cookie = NULL ;
ac_cookie_len = 0 ;
2007-08-16 18:12:20 +00:00
# ifdef PPPOE_SERVER
2007-12-19 20:47:22 +00:00
hunique = NULL ;
hunique_len = 0 ;
2007-08-16 18:12:20 +00:00
# endif
2007-12-19 20:47:22 +00:00
session = 0 ;
2014-10-12 17:54:43 +00:00
if ( pb - > len - off < ( u16_t ) PPPOE_HEADERLEN ) {
2012-05-16 00:02:02 +00:00
PPPDEBUG ( LOG_DEBUG , ( " pppoe: packet too short: %d \n " , pb - > len ) ) ;
2007-12-19 20:47:22 +00:00
goto done ;
}
ph = ( struct pppoehdr * ) ( ethhdr + 1 ) ;
if ( ph - > vertype ! = PPPOE_VERTYPE ) {
2012-05-16 00:02:02 +00:00
PPPDEBUG ( LOG_DEBUG , ( " pppoe: unknown version/type packet: 0x%x \n " , ph - > vertype ) ) ;
2007-12-19 20:47:22 +00:00
goto done ;
}
session = ntohs ( ph - > session ) ;
plen = ntohs ( ph - > plen ) ;
off + = sizeof ( * ph ) ;
if ( plen + off > pb - > len ) {
2012-05-16 00:02:02 +00:00
PPPDEBUG ( LOG_DEBUG , ( " pppoe: packet content does not fit: data available = %d, packet size = %u \n " ,
pb - > len - off , plen ) ) ;
2007-12-19 20:47:22 +00:00
goto done ;
}
if ( pb - > tot_len = = pb - > len ) {
2010-01-24 13:19:34 +00:00
pb - > tot_len = pb - > len = ( u16_t ) off + plen ; /* ignore trailing garbage */
2007-12-19 20:47:22 +00:00
}
tag = 0 ;
len = 0 ;
sc = NULL ;
while ( off + sizeof ( pt ) < = pb - > len ) {
2008-01-26 16:11:39 +00:00
MEMCPY ( & pt , ( u8_t * ) pb - > payload + off , sizeof ( pt ) ) ;
2007-12-19 20:47:22 +00:00
tag = ntohs ( pt . tag ) ;
len = ntohs ( pt . len ) ;
if ( off + sizeof ( pt ) + len > pb - > len ) {
2012-05-16 00:02:02 +00:00
PPPDEBUG ( LOG_DEBUG , ( " pppoe: tag 0x%x len 0x%x is too long \n " , tag , len ) ) ;
2007-12-19 20:47:22 +00:00
goto done ;
}
switch ( tag ) {
case PPPOE_TAG_EOL :
goto breakbreak ;
case PPPOE_TAG_SNAME :
break ; /* ignored */
case PPPOE_TAG_ACNAME :
break ; /* ignored */
case PPPOE_TAG_HUNIQUE :
if ( sc ! = NULL ) {
break ;
}
2007-08-16 18:12:20 +00:00
# ifdef PPPOE_SERVER
2007-12-19 20:47:22 +00:00
hunique = ( u8_t * ) pb - > payload + off + sizeof ( pt ) ;
hunique_len = len ;
2007-08-16 18:12:20 +00:00
# endif
2007-12-19 20:47:22 +00:00
sc = pppoe_find_softc_by_hunique ( ( u8_t * ) pb - > payload + off + sizeof ( pt ) , len , netif ) ;
break ;
case PPPOE_TAG_ACCOOKIE :
if ( ac_cookie = = NULL ) {
ac_cookie = ( u8_t * ) pb - > payload + off + sizeof ( pt ) ;
ac_cookie_len = len ;
}
break ;
2015-03-15 16:57:16 +00:00
# if PPP_DEBUG
2007-12-19 20:47:22 +00:00
case PPPOE_TAG_SNAME_ERR :
err_msg = " SERVICE NAME ERROR " ;
break ;
case PPPOE_TAG_ACSYS_ERR :
err_msg = " AC SYSTEM ERROR " ;
break ;
case PPPOE_TAG_GENERIC_ERR :
err_msg = " GENERIC ERROR " ;
break ;
2015-03-15 16:57:16 +00:00
# endif /* PPP_DEBUG */
2014-12-24 14:16:03 +00:00
default :
break ;
2007-12-19 20:47:22 +00:00
}
2015-03-01 23:05:55 +00:00
# if PPP_DEBUG
2015-03-01 23:45:19 +00:00
if ( err_msg ! = NULL ) {
char error_tmp [ PPPOE_ERRORSTRING_LEN ] ;
u16_t error_len = LWIP_MIN ( len , sizeof ( error_tmp ) - 1 ) ;
strncpy ( error_tmp , ( char * ) pb - > payload + off + sizeof ( pt ) , error_len ) ;
error_tmp [ error_len ] = ' \0 ' ;
if ( sc ) {
PPPDEBUG ( LOG_DEBUG , ( " pppoe: %c%c% " U16_F " : %s: %s \n " , sc - > sc_ethif - > name [ 0 ] , sc - > sc_ethif - > name [ 1 ] , sc - > sc_ethif - > num , err_msg , error_tmp ) ) ;
2007-12-19 20:47:22 +00:00
} else {
2015-03-01 23:45:19 +00:00
PPPDEBUG ( LOG_DEBUG , ( " pppoe: %s: %s \n " , err_msg , error_tmp ) ) ;
2007-12-19 20:47:22 +00:00
}
}
2015-03-01 23:05:55 +00:00
# endif /* PPP_DEBUG */
2007-12-19 20:47:22 +00:00
off + = sizeof ( pt ) + len ;
}
2007-08-16 18:12:20 +00:00
breakbreak : ;
2007-12-19 20:47:22 +00:00
switch ( ph - > code ) {
case PPPOE_CODE_PADI :
2007-08-16 18:12:20 +00:00
# ifdef PPPOE_SERVER
2007-12-19 20:47:22 +00:00
/*
* got service name , concentrator name , and / or host unique .
* ignore if we have no interfaces with IFF_PASSIVE | IFF_UP .
*/
if ( LIST_EMPTY ( & pppoe_softc_list ) ) {
goto done ;
}
LIST_FOREACH ( sc , & pppoe_softc_list , sc_list ) {
if ( ! ( sc - > sc_sppp . pp_if . if_flags & IFF_UP ) ) {
continue ;
}
if ( ! ( sc - > sc_sppp . pp_if . if_flags & IFF_PASSIVE ) ) {
continue ;
}
if ( sc - > sc_state = = PPPOE_STATE_INITIAL ) {
break ;
}
}
if ( sc = = NULL ) {
2012-05-16 00:02:02 +00:00
/* PPPDEBUG(LOG_DEBUG, ("pppoe: free passive interface is not found\n")); */
2007-12-19 20:47:22 +00:00
goto done ;
}
if ( hunique ) {
if ( sc - > sc_hunique ) {
mem_free ( sc - > sc_hunique ) ;
}
sc - > sc_hunique = mem_malloc ( hunique_len ) ;
if ( sc - > sc_hunique = = NULL ) {
goto done ;
}
sc - > sc_hunique_len = hunique_len ;
2008-01-26 16:11:39 +00:00
MEMCPY ( sc - > sc_hunique , hunique , hunique_len ) ;
2007-12-19 20:47:22 +00:00
}
2008-01-26 16:11:39 +00:00
MEMCPY ( & sc - > sc_dest , eh - > ether_shost , sizeof sc - > sc_dest ) ;
2007-12-19 20:47:22 +00:00
sc - > sc_state = PPPOE_STATE_PADO_SENT ;
pppoe_send_pado ( sc ) ;
break ;
2010-02-04 18:47:44 +00:00
# endif /* PPPOE_SERVER */
2007-12-19 20:47:22 +00:00
case PPPOE_CODE_PADR :
2010-02-04 18:47:44 +00:00
# ifdef PPPOE_SERVER
2007-12-19 20:47:22 +00:00
/*
* get sc from ac_cookie if IFF_PASSIVE
*/
if ( ac_cookie = = NULL ) {
/* be quiet if there is not a single pppoe instance */
2012-05-16 00:02:02 +00:00
PPPDEBUG ( LOG_DEBUG , ( " pppoe: received PADR but not includes ac_cookie \n " ) ) ;
2007-12-19 20:47:22 +00:00
goto done ;
}
sc = pppoe_find_softc_by_hunique ( ac_cookie , ac_cookie_len , netif ) ;
if ( sc = = NULL ) {
/* be quiet if there is not a single pppoe instance */
if ( ! LIST_EMPTY ( & pppoe_softc_list ) ) {
2012-05-16 00:02:02 +00:00
PPPDEBUG ( LOG_DEBUG , ( " pppoe: received PADR but could not find request for it \n " ) ) ;
2007-12-19 20:47:22 +00:00
}
goto done ;
}
if ( sc - > sc_state ! = PPPOE_STATE_PADO_SENT ) {
2012-05-16 00:02:02 +00:00
PPPDEBUG ( LOG_DEBUG , ( " %c%c% " U16_F " : received unexpected PADR \n " , sc - > sc_ethif - > name [ 0 ] , sc - > sc_ethif - > name [ 1 ] , sc - > sc_ethif - > num ) ) ;
2007-12-19 20:47:22 +00:00
goto done ;
}
if ( hunique ) {
if ( sc - > sc_hunique ) {
mem_free ( sc - > sc_hunique ) ;
}
sc - > sc_hunique = mem_malloc ( hunique_len ) ;
if ( sc - > sc_hunique = = NULL ) {
goto done ;
}
sc - > sc_hunique_len = hunique_len ;
2008-01-26 16:11:39 +00:00
MEMCPY ( sc - > sc_hunique , hunique , hunique_len ) ;
2007-12-19 20:47:22 +00:00
}
pppoe_send_pads ( sc ) ;
sc - > sc_state = PPPOE_STATE_SESSION ;
2015-02-14 23:35:45 +00:00
ppp_start ( sc - > pcb ) ; /* notify upper layers */
2007-12-19 20:47:22 +00:00
break ;
2010-02-04 18:47:44 +00:00
# else
2007-12-19 20:47:22 +00:00
/* ignore, we are no access concentrator */
goto done ;
2010-02-04 18:47:44 +00:00
# endif /* PPPOE_SERVER */
2007-12-19 20:47:22 +00:00
case PPPOE_CODE_PADO :
if ( sc = = NULL ) {
/* be quiet if there is not a single pppoe instance */
2010-05-16 14:24:40 +00:00
if ( pppoe_softc_list ! = NULL ) {
2012-05-16 00:02:02 +00:00
PPPDEBUG ( LOG_DEBUG , ( " pppoe: received PADO but could not find request for it \n " ) ) ;
2007-12-19 20:47:22 +00:00
}
goto done ;
}
if ( sc - > sc_state ! = PPPOE_STATE_PADI_SENT ) {
2012-05-16 00:02:02 +00:00
PPPDEBUG ( LOG_DEBUG , ( " %c%c% " U16_F " : received unexpected PADO \n " , sc - > sc_ethif - > name [ 0 ] , sc - > sc_ethif - > name [ 1 ] , sc - > sc_ethif - > num ) ) ;
2007-12-19 20:47:22 +00:00
goto done ;
}
if ( ac_cookie ) {
sc - > sc_ac_cookie_len = ac_cookie_len ;
2008-01-26 16:11:39 +00:00
MEMCPY ( sc - > sc_ac_cookie , ac_cookie , ac_cookie_len ) ;
2007-12-19 20:47:22 +00:00
}
2008-01-26 16:11:39 +00:00
MEMCPY ( & sc - > sc_dest , ethhdr - > src . addr , sizeof ( sc - > sc_dest . addr ) ) ;
2009-12-31 17:18:09 +00:00
sys_untimeout ( pppoe_timeout , sc ) ;
2007-12-19 20:47:22 +00:00
sc - > sc_padr_retried = 0 ;
sc - > sc_state = PPPOE_STATE_PADR_SENT ;
if ( ( err = pppoe_send_padr ( sc ) ) ! = 0 ) {
2010-02-22 20:16:39 +00:00
PPPDEBUG ( LOG_DEBUG , ( " pppoe: %c%c% " U16_F " : failed to send PADR, error=%d \n " , sc - > sc_ethif - > name [ 0 ] , sc - > sc_ethif - > name [ 1 ] , sc - > sc_ethif - > num , err ) ) ;
2007-12-19 20:47:22 +00:00
}
2009-12-31 17:18:09 +00:00
sys_timeout ( PPPOE_DISC_TIMEOUT * ( 1 + sc - > sc_padr_retried ) , pppoe_timeout , sc ) ;
2007-12-19 20:47:22 +00:00
break ;
case PPPOE_CODE_PADS :
if ( sc = = NULL ) {
goto done ;
}
sc - > sc_session = session ;
2009-12-31 17:18:09 +00:00
sys_untimeout ( pppoe_timeout , sc ) ;
2010-02-22 20:16:39 +00:00
PPPDEBUG ( LOG_DEBUG , ( " pppoe: %c%c% " U16_F " : session 0x%x connected \n " , sc - > sc_ethif - > name [ 0 ] , sc - > sc_ethif - > name [ 1 ] , sc - > sc_ethif - > num , session ) ) ;
2007-12-19 20:47:22 +00:00
sc - > sc_state = PPPOE_STATE_SESSION ;
2015-02-14 23:35:45 +00:00
ppp_start ( sc - > pcb ) ; /* notify upper layers */
2007-12-19 20:47:22 +00:00
break ;
case PPPOE_CODE_PADT :
2015-03-01 23:16:25 +00:00
/* Don't disconnect here, we let the LCP Echo/Reply find the fact
* that PPP session is down . Asking the PPP stack to end the session
* require strict checking about the PPP phase to prevent endless
* disconnection loops .
*/
#if 0 /* UNUSED */
if ( sc = = NULL ) { /* PADT frames are rarely sent with a hunique tag, this is actually almost always true */
2007-12-19 20:47:22 +00:00
goto done ;
}
pppoe_clear_softc ( sc , " received PADT " ) ;
2015-03-01 23:16:25 +00:00
# endif /* UNUSED */
2007-12-19 20:47:22 +00:00
break ;
default :
if ( sc ) {
2012-05-16 00:02:02 +00:00
PPPDEBUG ( LOG_DEBUG , ( " %c%c% " U16_F " : unknown code (0x% " X16_F " ) session = 0x% " X16_F " \n " ,
2007-12-19 20:47:22 +00:00
sc - > sc_ethif - > name [ 0 ] , sc - > sc_ethif - > name [ 1 ] , sc - > sc_ethif - > num ,
2012-05-16 00:02:02 +00:00
( u16_t ) ph - > code , session ) ) ;
2007-12-19 20:47:22 +00:00
} else {
2012-05-16 00:02:02 +00:00
PPPDEBUG ( LOG_DEBUG , ( " pppoe: unknown code (0x% " X16_F " ) session = 0x% " X16_F " \n " , ( u16_t ) ph - > code , session ) ) ;
2007-12-19 20:47:22 +00:00
}
break ;
}
2007-08-16 18:12:20 +00:00
done :
2007-12-19 20:47:22 +00:00
pbuf_free ( pb ) ;
return ;
2007-08-16 18:12:20 +00:00
}
void
pppoe_data_input ( struct netif * netif , struct pbuf * pb )
{
2007-12-19 20:47:22 +00:00
u16_t session , plen ;
struct pppoe_softc * sc ;
struct pppoehdr * ph ;
2007-08-16 18:12:20 +00:00
# ifdef PPPOE_TERM_UNKNOWN_SESSIONS
2007-12-19 20:47:22 +00:00
u8_t shost [ ETHER_ADDR_LEN ] ;
2007-08-16 18:12:20 +00:00
# endif
# ifdef PPPOE_TERM_UNKNOWN_SESSIONS
2008-01-26 16:11:39 +00:00
MEMCPY ( shost , ( ( struct eth_hdr * ) pb - > payload ) - > src . addr , sizeof ( shost ) ) ;
2007-08-16 18:12:20 +00:00
# endif
2015-04-26 21:42:18 +00:00
if ( pbuf_header ( pb , - ( s16_t ) sizeof ( struct eth_hdr ) ) ! = 0 ) {
2007-12-19 20:47:22 +00:00
/* bail out */
2010-02-22 20:16:39 +00:00
PPPDEBUG ( LOG_ERR , ( " pppoe_data_input: pbuf_header failed \n " ) ) ;
2007-12-19 20:47:22 +00:00
LINK_STATS_INC ( link . lenerr ) ;
goto drop ;
}
if ( pb - > len < sizeof ( * ph ) ) {
2012-05-16 00:02:02 +00:00
PPPDEBUG ( LOG_DEBUG , ( " pppoe_data_input: could not get PPPoE header \n " ) ) ;
2007-12-19 20:47:22 +00:00
goto drop ;
}
ph = ( struct pppoehdr * ) pb - > payload ;
if ( ph - > vertype ! = PPPOE_VERTYPE ) {
2012-05-16 00:02:02 +00:00
PPPDEBUG ( LOG_DEBUG , ( " pppoe (data): unknown version/type packet: 0x%x \n " , ph - > vertype ) ) ;
2007-12-19 20:47:22 +00:00
goto drop ;
}
if ( ph - > code ! = 0 ) {
goto drop ;
}
session = ntohs ( ph - > session ) ;
sc = pppoe_find_softc_by_session ( session , netif ) ;
if ( sc = = NULL ) {
2007-08-16 18:12:20 +00:00
# ifdef PPPOE_TERM_UNKNOWN_SESSIONS
2012-05-16 00:02:02 +00:00
PPPDEBUG ( LOG_DEBUG , ( " pppoe: input for unknown session 0x%x, sending PADT \n " , session ) ) ;
2007-12-19 20:47:22 +00:00
pppoe_send_padt ( netif , session , shost ) ;
2007-08-16 18:12:20 +00:00
# endif
2007-12-19 20:47:22 +00:00
goto drop ;
}
2007-08-16 18:12:20 +00:00
2007-12-19 20:47:22 +00:00
plen = ntohs ( ph - > plen ) ;
2007-08-16 18:12:20 +00:00
2015-04-26 21:42:18 +00:00
if ( pbuf_header ( pb , - ( s16_t ) ( PPPOE_HEADERLEN ) ) ! = 0 ) {
2007-12-19 20:47:22 +00:00
/* bail out */
2010-02-22 20:16:39 +00:00
PPPDEBUG ( LOG_ERR , ( " pppoe_data_input: pbuf_header PPPOE_HEADERLEN failed \n " ) ) ;
2007-12-19 20:47:22 +00:00
LINK_STATS_INC ( link . lenerr ) ;
goto drop ;
}
2007-08-16 18:12:20 +00:00
2010-02-22 20:16:39 +00:00
PPPDEBUG ( LOG_DEBUG , ( " pppoe_data_input: %c%c% " U16_F " : pkthdr.len=%d, pppoe.len=%d \n " ,
2007-12-19 20:47:22 +00:00
sc - > sc_ethif - > name [ 0 ] , sc - > sc_ethif - > name [ 1 ] , sc - > sc_ethif - > num ,
pb - > len , plen ) ) ;
2007-08-16 18:12:20 +00:00
2015-04-12 18:08:01 +00:00
if ( pb - > tot_len < plen ) {
2007-12-19 20:47:22 +00:00
goto drop ;
}
2007-08-16 18:12:20 +00:00
2012-06-12 21:28:09 +00:00
/* Dispatch the packet thereby consuming it. */
ppp_input ( sc - > pcb , pb ) ;
2007-12-19 20:47:22 +00:00
return ;
2007-08-16 18:12:20 +00:00
drop :
2007-12-19 20:47:22 +00:00
pbuf_free ( pb ) ;
2007-08-16 18:12:20 +00:00
}
static err_t
pppoe_output ( struct pppoe_softc * sc , struct pbuf * pb )
{
2007-12-19 20:47:22 +00:00
struct eth_hdr * ethhdr ;
u16_t etype ;
err_t res ;
2007-08-16 18:12:20 +00:00
2007-12-19 20:47:22 +00:00
if ( ! sc - > sc_ethif ) {
pbuf_free ( pb ) ;
return ERR_IF ;
}
2007-08-16 18:12:20 +00:00
2012-07-15 12:56:30 +00:00
/* make room for Ethernet header - should not fail */
2015-04-26 21:42:18 +00:00
if ( pbuf_header ( pb , ( s16_t ) ( sizeof ( struct eth_hdr ) ) ) ! = 0 ) {
2012-07-15 12:56:30 +00:00
/* bail out */
PPPDEBUG ( LOG_ERR , ( " pppoe: %c%c% " U16_F " : pppoe_output: could not allocate room for Ethernet header \n " , sc - > sc_ethif - > name [ 0 ] , sc - > sc_ethif - > name [ 1 ] , sc - > sc_ethif - > num ) ) ;
LINK_STATS_INC ( link . lenerr ) ;
pbuf_free ( pb ) ;
return ERR_BUF ;
}
2007-12-19 20:47:22 +00:00
ethhdr = ( struct eth_hdr * ) pb - > payload ;
etype = sc - > sc_state = = PPPOE_STATE_SESSION ? ETHTYPE_PPPOE : ETHTYPE_PPPOEDISC ;
ethhdr - > type = htons ( etype ) ;
2012-06-02 18:46:52 +00:00
MEMCPY ( & ethhdr - > dest . addr , & sc - > sc_dest . addr , sizeof ( ethhdr - > dest . addr ) ) ;
MEMCPY ( & ethhdr - > src . addr , & sc - > sc_ethif - > hwaddr , sizeof ( ethhdr - > src . addr ) ) ;
2007-08-16 18:12:20 +00:00
2010-02-22 20:16:39 +00:00
PPPDEBUG ( LOG_DEBUG , ( " pppoe: %c%c% " U16_F " (%x) state=%d, session=0x%x output -> %02 " X16_F " :%02 " X16_F " :%02 " X16_F " :%02 " X16_F " :%02 " X16_F " :%02 " X16_F " , len=%d \n " ,
2007-12-19 20:47:22 +00:00
sc - > sc_ethif - > name [ 0 ] , sc - > sc_ethif - > name [ 1 ] , sc - > sc_ethif - > num , etype ,
sc - > sc_state , sc - > sc_session ,
sc - > sc_dest . addr [ 0 ] , sc - > sc_dest . addr [ 1 ] , sc - > sc_dest . addr [ 2 ] , sc - > sc_dest . addr [ 3 ] , sc - > sc_dest . addr [ 4 ] , sc - > sc_dest . addr [ 5 ] ,
pb - > tot_len ) ) ;
2007-08-16 18:12:20 +00:00
2007-12-19 20:47:22 +00:00
res = sc - > sc_ethif - > linkoutput ( sc - > sc_ethif , pb ) ;
2007-08-16 18:12:20 +00:00
2007-12-19 20:47:22 +00:00
pbuf_free ( pb ) ;
2007-08-16 18:12:20 +00:00
2007-12-19 20:47:22 +00:00
return res ;
2007-08-16 18:12:20 +00:00
}
static err_t
pppoe_send_padi ( struct pppoe_softc * sc )
{
2007-12-19 20:47:22 +00:00
struct pbuf * pb ;
u8_t * p ;
2010-05-16 14:11:53 +00:00
int len ;
# ifdef PPPOE_TODO
int l1 = 0 , l2 = 0 ; /* XXX: gcc */
# endif /* PPPOE_TODO */
2007-12-19 20:47:22 +00:00
if ( sc - > sc_state > PPPOE_STATE_PADI_SENT ) {
2010-02-22 20:16:39 +00:00
PPPDEBUG ( LOG_ERR , ( " ERROR: pppoe_send_padi in state %d " , sc - > sc_state ) ) ;
2007-12-19 20:47:22 +00:00
}
/* calculate length of frame (excluding ethernet header + pppoe header) */
len = 2 + 2 + 2 + 2 + sizeof sc ; /* service name tag is required, host unique is send too */
2010-05-16 14:11:53 +00:00
# ifdef PPPOE_TODO
2007-12-19 20:47:22 +00:00
if ( sc - > sc_service_name ! = NULL ) {
2010-02-05 10:08:41 +00:00
l1 = ( int ) strlen ( sc - > sc_service_name ) ;
2007-12-19 20:47:22 +00:00
len + = l1 ;
}
if ( sc - > sc_concentrator_name ! = NULL ) {
2010-02-05 10:08:41 +00:00
l2 = ( int ) strlen ( sc - > sc_concentrator_name ) ;
2007-12-19 20:47:22 +00:00
len + = 2 + 2 + l2 ;
}
2010-05-16 14:11:53 +00:00
# endif /* PPPOE_TODO */
2010-01-24 13:19:34 +00:00
LWIP_ASSERT ( " sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff " ,
sizeof ( struct eth_hdr ) + PPPOE_HEADERLEN + len < = 0xffff ) ;
2007-12-19 20:47:22 +00:00
/* allocate a buffer */
2012-07-15 12:56:30 +00:00
pb = pbuf_alloc ( PBUF_LINK , ( u16_t ) ( PPPOE_HEADERLEN + len ) , PBUF_RAM ) ;
2007-12-19 20:47:22 +00:00
if ( ! pb ) {
return ERR_MEM ;
}
2010-01-24 13:19:34 +00:00
LWIP_ASSERT ( " pb->tot_len == pb->len " , pb - > tot_len = = pb - > len ) ;
2007-12-19 20:47:22 +00:00
2012-07-15 12:56:30 +00:00
p = ( u8_t * ) pb - > payload ;
2007-12-19 20:47:22 +00:00
/* fill in pkt */
2010-01-24 13:19:34 +00:00
PPPOE_ADD_HEADER ( p , PPPOE_CODE_PADI , 0 , ( u16_t ) len ) ;
2007-12-19 20:47:22 +00:00
PPPOE_ADD_16 ( p , PPPOE_TAG_SNAME ) ;
2010-05-16 14:11:53 +00:00
# ifdef PPPOE_TODO
2007-12-19 20:47:22 +00:00
if ( sc - > sc_service_name ! = NULL ) {
PPPOE_ADD_16 ( p , l1 ) ;
2008-01-26 16:11:39 +00:00
MEMCPY ( p , sc - > sc_service_name , l1 ) ;
2007-12-19 20:47:22 +00:00
p + = l1 ;
2010-05-16 14:11:53 +00:00
} else
# endif /* PPPOE_TODO */
{
2007-12-19 20:47:22 +00:00
PPPOE_ADD_16 ( p , 0 ) ;
}
2010-05-16 14:11:53 +00:00
# ifdef PPPOE_TODO
2007-12-19 20:47:22 +00:00
if ( sc - > sc_concentrator_name ! = NULL ) {
PPPOE_ADD_16 ( p , PPPOE_TAG_ACNAME ) ;
PPPOE_ADD_16 ( p , l2 ) ;
2008-01-26 16:11:39 +00:00
MEMCPY ( p , sc - > sc_concentrator_name , l2 ) ;
2007-12-19 20:47:22 +00:00
p + = l2 ;
}
2010-05-16 14:11:53 +00:00
# endif /* PPPOE_TODO */
2007-12-19 20:47:22 +00:00
PPPOE_ADD_16 ( p , PPPOE_TAG_HUNIQUE ) ;
PPPOE_ADD_16 ( p , sizeof ( sc ) ) ;
2008-01-26 16:11:39 +00:00
MEMCPY ( p , & sc , sizeof sc ) ;
2007-12-19 20:47:22 +00:00
/* send pkt */
return pppoe_output ( sc , pb ) ;
2007-08-16 18:12:20 +00:00
}
static void
pppoe_timeout ( void * arg )
{
2012-07-15 13:07:07 +00:00
u32_t retry_wait ;
int err ;
2007-12-19 20:47:22 +00:00
struct pppoe_softc * sc = ( struct pppoe_softc * ) arg ;
2010-02-22 20:16:39 +00:00
PPPDEBUG ( LOG_DEBUG , ( " pppoe: %c%c% " U16_F " : timeout \n " , sc - > sc_ethif - > name [ 0 ] , sc - > sc_ethif - > name [ 1 ] , sc - > sc_ethif - > num ) ) ;
2007-12-19 20:47:22 +00:00
switch ( sc - > sc_state ) {
case PPPOE_STATE_PADI_SENT :
/*
* We have two basic ways of retrying :
* - Quick retry mode : try a few times in short sequence
* - Slow retry mode : we already had a connection successfully
* established and will try infinitely ( without user
* intervention )
* We only enter slow retry mode if IFF_LINK1 ( aka autodial )
* is not set .
*/
2012-07-16 18:09:49 +00:00
if ( sc - > sc_padi_retried < 0xff ) {
2012-06-06 23:48:12 +00:00
sc - > sc_padi_retried + + ;
2012-07-15 13:07:07 +00:00
}
2012-06-09 23:08:37 +00:00
if ( ! sc - > pcb - > settings . persist & & sc - > sc_padi_retried > = PPPOE_DISC_MAXPADI ) {
2007-08-16 18:12:20 +00:00
#if 0
2007-12-19 20:47:22 +00:00
if ( ( sc - > sc_sppp . pp_if . if_flags & IFF_LINK1 ) = = 0 ) {
/* slow retry mode */
retry_wait = PPPOE_SLOW_RETRY ;
} else
2007-08-16 18:12:20 +00:00
# endif
2007-12-19 20:47:22 +00:00
{
pppoe_abort_connect ( sc ) ;
return ;
}
}
2012-07-15 13:07:07 +00:00
/* initialize for quick retry mode */
retry_wait = LWIP_MIN ( PPPOE_DISC_TIMEOUT * sc - > sc_padi_retried , PPPOE_SLOW_RETRY ) ;
2007-12-19 20:47:22 +00:00
if ( ( err = pppoe_send_padi ( sc ) ) ! = 0 ) {
sc - > sc_padi_retried - - ;
2010-02-22 20:16:39 +00:00
PPPDEBUG ( LOG_DEBUG , ( " pppoe: %c%c% " U16_F " : failed to transmit PADI, error=%d \n " , sc - > sc_ethif - > name [ 0 ] , sc - > sc_ethif - > name [ 1 ] , sc - > sc_ethif - > num , err ) ) ;
2007-12-19 20:47:22 +00:00
}
2009-12-31 17:18:09 +00:00
sys_timeout ( retry_wait , pppoe_timeout , sc ) ;
2007-12-19 20:47:22 +00:00
break ;
case PPPOE_STATE_PADR_SENT :
sc - > sc_padr_retried + + ;
if ( sc - > sc_padr_retried > = PPPOE_DISC_MAXPADR ) {
2008-01-26 16:11:39 +00:00
MEMCPY ( & sc - > sc_dest , ethbroadcast . addr , sizeof ( sc - > sc_dest ) ) ;
2007-12-19 20:47:22 +00:00
sc - > sc_state = PPPOE_STATE_PADI_SENT ;
sc - > sc_padr_retried = 0 ;
if ( ( err = pppoe_send_padi ( sc ) ) ! = 0 ) {
2010-02-22 20:16:39 +00:00
PPPDEBUG ( LOG_DEBUG , ( " pppoe: %c%c% " U16_F " : failed to send PADI, error=%d \n " , sc - > sc_ethif - > name [ 0 ] , sc - > sc_ethif - > name [ 1 ] , sc - > sc_ethif - > num , err ) ) ;
2007-12-19 20:47:22 +00:00
}
2009-12-31 17:18:09 +00:00
sys_timeout ( PPPOE_DISC_TIMEOUT * ( 1 + sc - > sc_padi_retried ) , pppoe_timeout , sc ) ;
2007-12-19 20:47:22 +00:00
return ;
}
if ( ( err = pppoe_send_padr ( sc ) ) ! = 0 ) {
sc - > sc_padr_retried - - ;
2010-02-22 20:16:39 +00:00
PPPDEBUG ( LOG_DEBUG , ( " pppoe: %c%c% " U16_F " : failed to send PADR, error=%d \n " , sc - > sc_ethif - > name [ 0 ] , sc - > sc_ethif - > name [ 1 ] , sc - > sc_ethif - > num , err ) ) ;
2007-12-19 20:47:22 +00:00
}
2009-12-31 17:18:09 +00:00
sys_timeout ( PPPOE_DISC_TIMEOUT * ( 1 + sc - > sc_padr_retried ) , pppoe_timeout , sc ) ;
2007-12-19 20:47:22 +00:00
break ;
default :
return ; /* all done, work in peace */
}
2007-08-16 18:12:20 +00:00
}
/* Start a connection (i.e. initiate discovery phase) */
2015-02-19 22:25:21 +00:00
static err_t
pppoe_connect ( ppp_pcb * ppp , void * ctx )
2007-08-16 18:12:20 +00:00
{
2007-12-19 20:47:22 +00:00
int err ;
2015-02-19 22:25:21 +00:00
struct pppoe_softc * sc = ( struct pppoe_softc * ) ctx ;
2015-02-15 23:24:17 +00:00
lcp_options * lcp_wo ;
lcp_options * lcp_ao ;
2015-03-08 21:20:19 +00:00
# if PPP_IPV4_SUPPORT && VJ_SUPPORT
2015-02-15 23:24:17 +00:00
ipcp_options * ipcp_wo ;
ipcp_options * ipcp_ao ;
2015-03-08 21:20:19 +00:00
# endif /* PPP_IPV4_SUPPORT && VJ_SUPPORT */
2007-08-16 18:12:20 +00:00
2007-12-19 20:47:22 +00:00
if ( sc - > sc_state ! = PPPOE_STATE_INITIAL ) {
return EBUSY ;
}
2007-08-16 18:12:20 +00:00
2012-06-06 22:46:19 +00:00
/* stop any timer */
sys_untimeout ( pppoe_timeout , sc ) ;
sc - > sc_session = 0 ;
sc - > sc_padi_retried = 0 ;
sc - > sc_padr_retried = 0 ;
2007-08-16 18:12:20 +00:00
# ifdef PPPOE_SERVER
2007-12-19 20:47:22 +00:00
/* wait PADI if IFF_PASSIVE */
if ( ( sc - > sc_sppp . pp_if . if_flags & IFF_PASSIVE ) ) {
return 0 ;
}
2007-08-16 18:12:20 +00:00
# endif
2015-02-15 10:25:37 +00:00
ppp_clear ( ppp ) ;
2015-02-15 23:24:17 +00:00
lcp_wo = & ppp - > lcp_wantoptions ;
lcp_wo - > mru = sc - > sc_ethif - > mtu - PPPOE_HEADERLEN - 2 ; /* two byte PPP protocol discriminator, then IP data */
lcp_wo - > neg_asyncmap = 0 ;
lcp_wo - > neg_pcompression = 0 ;
lcp_wo - > neg_accompression = 0 ;
lcp_ao = & ppp - > lcp_allowoptions ;
lcp_ao - > mru = sc - > sc_ethif - > mtu - PPPOE_HEADERLEN - 2 ; /* two byte PPP protocol discriminator, then IP data */
lcp_ao - > neg_asyncmap = 0 ;
lcp_ao - > neg_pcompression = 0 ;
lcp_ao - > neg_accompression = 0 ;
2015-03-08 21:20:19 +00:00
# if PPP_IPV4_SUPPORT && VJ_SUPPORT
2015-02-15 23:24:17 +00:00
ipcp_wo = & ppp - > ipcp_wantoptions ;
ipcp_wo - > neg_vj = 0 ;
ipcp_wo - > old_vj = 0 ;
ipcp_ao = & ppp - > ipcp_allowoptions ;
ipcp_ao - > neg_vj = 0 ;
ipcp_ao - > old_vj = 0 ;
2015-03-08 21:20:19 +00:00
# endif /* PPP_IPV4_SUPPORT && VJ_SUPPORT */
2015-02-15 10:25:37 +00:00
2007-12-19 20:47:22 +00:00
/* save state, in case we fail to send PADI */
sc - > sc_state = PPPOE_STATE_PADI_SENT ;
2012-05-16 00:02:02 +00:00
if ( ( err = pppoe_send_padi ( sc ) ) ! = 0 ) {
PPPDEBUG ( LOG_DEBUG , ( " pppoe: %c%c% " U16_F " : failed to send PADI, error=%d \n " , sc - > sc_ethif - > name [ 0 ] , sc - > sc_ethif - > name [ 1 ] , sc - > sc_ethif - > num , err ) ) ;
}
2009-12-31 17:18:09 +00:00
sys_timeout ( PPPOE_DISC_TIMEOUT , pppoe_timeout , sc ) ;
2007-12-19 20:47:22 +00:00
return err ;
2007-08-16 18:12:20 +00:00
}
/* disconnect */
2015-02-15 09:18:02 +00:00
static void
2015-02-19 22:25:21 +00:00
pppoe_disconnect ( ppp_pcb * ppp , void * ctx )
2007-08-16 18:12:20 +00:00
{
2015-02-19 22:25:21 +00:00
struct pppoe_softc * sc = ( struct pppoe_softc * ) ctx ;
2007-12-19 20:47:22 +00:00
if ( sc - > sc_state < PPPOE_STATE_SESSION ) {
2012-08-17 21:42:14 +00:00
return ;
2007-12-19 20:47:22 +00:00
}
2012-07-24 20:50:17 +00:00
PPPDEBUG ( LOG_DEBUG , ( " pppoe: %c%c% " U16_F " : disconnecting \n " , sc - > sc_ethif - > name [ 0 ] , sc - > sc_ethif - > name [ 1 ] , sc - > sc_ethif - > num ) ) ;
2012-08-17 21:42:14 +00:00
pppoe_send_padt ( sc - > sc_ethif , sc - > sc_session , ( const u8_t * ) & sc - > sc_dest ) ;
2012-07-24 20:50:17 +00:00
2007-12-19 20:47:22 +00:00
/* cleanup softc */
sc - > sc_state = PPPOE_STATE_INITIAL ;
2008-01-26 16:11:39 +00:00
MEMCPY ( & sc - > sc_dest , ethbroadcast . addr , sizeof ( sc - > sc_dest ) ) ;
2007-12-19 20:47:22 +00:00
sc - > sc_ac_cookie_len = 0 ;
2007-08-16 18:12:20 +00:00
# ifdef PPPOE_SERVER
2007-12-19 20:47:22 +00:00
if ( sc - > sc_hunique ) {
mem_free ( sc - > sc_hunique ) ;
sc - > sc_hunique = NULL ;
}
sc - > sc_hunique_len = 0 ;
2007-08-16 18:12:20 +00:00
# endif
2007-12-19 20:47:22 +00:00
sc - > sc_session = 0 ;
2012-06-06 22:46:19 +00:00
sc - > sc_padi_retried = 0 ;
sc - > sc_padr_retried = 0 ;
2007-08-16 18:12:20 +00:00
2015-02-19 22:25:21 +00:00
ppp_link_end ( ppp ) ; /* notify upper layers */
2012-08-17 21:42:14 +00:00
return ;
2007-08-16 18:12:20 +00:00
}
/* Connection attempt aborted */
static void
pppoe_abort_connect ( struct pppoe_softc * sc )
{
2012-05-16 00:02:02 +00:00
PPPDEBUG ( LOG_DEBUG , ( " %c%c% " U16_F " : could not establish connection \n " , sc - > sc_ethif - > name [ 0 ] , sc - > sc_ethif - > name [ 1 ] , sc - > sc_ethif - > num ) ) ;
2007-08-16 18:12:20 +00:00
2007-12-19 20:47:22 +00:00
/* clear connection state */
sc - > sc_state = PPPOE_STATE_INITIAL ;
2012-06-06 22:46:19 +00:00
MEMCPY ( & sc - > sc_dest , ethbroadcast . addr , sizeof ( sc - > sc_dest ) ) ;
sc - > sc_ac_cookie_len = 0 ;
sc - > sc_session = 0 ;
sc - > sc_padi_retried = 0 ;
sc - > sc_padr_retried = 0 ;
2015-02-14 23:35:45 +00:00
ppp_link_failed ( sc - > pcb ) ; /* notify upper layers */
2007-08-16 18:12:20 +00:00
}
/* Send a PADR packet */
static err_t
pppoe_send_padr ( struct pppoe_softc * sc )
{
2007-12-19 20:47:22 +00:00
struct pbuf * pb ;
u8_t * p ;
2010-05-16 14:11:53 +00:00
size_t len ;
# ifdef PPPOE_TODO
size_t l1 = 0 ; /* XXX: gcc */
# endif /* PPPOE_TODO */
2007-12-19 20:47:22 +00:00
if ( sc - > sc_state ! = PPPOE_STATE_PADR_SENT ) {
return ERR_CONN ;
}
len = 2 + 2 + 2 + 2 + sizeof ( sc ) ; /* service name, host unique */
2010-05-16 14:11:53 +00:00
# ifdef PPPOE_TODO
2007-12-19 20:47:22 +00:00
if ( sc - > sc_service_name ! = NULL ) { /* service name tag maybe empty */
l1 = strlen ( sc - > sc_service_name ) ;
len + = l1 ;
}
2010-05-16 14:11:53 +00:00
# endif /* PPPOE_TODO */
2007-12-19 20:47:22 +00:00
if ( sc - > sc_ac_cookie_len > 0 ) {
len + = 2 + 2 + sc - > sc_ac_cookie_len ; /* AC cookie */
}
2010-01-24 13:19:34 +00:00
LWIP_ASSERT ( " sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff " ,
sizeof ( struct eth_hdr ) + PPPOE_HEADERLEN + len < = 0xffff ) ;
2012-07-15 12:56:30 +00:00
pb = pbuf_alloc ( PBUF_LINK , ( u16_t ) ( PPPOE_HEADERLEN + len ) , PBUF_RAM ) ;
2007-12-19 20:47:22 +00:00
if ( ! pb ) {
return ERR_MEM ;
}
2010-01-24 13:19:34 +00:00
LWIP_ASSERT ( " pb->tot_len == pb->len " , pb - > tot_len = = pb - > len ) ;
2012-07-15 12:56:30 +00:00
p = ( u8_t * ) pb - > payload ;
2007-12-19 20:47:22 +00:00
PPPOE_ADD_HEADER ( p , PPPOE_CODE_PADR , 0 , len ) ;
PPPOE_ADD_16 ( p , PPPOE_TAG_SNAME ) ;
2010-05-16 14:11:53 +00:00
# ifdef PPPOE_TODO
2007-12-19 20:47:22 +00:00
if ( sc - > sc_service_name ! = NULL ) {
PPPOE_ADD_16 ( p , l1 ) ;
2008-01-26 16:11:39 +00:00
MEMCPY ( p , sc - > sc_service_name , l1 ) ;
2007-12-19 20:47:22 +00:00
p + = l1 ;
2010-05-16 14:11:53 +00:00
} else
# endif /* PPPOE_TODO */
{
2007-12-19 20:47:22 +00:00
PPPOE_ADD_16 ( p , 0 ) ;
}
if ( sc - > sc_ac_cookie_len > 0 ) {
PPPOE_ADD_16 ( p , PPPOE_TAG_ACCOOKIE ) ;
PPPOE_ADD_16 ( p , sc - > sc_ac_cookie_len ) ;
2008-01-26 16:11:39 +00:00
MEMCPY ( p , sc - > sc_ac_cookie , sc - > sc_ac_cookie_len ) ;
2007-12-19 20:47:22 +00:00
p + = sc - > sc_ac_cookie_len ;
}
PPPOE_ADD_16 ( p , PPPOE_TAG_HUNIQUE ) ;
PPPOE_ADD_16 ( p , sizeof ( sc ) ) ;
2008-01-26 16:11:39 +00:00
MEMCPY ( p , & sc , sizeof sc ) ;
2007-12-19 20:47:22 +00:00
return pppoe_output ( sc , pb ) ;
2007-08-16 18:12:20 +00:00
}
/* send a PADT packet */
static err_t
pppoe_send_padt ( struct netif * outgoing_if , u_int session , const u8_t * dest )
{
2007-12-19 20:47:22 +00:00
struct pbuf * pb ;
struct eth_hdr * ethhdr ;
err_t res ;
u8_t * p ;
2007-08-16 18:12:20 +00:00
2012-07-15 12:56:30 +00:00
pb = pbuf_alloc ( PBUF_LINK , ( u16_t ) ( PPPOE_HEADERLEN ) , PBUF_RAM ) ;
2007-12-19 20:47:22 +00:00
if ( ! pb ) {
return ERR_MEM ;
}
2010-01-24 13:19:34 +00:00
LWIP_ASSERT ( " pb->tot_len == pb->len " , pb - > tot_len = = pb - > len ) ;
2007-08-16 18:12:20 +00:00
2015-04-26 21:42:18 +00:00
pbuf_header ( pb , ( s16_t ) sizeof ( struct eth_hdr ) ) ;
2007-12-19 20:47:22 +00:00
ethhdr = ( struct eth_hdr * ) pb - > payload ;
2010-05-16 15:57:42 +00:00
ethhdr - > type = PP_HTONS ( ETHTYPE_PPPOEDISC ) ;
2012-06-02 18:46:52 +00:00
MEMCPY ( & ethhdr - > dest . addr , dest , sizeof ( ethhdr - > dest . addr ) ) ;
MEMCPY ( & ethhdr - > src . addr , & outgoing_if - > hwaddr , sizeof ( ethhdr - > src . addr ) ) ;
2007-08-16 18:12:20 +00:00
2007-12-19 20:47:22 +00:00
p = ( u8_t * ) ( ethhdr + 1 ) ;
PPPOE_ADD_HEADER ( p , PPPOE_CODE_PADT , session , 0 ) ;
2007-08-16 18:12:20 +00:00
2007-12-19 20:47:22 +00:00
res = outgoing_if - > linkoutput ( outgoing_if , pb ) ;
2007-08-16 18:12:20 +00:00
2007-12-19 20:47:22 +00:00
pbuf_free ( pb ) ;
2007-08-16 18:12:20 +00:00
2007-12-19 20:47:22 +00:00
return res ;
2007-08-16 18:12:20 +00:00
}
# ifdef PPPOE_SERVER
static err_t
pppoe_send_pado ( struct pppoe_softc * sc )
{
2007-12-19 20:47:22 +00:00
struct pbuf * pb ;
u8_t * p ;
size_t len ;
if ( sc - > sc_state ! = PPPOE_STATE_PADO_SENT ) {
return ERR_CONN ;
}
/* calc length */
len = 0 ;
/* include ac_cookie */
len + = 2 + 2 + sizeof ( sc ) ;
/* include hunique */
len + = 2 + 2 + sc - > sc_hunique_len ;
2012-07-15 12:56:30 +00:00
pb = pbuf_alloc ( PBUF_LINK , ( u16_t ) ( PPPOE_HEADERLEN + len ) , PBUF_RAM ) ;
2007-12-19 20:47:22 +00:00
if ( ! pb ) {
return ERR_MEM ;
}
2010-01-24 13:19:34 +00:00
LWIP_ASSERT ( " pb->tot_len == pb->len " , pb - > tot_len = = pb - > len ) ;
2012-07-15 12:56:30 +00:00
p = ( u8_t * ) pb - > payload ;
2007-12-19 20:47:22 +00:00
PPPOE_ADD_HEADER ( p , PPPOE_CODE_PADO , 0 , len ) ;
PPPOE_ADD_16 ( p , PPPOE_TAG_ACCOOKIE ) ;
PPPOE_ADD_16 ( p , sizeof ( sc ) ) ;
2008-01-26 16:11:39 +00:00
MEMCPY ( p , & sc , sizeof ( sc ) ) ;
2007-12-19 20:47:22 +00:00
p + = sizeof ( sc ) ;
PPPOE_ADD_16 ( p , PPPOE_TAG_HUNIQUE ) ;
PPPOE_ADD_16 ( p , sc - > sc_hunique_len ) ;
2008-01-26 16:11:39 +00:00
MEMCPY ( p , sc - > sc_hunique , sc - > sc_hunique_len ) ;
2007-12-19 20:47:22 +00:00
return pppoe_output ( sc , pb ) ;
2007-08-16 18:12:20 +00:00
}
static err_t
pppoe_send_pads ( struct pppoe_softc * sc )
{
2007-12-19 20:47:22 +00:00
struct pbuf * pb ;
u8_t * p ;
size_t len , l1 = 0 ; /* XXX: gcc */
if ( sc - > sc_state ! = PPPOE_STATE_PADO_SENT ) {
return ERR_CONN ;
}
sc - > sc_session = mono_time . tv_sec % 0xff + 1 ;
/* calc length */
len = 0 ;
/* include hunique */
len + = 2 + 2 + 2 + 2 + sc - > sc_hunique_len ; /* service name, host unique*/
if ( sc - > sc_service_name ! = NULL ) { /* service name tag maybe empty */
l1 = strlen ( sc - > sc_service_name ) ;
len + = l1 ;
}
2012-07-15 12:56:30 +00:00
pb = pbuf_alloc ( PBUF_LINK , ( u16_t ) ( PPPOE_HEADERLEN + len ) , PBUF_RAM ) ;
2007-12-19 20:47:22 +00:00
if ( ! pb ) {
return ERR_MEM ;
}
2010-01-24 13:19:34 +00:00
LWIP_ASSERT ( " pb->tot_len == pb->len " , pb - > tot_len = = pb - > len ) ;
2012-07-15 12:56:30 +00:00
p = ( u8_t * ) pb - > payload ;
2007-12-19 20:47:22 +00:00
PPPOE_ADD_HEADER ( p , PPPOE_CODE_PADS , sc - > sc_session , len ) ;
PPPOE_ADD_16 ( p , PPPOE_TAG_SNAME ) ;
if ( sc - > sc_service_name ! = NULL ) {
PPPOE_ADD_16 ( p , l1 ) ;
2008-01-26 16:11:39 +00:00
MEMCPY ( p , sc - > sc_service_name , l1 ) ;
2007-12-19 20:47:22 +00:00
p + = l1 ;
} else {
PPPOE_ADD_16 ( p , 0 ) ;
}
PPPOE_ADD_16 ( p , PPPOE_TAG_HUNIQUE ) ;
PPPOE_ADD_16 ( p , sc - > sc_hunique_len ) ;
2008-01-26 16:11:39 +00:00
MEMCPY ( p , sc - > sc_hunique , sc - > sc_hunique_len ) ;
2007-12-19 20:47:22 +00:00
return pppoe_output ( sc , pb ) ;
2007-08-16 18:12:20 +00:00
}
# endif
2015-02-15 10:04:09 +00:00
static err_t
2007-08-16 18:12:20 +00:00
pppoe_xmit ( struct pppoe_softc * sc , struct pbuf * pb )
{
2007-12-19 20:47:22 +00:00
u8_t * p ;
size_t len ;
/* are we ready to process data yet? */
if ( sc - > sc_state < PPPOE_STATE_SESSION ) {
/*sppp_flush(&sc->sc_sppp.pp_if);*/
pbuf_free ( pb ) ;
return ERR_CONN ;
}
len = pb - > tot_len ;
2012-07-15 12:56:30 +00:00
/* make room for PPPoE header - should not fail */
2015-04-26 21:42:18 +00:00
if ( pbuf_header ( pb , ( s16_t ) ( PPPOE_HEADERLEN ) ) ! = 0 ) {
2007-12-19 20:47:22 +00:00
/* bail out */
2012-07-15 12:56:30 +00:00
PPPDEBUG ( LOG_ERR , ( " pppoe: %c%c% " U16_F " : pppoe_xmit: could not allocate room for PPPoE header \n " , sc - > sc_ethif - > name [ 0 ] , sc - > sc_ethif - > name [ 1 ] , sc - > sc_ethif - > num ) ) ;
2007-12-19 20:47:22 +00:00
LINK_STATS_INC ( link . lenerr ) ;
pbuf_free ( pb ) ;
return ERR_BUF ;
2012-06-22 15:03:59 +00:00
}
2007-12-19 20:47:22 +00:00
2012-07-15 12:56:30 +00:00
p = ( u8_t * ) pb - > payload ;
2007-12-19 20:47:22 +00:00
PPPOE_ADD_HEADER ( p , 0 , sc - > sc_session , len ) ;
return pppoe_output ( sc , pb ) ;
2007-08-16 18:12:20 +00:00
}
#if 0 /*def PFIL_HOOKS*/
static int
pppoe_ifattach_hook ( void * arg , struct pbuf * * mp , struct netif * ifp , int dir )
{
2007-12-19 20:47:22 +00:00
struct pppoe_softc * sc ;
int s ;
if ( mp ! = ( struct pbuf * * ) PFIL_IFNET_DETACH ) {
return 0 ;
}
LIST_FOREACH ( sc , & pppoe_softc_list , sc_list ) {
if ( sc - > sc_ethif ! = ifp ) {
continue ;
}
if ( sc - > sc_sppp . pp_if . if_flags & IFF_UP ) {
sc - > sc_sppp . pp_if . if_flags & = ~ ( IFF_UP | IFF_RUNNING ) ;
2012-05-16 00:02:02 +00:00
PPPDEBUG ( LOG_DEBUG , ( " %c%c% " U16_F " : ethernet interface detached, going down \n " ,
sc - > sc_ethif - > name [ 0 ] , sc - > sc_ethif - > name [ 1 ] , sc - > sc_ethif - > num ) ) ;
2007-12-19 20:47:22 +00:00
}
sc - > sc_ethif = NULL ;
pppoe_clear_softc ( sc , " ethernet interface detached " ) ;
}
return 0 ;
2007-08-16 18:12:20 +00:00
}
# endif
2015-03-01 23:16:25 +00:00
#if 0 /* UNUSED */
2007-08-16 18:12:20 +00:00
static void
pppoe_clear_softc ( struct pppoe_softc * sc , const char * message )
{
2008-03-16 08:53:58 +00:00
LWIP_UNUSED_ARG ( message ) ;
2007-12-19 20:47:22 +00:00
/* stop timer */
2009-12-31 17:18:09 +00:00
sys_untimeout ( pppoe_timeout , sc ) ;
2010-02-22 20:16:39 +00:00
PPPDEBUG ( LOG_DEBUG , ( " pppoe: %c%c% " U16_F " : session 0x%x terminated, %s \n " , sc - > sc_ethif - > name [ 0 ] , sc - > sc_ethif - > name [ 1 ] , sc - > sc_ethif - > num , sc - > sc_session , message ) ) ;
2007-12-19 20:47:22 +00:00
/* fix our state */
sc - > sc_state = PPPOE_STATE_INITIAL ;
/* notify upper layers */
2015-03-01 23:16:25 +00:00
ppp_link_end ( sc - > pcb ) ; /* /!\ dangerous /!\ */
2007-12-19 20:47:22 +00:00
/* clean up softc */
2008-01-26 16:11:39 +00:00
MEMCPY ( & sc - > sc_dest , ethbroadcast . addr , sizeof ( sc - > sc_dest ) ) ;
2007-12-19 20:47:22 +00:00
sc - > sc_ac_cookie_len = 0 ;
sc - > sc_session = 0 ;
2012-06-06 22:46:19 +00:00
sc - > sc_padi_retried = 0 ;
sc - > sc_padr_retried = 0 ;
2007-08-16 18:12:20 +00:00
}
2015-03-01 23:16:25 +00:00
# endif /* UNUSED */
2012-06-03 14:38:26 +00:00
# endif /* PPP_SUPPORT && PPPOE_SUPPORT */