LwIP with PPP & Ethernet integration

Dependents:   NetworkingCoreLib

This is the mbed port of the LwIP stack: http://savannah.nongnu.org/projects/lwip/

It includes contributed content from NXP's port for LPCxxxx devices: http://www.lpcware.com/content/project/lightweight-ip-lwip-networking-stack

Licence

LwIP is licenced under the BSD licence:

Copyright (c) 2001-2004 Swedish Institute of Computer Science. 
All rights reserved. 
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. The name of the author may not be used to endorse or promote products 
derived from this software without specific prior written permission. 
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
Committer:
donatien
Date:
Fri May 25 08:56:35 2012 +0000
Revision:
2:1a87f74b8e3b
Parent:
0:8e01dca41002
Removed compilation of EMAC driver when using PPP

Who changed what in which revision?

UserRevisionLine numberNew contents of line
donatien 0:8e01dca41002 1 /*****************************************************************************
donatien 0:8e01dca41002 2 * ppp_oe.c - PPP Over Ethernet implementation for lwIP.
donatien 0:8e01dca41002 3 *
donatien 0:8e01dca41002 4 * Copyright (c) 2006 by Marc Boucher, Services Informatiques (MBSI) inc.
donatien 0:8e01dca41002 5 *
donatien 0:8e01dca41002 6 * The authors hereby grant permission to use, copy, modify, distribute,
donatien 0:8e01dca41002 7 * and license this software and its documentation for any purpose, provided
donatien 0:8e01dca41002 8 * that existing copyright notices are retained in all copies and that this
donatien 0:8e01dca41002 9 * notice and the following disclaimer are included verbatim in any
donatien 0:8e01dca41002 10 * distributions. No written agreement, license, or royalty fee is required
donatien 0:8e01dca41002 11 * for any of the authorized uses.
donatien 0:8e01dca41002 12 *
donatien 0:8e01dca41002 13 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
donatien 0:8e01dca41002 14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
donatien 0:8e01dca41002 15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
donatien 0:8e01dca41002 16 * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
donatien 0:8e01dca41002 17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
donatien 0:8e01dca41002 18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
donatien 0:8e01dca41002 19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
donatien 0:8e01dca41002 20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
donatien 0:8e01dca41002 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
donatien 0:8e01dca41002 22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
donatien 0:8e01dca41002 23 *
donatien 0:8e01dca41002 24 ******************************************************************************
donatien 0:8e01dca41002 25 * REVISION HISTORY
donatien 0:8e01dca41002 26 *
donatien 0:8e01dca41002 27 * 06-01-01 Marc Boucher <marc@mbsi.ca>
donatien 0:8e01dca41002 28 * Ported to lwIP.
donatien 0:8e01dca41002 29 *****************************************************************************/
donatien 0:8e01dca41002 30
donatien 0:8e01dca41002 31
donatien 0:8e01dca41002 32
donatien 0:8e01dca41002 33 /* based on NetBSD: if_pppoe.c,v 1.64 2006/01/31 23:50:15 martin Exp */
donatien 0:8e01dca41002 34
donatien 0:8e01dca41002 35 /*-
donatien 0:8e01dca41002 36 * Copyright (c) 2002 The NetBSD Foundation, Inc.
donatien 0:8e01dca41002 37 * All rights reserved.
donatien 0:8e01dca41002 38 *
donatien 0:8e01dca41002 39 * This code is derived from software contributed to The NetBSD Foundation
donatien 0:8e01dca41002 40 * by Martin Husemann <martin@NetBSD.org>.
donatien 0:8e01dca41002 41 *
donatien 0:8e01dca41002 42 * Redistribution and use in source and binary forms, with or without
donatien 0:8e01dca41002 43 * modification, are permitted provided that the following conditions
donatien 0:8e01dca41002 44 * are met:
donatien 0:8e01dca41002 45 * 1. Redistributions of source code must retain the above copyright
donatien 0:8e01dca41002 46 * notice, this list of conditions and the following disclaimer.
donatien 0:8e01dca41002 47 * 2. Redistributions in binary form must reproduce the above copyright
donatien 0:8e01dca41002 48 * notice, this list of conditions and the following disclaimer in the
donatien 0:8e01dca41002 49 * documentation and/or other materials provided with the distribution.
donatien 0:8e01dca41002 50 * 3. All advertising materials mentioning features or use of this software
donatien 0:8e01dca41002 51 * must display the following acknowledgement:
donatien 0:8e01dca41002 52 * This product includes software developed by the NetBSD
donatien 0:8e01dca41002 53 * Foundation, Inc. and its contributors.
donatien 0:8e01dca41002 54 * 4. Neither the name of The NetBSD Foundation nor the names of its
donatien 0:8e01dca41002 55 * contributors may be used to endorse or promote products derived
donatien 0:8e01dca41002 56 * from this software without specific prior written permission.
donatien 0:8e01dca41002 57 *
donatien 0:8e01dca41002 58 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
donatien 0:8e01dca41002 59 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
donatien 0:8e01dca41002 60 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
donatien 0:8e01dca41002 61 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
donatien 0:8e01dca41002 62 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
donatien 0:8e01dca41002 63 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
donatien 0:8e01dca41002 64 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
donatien 0:8e01dca41002 65 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
donatien 0:8e01dca41002 66 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
donatien 0:8e01dca41002 67 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
donatien 0:8e01dca41002 68 * POSSIBILITY OF SUCH DAMAGE.
donatien 0:8e01dca41002 69 */
donatien 0:8e01dca41002 70
donatien 0:8e01dca41002 71 #include "lwip/opt.h"
donatien 0:8e01dca41002 72
donatien 0:8e01dca41002 73 #if PPPOE_SUPPORT /* don't build if not configured for use in lwipopts.h */
donatien 0:8e01dca41002 74
donatien 0:8e01dca41002 75 #include "netif/ppp_oe.h"
donatien 0:8e01dca41002 76
donatien 0:8e01dca41002 77 #include "ppp.h"
donatien 0:8e01dca41002 78 #include "pppdebug.h"
donatien 0:8e01dca41002 79
donatien 0:8e01dca41002 80 #include "lwip/timers.h"
donatien 0:8e01dca41002 81 #include "lwip/memp.h"
donatien 0:8e01dca41002 82
donatien 0:8e01dca41002 83 #include <string.h>
donatien 0:8e01dca41002 84 #include <stdio.h>
donatien 0:8e01dca41002 85
donatien 0:8e01dca41002 86
donatien 0:8e01dca41002 87 /* Add a 16 bit unsigned value to a buffer pointed to by PTR */
donatien 0:8e01dca41002 88 #define PPPOE_ADD_16(PTR, VAL) \
donatien 0:8e01dca41002 89 *(PTR)++ = (u8_t)((VAL) / 256); \
donatien 0:8e01dca41002 90 *(PTR)++ = (u8_t)((VAL) % 256)
donatien 0:8e01dca41002 91
donatien 0:8e01dca41002 92 /* Add a complete PPPoE header to the buffer pointed to by PTR */
donatien 0:8e01dca41002 93 #define PPPOE_ADD_HEADER(PTR, CODE, SESS, LEN) \
donatien 0:8e01dca41002 94 *(PTR)++ = PPPOE_VERTYPE; \
donatien 0:8e01dca41002 95 *(PTR)++ = (CODE); \
donatien 0:8e01dca41002 96 PPPOE_ADD_16(PTR, SESS); \
donatien 0:8e01dca41002 97 PPPOE_ADD_16(PTR, LEN)
donatien 0:8e01dca41002 98
donatien 0:8e01dca41002 99 #define PPPOE_DISC_TIMEOUT (5*1000) /* base for quick timeout calculation */
donatien 0:8e01dca41002 100 #define PPPOE_SLOW_RETRY (60*1000) /* persistent retry interval */
donatien 0:8e01dca41002 101 #define PPPOE_DISC_MAXPADI 4 /* retry PADI four times (quickly) */
donatien 0:8e01dca41002 102 #define PPPOE_DISC_MAXPADR 2 /* retry PADR twice */
donatien 0:8e01dca41002 103
donatien 0:8e01dca41002 104 #ifdef PPPOE_SERVER
donatien 0:8e01dca41002 105 #error "PPPOE_SERVER is not yet supported under lwIP!"
donatien 0:8e01dca41002 106 /* from if_spppsubr.c */
donatien 0:8e01dca41002 107 #define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */
donatien 0:8e01dca41002 108 #endif
donatien 0:8e01dca41002 109
donatien 0:8e01dca41002 110 #ifndef PPPOE_ERRORSTRING_LEN
donatien 0:8e01dca41002 111 #define PPPOE_ERRORSTRING_LEN 64
donatien 0:8e01dca41002 112 #endif
donatien 0:8e01dca41002 113 static char pppoe_error_tmp[PPPOE_ERRORSTRING_LEN];
donatien 0:8e01dca41002 114
donatien 0:8e01dca41002 115
donatien 0:8e01dca41002 116 /* input routines */
donatien 0:8e01dca41002 117 static void pppoe_dispatch_disc_pkt(struct netif *, struct pbuf *);
donatien 0:8e01dca41002 118
donatien 0:8e01dca41002 119 /* management routines */
donatien 0:8e01dca41002 120 static int pppoe_do_disconnect(struct pppoe_softc *);
donatien 0:8e01dca41002 121 static void pppoe_abort_connect(struct pppoe_softc *);
donatien 0:8e01dca41002 122 static void pppoe_clear_softc(struct pppoe_softc *, const char *);
donatien 0:8e01dca41002 123
donatien 0:8e01dca41002 124 /* internal timeout handling */
donatien 0:8e01dca41002 125 static void pppoe_timeout(void *);
donatien 0:8e01dca41002 126
donatien 0:8e01dca41002 127 /* sending actual protocol controll packets */
donatien 0:8e01dca41002 128 static err_t pppoe_send_padi(struct pppoe_softc *);
donatien 0:8e01dca41002 129 static err_t pppoe_send_padr(struct pppoe_softc *);
donatien 0:8e01dca41002 130 #ifdef PPPOE_SERVER
donatien 0:8e01dca41002 131 static err_t pppoe_send_pado(struct pppoe_softc *);
donatien 0:8e01dca41002 132 static err_t pppoe_send_pads(struct pppoe_softc *);
donatien 0:8e01dca41002 133 #endif
donatien 0:8e01dca41002 134 static err_t pppoe_send_padt(struct netif *, u_int, const u8_t *);
donatien 0:8e01dca41002 135
donatien 0:8e01dca41002 136 /* internal helper functions */
donatien 0:8e01dca41002 137 static struct pppoe_softc * pppoe_find_softc_by_session(u_int, struct netif *);
donatien 0:8e01dca41002 138 static struct pppoe_softc * pppoe_find_softc_by_hunique(u8_t *, size_t, struct netif *);
donatien 0:8e01dca41002 139
donatien 0:8e01dca41002 140 /** linked list of created pppoe interfaces */
donatien 0:8e01dca41002 141 static struct pppoe_softc *pppoe_softc_list;
donatien 0:8e01dca41002 142
donatien 0:8e01dca41002 143 err_t
donatien 0:8e01dca41002 144 pppoe_create(struct netif *ethif, int pd, void (*linkStatusCB)(int pd, int up), struct pppoe_softc **scptr)
donatien 0:8e01dca41002 145 {
donatien 0:8e01dca41002 146 struct pppoe_softc *sc;
donatien 0:8e01dca41002 147
donatien 0:8e01dca41002 148 sc = (struct pppoe_softc *)memp_malloc(MEMP_PPPOE_IF);
donatien 0:8e01dca41002 149 if (sc == NULL) {
donatien 0:8e01dca41002 150 *scptr = NULL;
donatien 0:8e01dca41002 151 return ERR_MEM;
donatien 0:8e01dca41002 152 }
donatien 0:8e01dca41002 153 memset(sc, 0, sizeof(struct pppoe_softc));
donatien 0:8e01dca41002 154
donatien 0:8e01dca41002 155 /* changed to real address later */
donatien 0:8e01dca41002 156 MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest));
donatien 0:8e01dca41002 157
donatien 0:8e01dca41002 158 sc->sc_pd = pd;
donatien 0:8e01dca41002 159 sc->sc_linkStatusCB = linkStatusCB;
donatien 0:8e01dca41002 160 sc->sc_ethif = ethif;
donatien 0:8e01dca41002 161
donatien 0:8e01dca41002 162 /* put the new interface at the head of the list */
donatien 0:8e01dca41002 163 sc->next = pppoe_softc_list;
donatien 0:8e01dca41002 164 pppoe_softc_list = sc;
donatien 0:8e01dca41002 165
donatien 0:8e01dca41002 166 *scptr = sc;
donatien 0:8e01dca41002 167
donatien 0:8e01dca41002 168 return ERR_OK;
donatien 0:8e01dca41002 169 }
donatien 0:8e01dca41002 170
donatien 0:8e01dca41002 171 err_t
donatien 0:8e01dca41002 172 pppoe_destroy(struct netif *ifp)
donatien 0:8e01dca41002 173 {
donatien 0:8e01dca41002 174 struct pppoe_softc *sc, *prev = NULL;
donatien 0:8e01dca41002 175
donatien 0:8e01dca41002 176 for (sc = pppoe_softc_list; sc != NULL; prev = sc, sc = sc->next) {
donatien 0:8e01dca41002 177 if (sc->sc_ethif == ifp) {
donatien 0:8e01dca41002 178 break;
donatien 0:8e01dca41002 179 }
donatien 0:8e01dca41002 180 }
donatien 0:8e01dca41002 181
donatien 0:8e01dca41002 182 if(!(sc && (sc->sc_ethif == ifp))) {
donatien 0:8e01dca41002 183 return ERR_IF;
donatien 0:8e01dca41002 184 }
donatien 0:8e01dca41002 185
donatien 0:8e01dca41002 186 sys_untimeout(pppoe_timeout, sc);
donatien 0:8e01dca41002 187 if (prev == NULL) {
donatien 0:8e01dca41002 188 /* remove sc from the head of the list */
donatien 0:8e01dca41002 189 pppoe_softc_list = sc->next;
donatien 0:8e01dca41002 190 } else {
donatien 0:8e01dca41002 191 /* remove sc from the list */
donatien 0:8e01dca41002 192 prev->next = sc->next;
donatien 0:8e01dca41002 193 }
donatien 0:8e01dca41002 194
donatien 0:8e01dca41002 195 #ifdef PPPOE_TODO
donatien 0:8e01dca41002 196 if (sc->sc_concentrator_name) {
donatien 0:8e01dca41002 197 mem_free(sc->sc_concentrator_name);
donatien 0:8e01dca41002 198 }
donatien 0:8e01dca41002 199 if (sc->sc_service_name) {
donatien 0:8e01dca41002 200 mem_free(sc->sc_service_name);
donatien 0:8e01dca41002 201 }
donatien 0:8e01dca41002 202 #endif /* PPPOE_TODO */
donatien 0:8e01dca41002 203 memp_free(MEMP_PPPOE_IF, sc);
donatien 0:8e01dca41002 204
donatien 0:8e01dca41002 205 return ERR_OK;
donatien 0:8e01dca41002 206 }
donatien 0:8e01dca41002 207
donatien 0:8e01dca41002 208 /*
donatien 0:8e01dca41002 209 * Find the interface handling the specified session.
donatien 0:8e01dca41002 210 * Note: O(number of sessions open), this is a client-side only, mean
donatien 0:8e01dca41002 211 * and lean implementation, so number of open sessions typically should
donatien 0:8e01dca41002 212 * be 1.
donatien 0:8e01dca41002 213 */
donatien 0:8e01dca41002 214 static struct pppoe_softc *
donatien 0:8e01dca41002 215 pppoe_find_softc_by_session(u_int session, struct netif *rcvif)
donatien 0:8e01dca41002 216 {
donatien 0:8e01dca41002 217 struct pppoe_softc *sc;
donatien 0:8e01dca41002 218
donatien 0:8e01dca41002 219 if (session == 0) {
donatien 0:8e01dca41002 220 return NULL;
donatien 0:8e01dca41002 221 }
donatien 0:8e01dca41002 222
donatien 0:8e01dca41002 223 for (sc = pppoe_softc_list; sc != NULL; sc = sc->next) {
donatien 0:8e01dca41002 224 if (sc->sc_state == PPPOE_STATE_SESSION
donatien 0:8e01dca41002 225 && sc->sc_session == session) {
donatien 0:8e01dca41002 226 if (sc->sc_ethif == rcvif) {
donatien 0:8e01dca41002 227 return sc;
donatien 0:8e01dca41002 228 } else {
donatien 0:8e01dca41002 229 return NULL;
donatien 0:8e01dca41002 230 }
donatien 0:8e01dca41002 231 }
donatien 0:8e01dca41002 232 }
donatien 0:8e01dca41002 233 return NULL;
donatien 0:8e01dca41002 234 }
donatien 0:8e01dca41002 235
donatien 0:8e01dca41002 236 /* Check host unique token passed and return appropriate softc pointer,
donatien 0:8e01dca41002 237 * or NULL if token is bogus. */
donatien 0:8e01dca41002 238 static struct pppoe_softc *
donatien 0:8e01dca41002 239 pppoe_find_softc_by_hunique(u8_t *token, size_t len, struct netif *rcvif)
donatien 0:8e01dca41002 240 {
donatien 0:8e01dca41002 241 struct pppoe_softc *sc, *t;
donatien 0:8e01dca41002 242
donatien 0:8e01dca41002 243 if (pppoe_softc_list == NULL) {
donatien 0:8e01dca41002 244 return NULL;
donatien 0:8e01dca41002 245 }
donatien 0:8e01dca41002 246
donatien 0:8e01dca41002 247 if (len != sizeof sc) {
donatien 0:8e01dca41002 248 return NULL;
donatien 0:8e01dca41002 249 }
donatien 0:8e01dca41002 250 MEMCPY(&t, token, len);
donatien 0:8e01dca41002 251
donatien 0:8e01dca41002 252 for (sc = pppoe_softc_list; sc != NULL; sc = sc->next) {
donatien 0:8e01dca41002 253 if (sc == t) {
donatien 0:8e01dca41002 254 break;
donatien 0:8e01dca41002 255 }
donatien 0:8e01dca41002 256 }
donatien 0:8e01dca41002 257
donatien 0:8e01dca41002 258 if (sc == NULL) {
donatien 0:8e01dca41002 259 PPPDEBUG(LOG_DEBUG, ("pppoe: alien host unique tag, no session found\n"));
donatien 0:8e01dca41002 260 return NULL;
donatien 0:8e01dca41002 261 }
donatien 0:8e01dca41002 262
donatien 0:8e01dca41002 263 /* should be safe to access *sc now */
donatien 0:8e01dca41002 264 if (sc->sc_state < PPPOE_STATE_PADI_SENT || sc->sc_state >= PPPOE_STATE_SESSION) {
donatien 0:8e01dca41002 265 printf("%c%c%"U16_F": host unique tag found, but it belongs to a connection in state %d\n",
donatien 0:8e01dca41002 266 sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_state);
donatien 0:8e01dca41002 267 return NULL;
donatien 0:8e01dca41002 268 }
donatien 0:8e01dca41002 269 if (sc->sc_ethif != rcvif) {
donatien 0:8e01dca41002 270 printf("%c%c%"U16_F": wrong interface, not accepting host unique\n",
donatien 0:8e01dca41002 271 sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num);
donatien 0:8e01dca41002 272 return NULL;
donatien 0:8e01dca41002 273 }
donatien 0:8e01dca41002 274 return sc;
donatien 0:8e01dca41002 275 }
donatien 0:8e01dca41002 276
donatien 0:8e01dca41002 277 static void
donatien 0:8e01dca41002 278 pppoe_linkstatus_up(struct pppoe_softc *sc)
donatien 0:8e01dca41002 279 {
donatien 0:8e01dca41002 280 sc->sc_linkStatusCB(sc->sc_pd, 1);
donatien 0:8e01dca41002 281 }
donatien 0:8e01dca41002 282
donatien 0:8e01dca41002 283 /* analyze and handle a single received packet while not in session state */
donatien 0:8e01dca41002 284 static void
donatien 0:8e01dca41002 285 pppoe_dispatch_disc_pkt(struct netif *netif, struct pbuf *pb)
donatien 0:8e01dca41002 286 {
donatien 0:8e01dca41002 287 u16_t tag, len;
donatien 0:8e01dca41002 288 u16_t session, plen;
donatien 0:8e01dca41002 289 struct pppoe_softc *sc;
donatien 0:8e01dca41002 290 const char *err_msg;
donatien 0:8e01dca41002 291 char devname[6];
donatien 0:8e01dca41002 292 u8_t *ac_cookie;
donatien 0:8e01dca41002 293 u16_t ac_cookie_len;
donatien 0:8e01dca41002 294 #ifdef PPPOE_SERVER
donatien 0:8e01dca41002 295 u8_t *hunique;
donatien 0:8e01dca41002 296 size_t hunique_len;
donatien 0:8e01dca41002 297 #endif
donatien 0:8e01dca41002 298 struct pppoehdr *ph;
donatien 0:8e01dca41002 299 struct pppoetag pt;
donatien 0:8e01dca41002 300 int off, err, errortag;
donatien 0:8e01dca41002 301 struct eth_hdr *ethhdr;
donatien 0:8e01dca41002 302
donatien 0:8e01dca41002 303 pb = pppSingleBuf(pb);
donatien 0:8e01dca41002 304
donatien 0:8e01dca41002 305 strcpy(devname, "pppoe"); /* as long as we don't know which instance */
donatien 0:8e01dca41002 306 err_msg = NULL;
donatien 0:8e01dca41002 307 errortag = 0;
donatien 0:8e01dca41002 308 if (pb->len < sizeof(*ethhdr)) {
donatien 0:8e01dca41002 309 goto done;
donatien 0:8e01dca41002 310 }
donatien 0:8e01dca41002 311 ethhdr = (struct eth_hdr *)pb->payload;
donatien 0:8e01dca41002 312 off = sizeof(*ethhdr);
donatien 0:8e01dca41002 313
donatien 0:8e01dca41002 314 ac_cookie = NULL;
donatien 0:8e01dca41002 315 ac_cookie_len = 0;
donatien 0:8e01dca41002 316 #ifdef PPPOE_SERVER
donatien 0:8e01dca41002 317 hunique = NULL;
donatien 0:8e01dca41002 318 hunique_len = 0;
donatien 0:8e01dca41002 319 #endif
donatien 0:8e01dca41002 320 session = 0;
donatien 0:8e01dca41002 321 if (pb->len - off < PPPOE_HEADERLEN) {
donatien 0:8e01dca41002 322 printf("pppoe: packet too short: %d\n", pb->len);
donatien 0:8e01dca41002 323 goto done;
donatien 0:8e01dca41002 324 }
donatien 0:8e01dca41002 325
donatien 0:8e01dca41002 326 ph = (struct pppoehdr *) (ethhdr + 1);
donatien 0:8e01dca41002 327 if (ph->vertype != PPPOE_VERTYPE) {
donatien 0:8e01dca41002 328 printf("pppoe: unknown version/type packet: 0x%x\n", ph->vertype);
donatien 0:8e01dca41002 329 goto done;
donatien 0:8e01dca41002 330 }
donatien 0:8e01dca41002 331 session = ntohs(ph->session);
donatien 0:8e01dca41002 332 plen = ntohs(ph->plen);
donatien 0:8e01dca41002 333 off += sizeof(*ph);
donatien 0:8e01dca41002 334
donatien 0:8e01dca41002 335 if (plen + off > pb->len) {
donatien 0:8e01dca41002 336 printf("pppoe: packet content does not fit: data available = %d, packet size = %u\n",
donatien 0:8e01dca41002 337 pb->len - off, plen);
donatien 0:8e01dca41002 338 goto done;
donatien 0:8e01dca41002 339 }
donatien 0:8e01dca41002 340 if(pb->tot_len == pb->len) {
donatien 0:8e01dca41002 341 pb->tot_len = pb->len = (u16_t)off + plen; /* ignore trailing garbage */
donatien 0:8e01dca41002 342 }
donatien 0:8e01dca41002 343 tag = 0;
donatien 0:8e01dca41002 344 len = 0;
donatien 0:8e01dca41002 345 sc = NULL;
donatien 0:8e01dca41002 346 while (off + sizeof(pt) <= pb->len) {
donatien 0:8e01dca41002 347 MEMCPY(&pt, (u8_t*)pb->payload + off, sizeof(pt));
donatien 0:8e01dca41002 348 tag = ntohs(pt.tag);
donatien 0:8e01dca41002 349 len = ntohs(pt.len);
donatien 0:8e01dca41002 350 if (off + sizeof(pt) + len > pb->len) {
donatien 0:8e01dca41002 351 printf("pppoe: tag 0x%x len 0x%x is too long\n", tag, len);
donatien 0:8e01dca41002 352 goto done;
donatien 0:8e01dca41002 353 }
donatien 0:8e01dca41002 354 switch (tag) {
donatien 0:8e01dca41002 355 case PPPOE_TAG_EOL:
donatien 0:8e01dca41002 356 goto breakbreak;
donatien 0:8e01dca41002 357 case PPPOE_TAG_SNAME:
donatien 0:8e01dca41002 358 break; /* ignored */
donatien 0:8e01dca41002 359 case PPPOE_TAG_ACNAME:
donatien 0:8e01dca41002 360 break; /* ignored */
donatien 0:8e01dca41002 361 case PPPOE_TAG_HUNIQUE:
donatien 0:8e01dca41002 362 if (sc != NULL) {
donatien 0:8e01dca41002 363 break;
donatien 0:8e01dca41002 364 }
donatien 0:8e01dca41002 365 #ifdef PPPOE_SERVER
donatien 0:8e01dca41002 366 hunique = (u8_t*)pb->payload + off + sizeof(pt);
donatien 0:8e01dca41002 367 hunique_len = len;
donatien 0:8e01dca41002 368 #endif
donatien 0:8e01dca41002 369 sc = pppoe_find_softc_by_hunique((u8_t*)pb->payload + off + sizeof(pt), len, netif);
donatien 0:8e01dca41002 370 if (sc != NULL) {
donatien 0:8e01dca41002 371 snprintf(devname, sizeof(devname), "%c%c%"U16_F, sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num);
donatien 0:8e01dca41002 372 }
donatien 0:8e01dca41002 373 break;
donatien 0:8e01dca41002 374 case PPPOE_TAG_ACCOOKIE:
donatien 0:8e01dca41002 375 if (ac_cookie == NULL) {
donatien 0:8e01dca41002 376 ac_cookie = (u8_t*)pb->payload + off + sizeof(pt);
donatien 0:8e01dca41002 377 ac_cookie_len = len;
donatien 0:8e01dca41002 378 }
donatien 0:8e01dca41002 379 break;
donatien 0:8e01dca41002 380 case PPPOE_TAG_SNAME_ERR:
donatien 0:8e01dca41002 381 err_msg = "SERVICE NAME ERROR";
donatien 0:8e01dca41002 382 errortag = 1;
donatien 0:8e01dca41002 383 break;
donatien 0:8e01dca41002 384 case PPPOE_TAG_ACSYS_ERR:
donatien 0:8e01dca41002 385 err_msg = "AC SYSTEM ERROR";
donatien 0:8e01dca41002 386 errortag = 1;
donatien 0:8e01dca41002 387 break;
donatien 0:8e01dca41002 388 case PPPOE_TAG_GENERIC_ERR:
donatien 0:8e01dca41002 389 err_msg = "GENERIC ERROR";
donatien 0:8e01dca41002 390 errortag = 1;
donatien 0:8e01dca41002 391 break;
donatien 0:8e01dca41002 392 }
donatien 0:8e01dca41002 393 if (err_msg) {
donatien 0:8e01dca41002 394 if (errortag && len) {
donatien 0:8e01dca41002 395 u16_t error_len = LWIP_MIN(len, sizeof(pppoe_error_tmp)-1);
donatien 0:8e01dca41002 396 strncpy(pppoe_error_tmp, (char*)pb->payload + off + sizeof(pt), error_len);
donatien 0:8e01dca41002 397 pppoe_error_tmp[error_len-1] = '\0';
donatien 0:8e01dca41002 398 printf("%s: %s: %s\n", devname, err_msg, pppoe_error_tmp);
donatien 0:8e01dca41002 399 } else {
donatien 0:8e01dca41002 400 printf("%s: %s\n", devname, err_msg);
donatien 0:8e01dca41002 401 }
donatien 0:8e01dca41002 402 if (errortag) {
donatien 0:8e01dca41002 403 goto done;
donatien 0:8e01dca41002 404 }
donatien 0:8e01dca41002 405 }
donatien 0:8e01dca41002 406 off += sizeof(pt) + len;
donatien 0:8e01dca41002 407 }
donatien 0:8e01dca41002 408
donatien 0:8e01dca41002 409 breakbreak:;
donatien 0:8e01dca41002 410 switch (ph->code) {
donatien 0:8e01dca41002 411 case PPPOE_CODE_PADI:
donatien 0:8e01dca41002 412 #ifdef PPPOE_SERVER
donatien 0:8e01dca41002 413 /*
donatien 0:8e01dca41002 414 * got service name, concentrator name, and/or host unique.
donatien 0:8e01dca41002 415 * ignore if we have no interfaces with IFF_PASSIVE|IFF_UP.
donatien 0:8e01dca41002 416 */
donatien 0:8e01dca41002 417 if (LIST_EMPTY(&pppoe_softc_list)) {
donatien 0:8e01dca41002 418 goto done;
donatien 0:8e01dca41002 419 }
donatien 0:8e01dca41002 420 LIST_FOREACH(sc, &pppoe_softc_list, sc_list) {
donatien 0:8e01dca41002 421 if (!(sc->sc_sppp.pp_if.if_flags & IFF_UP)) {
donatien 0:8e01dca41002 422 continue;
donatien 0:8e01dca41002 423 }
donatien 0:8e01dca41002 424 if (!(sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) {
donatien 0:8e01dca41002 425 continue;
donatien 0:8e01dca41002 426 }
donatien 0:8e01dca41002 427 if (sc->sc_state == PPPOE_STATE_INITIAL) {
donatien 0:8e01dca41002 428 break;
donatien 0:8e01dca41002 429 }
donatien 0:8e01dca41002 430 }
donatien 0:8e01dca41002 431 if (sc == NULL) {
donatien 0:8e01dca41002 432 /* printf("pppoe: free passive interface is not found\n"); */
donatien 0:8e01dca41002 433 goto done;
donatien 0:8e01dca41002 434 }
donatien 0:8e01dca41002 435 if (hunique) {
donatien 0:8e01dca41002 436 if (sc->sc_hunique) {
donatien 0:8e01dca41002 437 mem_free(sc->sc_hunique);
donatien 0:8e01dca41002 438 }
donatien 0:8e01dca41002 439 sc->sc_hunique = mem_malloc(hunique_len);
donatien 0:8e01dca41002 440 if (sc->sc_hunique == NULL) {
donatien 0:8e01dca41002 441 goto done;
donatien 0:8e01dca41002 442 }
donatien 0:8e01dca41002 443 sc->sc_hunique_len = hunique_len;
donatien 0:8e01dca41002 444 MEMCPY(sc->sc_hunique, hunique, hunique_len);
donatien 0:8e01dca41002 445 }
donatien 0:8e01dca41002 446 MEMCPY(&sc->sc_dest, eh->ether_shost, sizeof sc->sc_dest);
donatien 0:8e01dca41002 447 sc->sc_state = PPPOE_STATE_PADO_SENT;
donatien 0:8e01dca41002 448 pppoe_send_pado(sc);
donatien 0:8e01dca41002 449 break;
donatien 0:8e01dca41002 450 #endif /* PPPOE_SERVER */
donatien 0:8e01dca41002 451 case PPPOE_CODE_PADR:
donatien 0:8e01dca41002 452 #ifdef PPPOE_SERVER
donatien 0:8e01dca41002 453 /*
donatien 0:8e01dca41002 454 * get sc from ac_cookie if IFF_PASSIVE
donatien 0:8e01dca41002 455 */
donatien 0:8e01dca41002 456 if (ac_cookie == NULL) {
donatien 0:8e01dca41002 457 /* be quiet if there is not a single pppoe instance */
donatien 0:8e01dca41002 458 printf("pppoe: received PADR but not includes ac_cookie\n");
donatien 0:8e01dca41002 459 goto done;
donatien 0:8e01dca41002 460 }
donatien 0:8e01dca41002 461 sc = pppoe_find_softc_by_hunique(ac_cookie, ac_cookie_len, netif);
donatien 0:8e01dca41002 462 if (sc == NULL) {
donatien 0:8e01dca41002 463 /* be quiet if there is not a single pppoe instance */
donatien 0:8e01dca41002 464 if (!LIST_EMPTY(&pppoe_softc_list)) {
donatien 0:8e01dca41002 465 printf("pppoe: received PADR but could not find request for it\n");
donatien 0:8e01dca41002 466 }
donatien 0:8e01dca41002 467 goto done;
donatien 0:8e01dca41002 468 }
donatien 0:8e01dca41002 469 if (sc->sc_state != PPPOE_STATE_PADO_SENT) {
donatien 0:8e01dca41002 470 printf("%c%c%"U16_F": received unexpected PADR\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num);
donatien 0:8e01dca41002 471 goto done;
donatien 0:8e01dca41002 472 }
donatien 0:8e01dca41002 473 if (hunique) {
donatien 0:8e01dca41002 474 if (sc->sc_hunique) {
donatien 0:8e01dca41002 475 mem_free(sc->sc_hunique);
donatien 0:8e01dca41002 476 }
donatien 0:8e01dca41002 477 sc->sc_hunique = mem_malloc(hunique_len);
donatien 0:8e01dca41002 478 if (sc->sc_hunique == NULL) {
donatien 0:8e01dca41002 479 goto done;
donatien 0:8e01dca41002 480 }
donatien 0:8e01dca41002 481 sc->sc_hunique_len = hunique_len;
donatien 0:8e01dca41002 482 MEMCPY(sc->sc_hunique, hunique, hunique_len);
donatien 0:8e01dca41002 483 }
donatien 0:8e01dca41002 484 pppoe_send_pads(sc);
donatien 0:8e01dca41002 485 sc->sc_state = PPPOE_STATE_SESSION;
donatien 0:8e01dca41002 486 pppoe_linkstatus_up(sc); /* notify upper layers */
donatien 0:8e01dca41002 487 break;
donatien 0:8e01dca41002 488 #else
donatien 0:8e01dca41002 489 /* ignore, we are no access concentrator */
donatien 0:8e01dca41002 490 goto done;
donatien 0:8e01dca41002 491 #endif /* PPPOE_SERVER */
donatien 0:8e01dca41002 492 case PPPOE_CODE_PADO:
donatien 0:8e01dca41002 493 if (sc == NULL) {
donatien 0:8e01dca41002 494 /* be quiet if there is not a single pppoe instance */
donatien 0:8e01dca41002 495 if (pppoe_softc_list != NULL) {
donatien 0:8e01dca41002 496 printf("pppoe: received PADO but could not find request for it\n");
donatien 0:8e01dca41002 497 }
donatien 0:8e01dca41002 498 goto done;
donatien 0:8e01dca41002 499 }
donatien 0:8e01dca41002 500 if (sc->sc_state != PPPOE_STATE_PADI_SENT) {
donatien 0:8e01dca41002 501 printf("%c%c%"U16_F": received unexpected PADO\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num);
donatien 0:8e01dca41002 502 goto done;
donatien 0:8e01dca41002 503 }
donatien 0:8e01dca41002 504 if (ac_cookie) {
donatien 0:8e01dca41002 505 sc->sc_ac_cookie_len = ac_cookie_len;
donatien 0:8e01dca41002 506 MEMCPY(sc->sc_ac_cookie, ac_cookie, ac_cookie_len);
donatien 0:8e01dca41002 507 }
donatien 0:8e01dca41002 508 MEMCPY(&sc->sc_dest, ethhdr->src.addr, sizeof(sc->sc_dest.addr));
donatien 0:8e01dca41002 509 sys_untimeout(pppoe_timeout, sc);
donatien 0:8e01dca41002 510 sc->sc_padr_retried = 0;
donatien 0:8e01dca41002 511 sc->sc_state = PPPOE_STATE_PADR_SENT;
donatien 0:8e01dca41002 512 if ((err = pppoe_send_padr(sc)) != 0) {
donatien 0:8e01dca41002 513 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));
donatien 0:8e01dca41002 514 }
donatien 0:8e01dca41002 515 sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc);
donatien 0:8e01dca41002 516 break;
donatien 0:8e01dca41002 517 case PPPOE_CODE_PADS:
donatien 0:8e01dca41002 518 if (sc == NULL) {
donatien 0:8e01dca41002 519 goto done;
donatien 0:8e01dca41002 520 }
donatien 0:8e01dca41002 521 sc->sc_session = session;
donatien 0:8e01dca41002 522 sys_untimeout(pppoe_timeout, sc);
donatien 0:8e01dca41002 523 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));
donatien 0:8e01dca41002 524 sc->sc_state = PPPOE_STATE_SESSION;
donatien 0:8e01dca41002 525 pppoe_linkstatus_up(sc); /* notify upper layers */
donatien 0:8e01dca41002 526 break;
donatien 0:8e01dca41002 527 case PPPOE_CODE_PADT:
donatien 0:8e01dca41002 528 if (sc == NULL) {
donatien 0:8e01dca41002 529 goto done;
donatien 0:8e01dca41002 530 }
donatien 0:8e01dca41002 531 pppoe_clear_softc(sc, "received PADT");
donatien 0:8e01dca41002 532 break;
donatien 0:8e01dca41002 533 default:
donatien 0:8e01dca41002 534 if(sc) {
donatien 0:8e01dca41002 535 printf("%c%c%"U16_F": unknown code (0x%"X16_F") session = 0x%"X16_F"\n",
donatien 0:8e01dca41002 536 sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num,
donatien 0:8e01dca41002 537 (u16_t)ph->code, session);
donatien 0:8e01dca41002 538 } else {
donatien 0:8e01dca41002 539 printf("pppoe: unknown code (0x%"X16_F") session = 0x%"X16_F"\n", (u16_t)ph->code, session);
donatien 0:8e01dca41002 540 }
donatien 0:8e01dca41002 541 break;
donatien 0:8e01dca41002 542 }
donatien 0:8e01dca41002 543
donatien 0:8e01dca41002 544 done:
donatien 0:8e01dca41002 545 pbuf_free(pb);
donatien 0:8e01dca41002 546 return;
donatien 0:8e01dca41002 547 }
donatien 0:8e01dca41002 548
donatien 0:8e01dca41002 549 void
donatien 0:8e01dca41002 550 pppoe_disc_input(struct netif *netif, struct pbuf *p)
donatien 0:8e01dca41002 551 {
donatien 0:8e01dca41002 552 /* avoid error messages if there is not a single pppoe instance */
donatien 0:8e01dca41002 553 if (pppoe_softc_list != NULL) {
donatien 0:8e01dca41002 554 pppoe_dispatch_disc_pkt(netif, p);
donatien 0:8e01dca41002 555 } else {
donatien 0:8e01dca41002 556 pbuf_free(p);
donatien 0:8e01dca41002 557 }
donatien 0:8e01dca41002 558 }
donatien 0:8e01dca41002 559
donatien 0:8e01dca41002 560 void
donatien 0:8e01dca41002 561 pppoe_data_input(struct netif *netif, struct pbuf *pb)
donatien 0:8e01dca41002 562 {
donatien 0:8e01dca41002 563 u16_t session, plen;
donatien 0:8e01dca41002 564 struct pppoe_softc *sc;
donatien 0:8e01dca41002 565 struct pppoehdr *ph;
donatien 0:8e01dca41002 566 #ifdef PPPOE_TERM_UNKNOWN_SESSIONS
donatien 0:8e01dca41002 567 u8_t shost[ETHER_ADDR_LEN];
donatien 0:8e01dca41002 568 #endif
donatien 0:8e01dca41002 569
donatien 0:8e01dca41002 570 #ifdef PPPOE_TERM_UNKNOWN_SESSIONS
donatien 0:8e01dca41002 571 MEMCPY(shost, ((struct eth_hdr *)pb->payload)->src.addr, sizeof(shost));
donatien 0:8e01dca41002 572 #endif
donatien 0:8e01dca41002 573 if (pbuf_header(pb, -(int)sizeof(struct eth_hdr)) != 0) {
donatien 0:8e01dca41002 574 /* bail out */
donatien 0:8e01dca41002 575 PPPDEBUG(LOG_ERR, ("pppoe_data_input: pbuf_header failed\n"));
donatien 0:8e01dca41002 576 LINK_STATS_INC(link.lenerr);
donatien 0:8e01dca41002 577 goto drop;
donatien 0:8e01dca41002 578 }
donatien 0:8e01dca41002 579
donatien 0:8e01dca41002 580 pb = pppSingleBuf (pb);
donatien 0:8e01dca41002 581
donatien 0:8e01dca41002 582 if (pb->len <= PPPOE_HEADERLEN) {
donatien 0:8e01dca41002 583 printf("pppoe (data): dropping too short packet: %d bytes\n", pb->len);
donatien 0:8e01dca41002 584 goto drop;
donatien 0:8e01dca41002 585 }
donatien 0:8e01dca41002 586
donatien 0:8e01dca41002 587 if (pb->len < sizeof(*ph)) {
donatien 0:8e01dca41002 588 printf("pppoe_data_input: could not get PPPoE header\n");
donatien 0:8e01dca41002 589 goto drop;
donatien 0:8e01dca41002 590 }
donatien 0:8e01dca41002 591 ph = (struct pppoehdr *)pb->payload;
donatien 0:8e01dca41002 592
donatien 0:8e01dca41002 593 if (ph->vertype != PPPOE_VERTYPE) {
donatien 0:8e01dca41002 594 printf("pppoe (data): unknown version/type packet: 0x%x\n", ph->vertype);
donatien 0:8e01dca41002 595 goto drop;
donatien 0:8e01dca41002 596 }
donatien 0:8e01dca41002 597 if (ph->code != 0) {
donatien 0:8e01dca41002 598 goto drop;
donatien 0:8e01dca41002 599 }
donatien 0:8e01dca41002 600
donatien 0:8e01dca41002 601 session = ntohs(ph->session);
donatien 0:8e01dca41002 602 sc = pppoe_find_softc_by_session(session, netif);
donatien 0:8e01dca41002 603 if (sc == NULL) {
donatien 0:8e01dca41002 604 #ifdef PPPOE_TERM_UNKNOWN_SESSIONS
donatien 0:8e01dca41002 605 printf("pppoe: input for unknown session 0x%x, sending PADT\n", session);
donatien 0:8e01dca41002 606 pppoe_send_padt(netif, session, shost);
donatien 0:8e01dca41002 607 #endif
donatien 0:8e01dca41002 608 goto drop;
donatien 0:8e01dca41002 609 }
donatien 0:8e01dca41002 610
donatien 0:8e01dca41002 611 plen = ntohs(ph->plen);
donatien 0:8e01dca41002 612
donatien 0:8e01dca41002 613 if (pbuf_header(pb, -(int)(PPPOE_HEADERLEN)) != 0) {
donatien 0:8e01dca41002 614 /* bail out */
donatien 0:8e01dca41002 615 PPPDEBUG(LOG_ERR, ("pppoe_data_input: pbuf_header PPPOE_HEADERLEN failed\n"));
donatien 0:8e01dca41002 616 LINK_STATS_INC(link.lenerr);
donatien 0:8e01dca41002 617 goto drop;
donatien 0:8e01dca41002 618 }
donatien 0:8e01dca41002 619
donatien 0:8e01dca41002 620 PPPDEBUG(LOG_DEBUG, ("pppoe_data_input: %c%c%"U16_F": pkthdr.len=%d, pppoe.len=%d\n",
donatien 0:8e01dca41002 621 sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num,
donatien 0:8e01dca41002 622 pb->len, plen));
donatien 0:8e01dca41002 623
donatien 0:8e01dca41002 624 if (pb->len < plen) {
donatien 0:8e01dca41002 625 goto drop;
donatien 0:8e01dca41002 626 }
donatien 0:8e01dca41002 627
donatien 0:8e01dca41002 628 pppInProcOverEthernet(sc->sc_pd, pb);
donatien 0:8e01dca41002 629
donatien 0:8e01dca41002 630 return;
donatien 0:8e01dca41002 631
donatien 0:8e01dca41002 632 drop:
donatien 0:8e01dca41002 633 pbuf_free(pb);
donatien 0:8e01dca41002 634 }
donatien 0:8e01dca41002 635
donatien 0:8e01dca41002 636 static err_t
donatien 0:8e01dca41002 637 pppoe_output(struct pppoe_softc *sc, struct pbuf *pb)
donatien 0:8e01dca41002 638 {
donatien 0:8e01dca41002 639 struct eth_hdr *ethhdr;
donatien 0:8e01dca41002 640 u16_t etype;
donatien 0:8e01dca41002 641 err_t res;
donatien 0:8e01dca41002 642
donatien 0:8e01dca41002 643 if (!sc->sc_ethif) {
donatien 0:8e01dca41002 644 pbuf_free(pb);
donatien 0:8e01dca41002 645 return ERR_IF;
donatien 0:8e01dca41002 646 }
donatien 0:8e01dca41002 647
donatien 0:8e01dca41002 648 ethhdr = (struct eth_hdr *)pb->payload;
donatien 0:8e01dca41002 649 etype = sc->sc_state == PPPOE_STATE_SESSION ? ETHTYPE_PPPOE : ETHTYPE_PPPOEDISC;
donatien 0:8e01dca41002 650 ethhdr->type = htons(etype);
donatien 0:8e01dca41002 651 MEMCPY(ethhdr->dest.addr, sc->sc_dest.addr, sizeof(ethhdr->dest.addr));
donatien 0:8e01dca41002 652 MEMCPY(ethhdr->src.addr, ((struct eth_addr *)sc->sc_ethif->hwaddr)->addr, sizeof(ethhdr->src.addr));
donatien 0:8e01dca41002 653
donatien 0:8e01dca41002 654 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",
donatien 0:8e01dca41002 655 sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, etype,
donatien 0:8e01dca41002 656 sc->sc_state, sc->sc_session,
donatien 0:8e01dca41002 657 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],
donatien 0:8e01dca41002 658 pb->tot_len));
donatien 0:8e01dca41002 659
donatien 0:8e01dca41002 660 res = sc->sc_ethif->linkoutput(sc->sc_ethif, pb);
donatien 0:8e01dca41002 661
donatien 0:8e01dca41002 662 pbuf_free(pb);
donatien 0:8e01dca41002 663
donatien 0:8e01dca41002 664 return res;
donatien 0:8e01dca41002 665 }
donatien 0:8e01dca41002 666
donatien 0:8e01dca41002 667 static err_t
donatien 0:8e01dca41002 668 pppoe_send_padi(struct pppoe_softc *sc)
donatien 0:8e01dca41002 669 {
donatien 0:8e01dca41002 670 struct pbuf *pb;
donatien 0:8e01dca41002 671 u8_t *p;
donatien 0:8e01dca41002 672 int len;
donatien 0:8e01dca41002 673 #ifdef PPPOE_TODO
donatien 0:8e01dca41002 674 int l1 = 0, l2 = 0; /* XXX: gcc */
donatien 0:8e01dca41002 675 #endif /* PPPOE_TODO */
donatien 0:8e01dca41002 676
donatien 0:8e01dca41002 677 if (sc->sc_state >PPPOE_STATE_PADI_SENT) {
donatien 0:8e01dca41002 678 PPPDEBUG(LOG_ERR, ("ERROR: pppoe_send_padi in state %d", sc->sc_state));
donatien 0:8e01dca41002 679 }
donatien 0:8e01dca41002 680
donatien 0:8e01dca41002 681 /* calculate length of frame (excluding ethernet header + pppoe header) */
donatien 0:8e01dca41002 682 len = 2 + 2 + 2 + 2 + sizeof sc; /* service name tag is required, host unique is send too */
donatien 0:8e01dca41002 683 #ifdef PPPOE_TODO
donatien 0:8e01dca41002 684 if (sc->sc_service_name != NULL) {
donatien 0:8e01dca41002 685 l1 = (int)strlen(sc->sc_service_name);
donatien 0:8e01dca41002 686 len += l1;
donatien 0:8e01dca41002 687 }
donatien 0:8e01dca41002 688 if (sc->sc_concentrator_name != NULL) {
donatien 0:8e01dca41002 689 l2 = (int)strlen(sc->sc_concentrator_name);
donatien 0:8e01dca41002 690 len += 2 + 2 + l2;
donatien 0:8e01dca41002 691 }
donatien 0:8e01dca41002 692 #endif /* PPPOE_TODO */
donatien 0:8e01dca41002 693 LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff",
donatien 0:8e01dca41002 694 sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff);
donatien 0:8e01dca41002 695
donatien 0:8e01dca41002 696 /* allocate a buffer */
donatien 0:8e01dca41002 697 pb = pbuf_alloc(PBUF_LINK, (u16_t)(sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len), PBUF_RAM);
donatien 0:8e01dca41002 698 if (!pb) {
donatien 0:8e01dca41002 699 return ERR_MEM;
donatien 0:8e01dca41002 700 }
donatien 0:8e01dca41002 701 LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len);
donatien 0:8e01dca41002 702
donatien 0:8e01dca41002 703 p = (u8_t*)pb->payload + sizeof (struct eth_hdr);
donatien 0:8e01dca41002 704 /* fill in pkt */
donatien 0:8e01dca41002 705 PPPOE_ADD_HEADER(p, PPPOE_CODE_PADI, 0, (u16_t)len);
donatien 0:8e01dca41002 706 PPPOE_ADD_16(p, PPPOE_TAG_SNAME);
donatien 0:8e01dca41002 707 #ifdef PPPOE_TODO
donatien 0:8e01dca41002 708 if (sc->sc_service_name != NULL) {
donatien 0:8e01dca41002 709 PPPOE_ADD_16(p, l1);
donatien 0:8e01dca41002 710 MEMCPY(p, sc->sc_service_name, l1);
donatien 0:8e01dca41002 711 p += l1;
donatien 0:8e01dca41002 712 } else
donatien 0:8e01dca41002 713 #endif /* PPPOE_TODO */
donatien 0:8e01dca41002 714 {
donatien 0:8e01dca41002 715 PPPOE_ADD_16(p, 0);
donatien 0:8e01dca41002 716 }
donatien 0:8e01dca41002 717 #ifdef PPPOE_TODO
donatien 0:8e01dca41002 718 if (sc->sc_concentrator_name != NULL) {
donatien 0:8e01dca41002 719 PPPOE_ADD_16(p, PPPOE_TAG_ACNAME);
donatien 0:8e01dca41002 720 PPPOE_ADD_16(p, l2);
donatien 0:8e01dca41002 721 MEMCPY(p, sc->sc_concentrator_name, l2);
donatien 0:8e01dca41002 722 p += l2;
donatien 0:8e01dca41002 723 }
donatien 0:8e01dca41002 724 #endif /* PPPOE_TODO */
donatien 0:8e01dca41002 725 PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE);
donatien 0:8e01dca41002 726 PPPOE_ADD_16(p, sizeof(sc));
donatien 0:8e01dca41002 727 MEMCPY(p, &sc, sizeof sc);
donatien 0:8e01dca41002 728
donatien 0:8e01dca41002 729 /* send pkt */
donatien 0:8e01dca41002 730 return pppoe_output(sc, pb);
donatien 0:8e01dca41002 731 }
donatien 0:8e01dca41002 732
donatien 0:8e01dca41002 733 static void
donatien 0:8e01dca41002 734 pppoe_timeout(void *arg)
donatien 0:8e01dca41002 735 {
donatien 0:8e01dca41002 736 int retry_wait, err;
donatien 0:8e01dca41002 737 struct pppoe_softc *sc = (struct pppoe_softc*)arg;
donatien 0:8e01dca41002 738
donatien 0:8e01dca41002 739 PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": timeout\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num));
donatien 0:8e01dca41002 740
donatien 0:8e01dca41002 741 switch (sc->sc_state) {
donatien 0:8e01dca41002 742 case PPPOE_STATE_PADI_SENT:
donatien 0:8e01dca41002 743 /*
donatien 0:8e01dca41002 744 * We have two basic ways of retrying:
donatien 0:8e01dca41002 745 * - Quick retry mode: try a few times in short sequence
donatien 0:8e01dca41002 746 * - Slow retry mode: we already had a connection successfully
donatien 0:8e01dca41002 747 * established and will try infinitely (without user
donatien 0:8e01dca41002 748 * intervention)
donatien 0:8e01dca41002 749 * We only enter slow retry mode if IFF_LINK1 (aka autodial)
donatien 0:8e01dca41002 750 * is not set.
donatien 0:8e01dca41002 751 */
donatien 0:8e01dca41002 752
donatien 0:8e01dca41002 753 /* initialize for quick retry mode */
donatien 0:8e01dca41002 754 retry_wait = PPPOE_DISC_TIMEOUT * (1 + sc->sc_padi_retried);
donatien 0:8e01dca41002 755
donatien 0:8e01dca41002 756 sc->sc_padi_retried++;
donatien 0:8e01dca41002 757 if (sc->sc_padi_retried >= PPPOE_DISC_MAXPADI) {
donatien 0:8e01dca41002 758 #if 0
donatien 0:8e01dca41002 759 if ((sc->sc_sppp.pp_if.if_flags & IFF_LINK1) == 0) {
donatien 0:8e01dca41002 760 /* slow retry mode */
donatien 0:8e01dca41002 761 retry_wait = PPPOE_SLOW_RETRY;
donatien 0:8e01dca41002 762 } else
donatien 0:8e01dca41002 763 #endif
donatien 0:8e01dca41002 764 {
donatien 0:8e01dca41002 765 pppoe_abort_connect(sc);
donatien 0:8e01dca41002 766 return;
donatien 0:8e01dca41002 767 }
donatien 0:8e01dca41002 768 }
donatien 0:8e01dca41002 769 if ((err = pppoe_send_padi(sc)) != 0) {
donatien 0:8e01dca41002 770 sc->sc_padi_retried--;
donatien 0:8e01dca41002 771 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));
donatien 0:8e01dca41002 772 }
donatien 0:8e01dca41002 773 sys_timeout(retry_wait, pppoe_timeout, sc);
donatien 0:8e01dca41002 774 break;
donatien 0:8e01dca41002 775
donatien 0:8e01dca41002 776 case PPPOE_STATE_PADR_SENT:
donatien 0:8e01dca41002 777 sc->sc_padr_retried++;
donatien 0:8e01dca41002 778 if (sc->sc_padr_retried >= PPPOE_DISC_MAXPADR) {
donatien 0:8e01dca41002 779 MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest));
donatien 0:8e01dca41002 780 sc->sc_state = PPPOE_STATE_PADI_SENT;
donatien 0:8e01dca41002 781 sc->sc_padr_retried = 0;
donatien 0:8e01dca41002 782 if ((err = pppoe_send_padi(sc)) != 0) {
donatien 0:8e01dca41002 783 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));
donatien 0:8e01dca41002 784 }
donatien 0:8e01dca41002 785 sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padi_retried), pppoe_timeout, sc);
donatien 0:8e01dca41002 786 return;
donatien 0:8e01dca41002 787 }
donatien 0:8e01dca41002 788 if ((err = pppoe_send_padr(sc)) != 0) {
donatien 0:8e01dca41002 789 sc->sc_padr_retried--;
donatien 0:8e01dca41002 790 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));
donatien 0:8e01dca41002 791 }
donatien 0:8e01dca41002 792 sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc);
donatien 0:8e01dca41002 793 break;
donatien 0:8e01dca41002 794 case PPPOE_STATE_CLOSING:
donatien 0:8e01dca41002 795 pppoe_do_disconnect(sc);
donatien 0:8e01dca41002 796 break;
donatien 0:8e01dca41002 797 default:
donatien 0:8e01dca41002 798 return; /* all done, work in peace */
donatien 0:8e01dca41002 799 }
donatien 0:8e01dca41002 800 }
donatien 0:8e01dca41002 801
donatien 0:8e01dca41002 802 /* Start a connection (i.e. initiate discovery phase) */
donatien 0:8e01dca41002 803 int
donatien 0:8e01dca41002 804 pppoe_connect(struct pppoe_softc *sc)
donatien 0:8e01dca41002 805 {
donatien 0:8e01dca41002 806 int err;
donatien 0:8e01dca41002 807
donatien 0:8e01dca41002 808 if (sc->sc_state != PPPOE_STATE_INITIAL) {
donatien 0:8e01dca41002 809 return EBUSY;
donatien 0:8e01dca41002 810 }
donatien 0:8e01dca41002 811
donatien 0:8e01dca41002 812 #ifdef PPPOE_SERVER
donatien 0:8e01dca41002 813 /* wait PADI if IFF_PASSIVE */
donatien 0:8e01dca41002 814 if ((sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) {
donatien 0:8e01dca41002 815 return 0;
donatien 0:8e01dca41002 816 }
donatien 0:8e01dca41002 817 #endif
donatien 0:8e01dca41002 818 /* save state, in case we fail to send PADI */
donatien 0:8e01dca41002 819 sc->sc_state = PPPOE_STATE_PADI_SENT;
donatien 0:8e01dca41002 820 sc->sc_padr_retried = 0;
donatien 0:8e01dca41002 821 err = pppoe_send_padi(sc);
donatien 0:8e01dca41002 822 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));
donatien 0:8e01dca41002 823 sys_timeout(PPPOE_DISC_TIMEOUT, pppoe_timeout, sc);
donatien 0:8e01dca41002 824 return err;
donatien 0:8e01dca41002 825 }
donatien 0:8e01dca41002 826
donatien 0:8e01dca41002 827 /* disconnect */
donatien 0:8e01dca41002 828 void
donatien 0:8e01dca41002 829 pppoe_disconnect(struct pppoe_softc *sc)
donatien 0:8e01dca41002 830 {
donatien 0:8e01dca41002 831 if (sc->sc_state < PPPOE_STATE_SESSION) {
donatien 0:8e01dca41002 832 return;
donatien 0:8e01dca41002 833 }
donatien 0:8e01dca41002 834 /*
donatien 0:8e01dca41002 835 * Do not call pppoe_disconnect here, the upper layer state
donatien 0:8e01dca41002 836 * machine gets confused by this. We must return from this
donatien 0:8e01dca41002 837 * function and defer disconnecting to the timeout handler.
donatien 0:8e01dca41002 838 */
donatien 0:8e01dca41002 839 sc->sc_state = PPPOE_STATE_CLOSING;
donatien 0:8e01dca41002 840 sys_timeout(20, pppoe_timeout, sc);
donatien 0:8e01dca41002 841 }
donatien 0:8e01dca41002 842
donatien 0:8e01dca41002 843 static int
donatien 0:8e01dca41002 844 pppoe_do_disconnect(struct pppoe_softc *sc)
donatien 0:8e01dca41002 845 {
donatien 0:8e01dca41002 846 int err;
donatien 0:8e01dca41002 847
donatien 0:8e01dca41002 848 if (sc->sc_state < PPPOE_STATE_SESSION) {
donatien 0:8e01dca41002 849 err = EBUSY;
donatien 0:8e01dca41002 850 } else {
donatien 0:8e01dca41002 851 PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": disconnecting\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num));
donatien 0:8e01dca41002 852 err = pppoe_send_padt(sc->sc_ethif, sc->sc_session, (const u8_t *)&sc->sc_dest);
donatien 0:8e01dca41002 853 }
donatien 0:8e01dca41002 854
donatien 0:8e01dca41002 855 /* cleanup softc */
donatien 0:8e01dca41002 856 sc->sc_state = PPPOE_STATE_INITIAL;
donatien 0:8e01dca41002 857 MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest));
donatien 0:8e01dca41002 858 sc->sc_ac_cookie_len = 0;
donatien 0:8e01dca41002 859 #ifdef PPPOE_SERVER
donatien 0:8e01dca41002 860 if (sc->sc_hunique) {
donatien 0:8e01dca41002 861 mem_free(sc->sc_hunique);
donatien 0:8e01dca41002 862 sc->sc_hunique = NULL;
donatien 0:8e01dca41002 863 }
donatien 0:8e01dca41002 864 sc->sc_hunique_len = 0;
donatien 0:8e01dca41002 865 #endif
donatien 0:8e01dca41002 866 sc->sc_session = 0;
donatien 0:8e01dca41002 867
donatien 0:8e01dca41002 868 sc->sc_linkStatusCB(sc->sc_pd, 0); /* notify upper layers */
donatien 0:8e01dca41002 869
donatien 0:8e01dca41002 870 return err;
donatien 0:8e01dca41002 871 }
donatien 0:8e01dca41002 872
donatien 0:8e01dca41002 873 /* Connection attempt aborted */
donatien 0:8e01dca41002 874 static void
donatien 0:8e01dca41002 875 pppoe_abort_connect(struct pppoe_softc *sc)
donatien 0:8e01dca41002 876 {
donatien 0:8e01dca41002 877 printf("%c%c%"U16_F": could not establish connection\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num);
donatien 0:8e01dca41002 878 sc->sc_state = PPPOE_STATE_CLOSING;
donatien 0:8e01dca41002 879
donatien 0:8e01dca41002 880 sc->sc_linkStatusCB(sc->sc_pd, 0); /* notify upper layers */
donatien 0:8e01dca41002 881
donatien 0:8e01dca41002 882 /* clear connection state */
donatien 0:8e01dca41002 883 MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest));
donatien 0:8e01dca41002 884 sc->sc_state = PPPOE_STATE_INITIAL;
donatien 0:8e01dca41002 885 }
donatien 0:8e01dca41002 886
donatien 0:8e01dca41002 887 /* Send a PADR packet */
donatien 0:8e01dca41002 888 static err_t
donatien 0:8e01dca41002 889 pppoe_send_padr(struct pppoe_softc *sc)
donatien 0:8e01dca41002 890 {
donatien 0:8e01dca41002 891 struct pbuf *pb;
donatien 0:8e01dca41002 892 u8_t *p;
donatien 0:8e01dca41002 893 size_t len;
donatien 0:8e01dca41002 894 #ifdef PPPOE_TODO
donatien 0:8e01dca41002 895 size_t l1 = 0; /* XXX: gcc */
donatien 0:8e01dca41002 896 #endif /* PPPOE_TODO */
donatien 0:8e01dca41002 897
donatien 0:8e01dca41002 898 if (sc->sc_state != PPPOE_STATE_PADR_SENT) {
donatien 0:8e01dca41002 899 return ERR_CONN;
donatien 0:8e01dca41002 900 }
donatien 0:8e01dca41002 901
donatien 0:8e01dca41002 902 len = 2 + 2 + 2 + 2 + sizeof(sc); /* service name, host unique */
donatien 0:8e01dca41002 903 #ifdef PPPOE_TODO
donatien 0:8e01dca41002 904 if (sc->sc_service_name != NULL) { /* service name tag maybe empty */
donatien 0:8e01dca41002 905 l1 = strlen(sc->sc_service_name);
donatien 0:8e01dca41002 906 len += l1;
donatien 0:8e01dca41002 907 }
donatien 0:8e01dca41002 908 #endif /* PPPOE_TODO */
donatien 0:8e01dca41002 909 if (sc->sc_ac_cookie_len > 0) {
donatien 0:8e01dca41002 910 len += 2 + 2 + sc->sc_ac_cookie_len; /* AC cookie */
donatien 0:8e01dca41002 911 }
donatien 0:8e01dca41002 912 LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff",
donatien 0:8e01dca41002 913 sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff);
donatien 0:8e01dca41002 914 pb = pbuf_alloc(PBUF_LINK, (u16_t)(sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len), PBUF_RAM);
donatien 0:8e01dca41002 915 if (!pb) {
donatien 0:8e01dca41002 916 return ERR_MEM;
donatien 0:8e01dca41002 917 }
donatien 0:8e01dca41002 918 LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len);
donatien 0:8e01dca41002 919 p = (u8_t*)pb->payload + sizeof (struct eth_hdr);
donatien 0:8e01dca41002 920 PPPOE_ADD_HEADER(p, PPPOE_CODE_PADR, 0, len);
donatien 0:8e01dca41002 921 PPPOE_ADD_16(p, PPPOE_TAG_SNAME);
donatien 0:8e01dca41002 922 #ifdef PPPOE_TODO
donatien 0:8e01dca41002 923 if (sc->sc_service_name != NULL) {
donatien 0:8e01dca41002 924 PPPOE_ADD_16(p, l1);
donatien 0:8e01dca41002 925 MEMCPY(p, sc->sc_service_name, l1);
donatien 0:8e01dca41002 926 p += l1;
donatien 0:8e01dca41002 927 } else
donatien 0:8e01dca41002 928 #endif /* PPPOE_TODO */
donatien 0:8e01dca41002 929 {
donatien 0:8e01dca41002 930 PPPOE_ADD_16(p, 0);
donatien 0:8e01dca41002 931 }
donatien 0:8e01dca41002 932 if (sc->sc_ac_cookie_len > 0) {
donatien 0:8e01dca41002 933 PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE);
donatien 0:8e01dca41002 934 PPPOE_ADD_16(p, sc->sc_ac_cookie_len);
donatien 0:8e01dca41002 935 MEMCPY(p, sc->sc_ac_cookie, sc->sc_ac_cookie_len);
donatien 0:8e01dca41002 936 p += sc->sc_ac_cookie_len;
donatien 0:8e01dca41002 937 }
donatien 0:8e01dca41002 938 PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE);
donatien 0:8e01dca41002 939 PPPOE_ADD_16(p, sizeof(sc));
donatien 0:8e01dca41002 940 MEMCPY(p, &sc, sizeof sc);
donatien 0:8e01dca41002 941
donatien 0:8e01dca41002 942 return pppoe_output(sc, pb);
donatien 0:8e01dca41002 943 }
donatien 0:8e01dca41002 944
donatien 0:8e01dca41002 945 /* send a PADT packet */
donatien 0:8e01dca41002 946 static err_t
donatien 0:8e01dca41002 947 pppoe_send_padt(struct netif *outgoing_if, u_int session, const u8_t *dest)
donatien 0:8e01dca41002 948 {
donatien 0:8e01dca41002 949 struct pbuf *pb;
donatien 0:8e01dca41002 950 struct eth_hdr *ethhdr;
donatien 0:8e01dca41002 951 err_t res;
donatien 0:8e01dca41002 952 u8_t *p;
donatien 0:8e01dca41002 953
donatien 0:8e01dca41002 954 pb = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr) + PPPOE_HEADERLEN, PBUF_RAM);
donatien 0:8e01dca41002 955 if (!pb) {
donatien 0:8e01dca41002 956 return ERR_MEM;
donatien 0:8e01dca41002 957 }
donatien 0:8e01dca41002 958 LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len);
donatien 0:8e01dca41002 959
donatien 0:8e01dca41002 960 ethhdr = (struct eth_hdr *)pb->payload;
donatien 0:8e01dca41002 961 ethhdr->type = PP_HTONS(ETHTYPE_PPPOEDISC);
donatien 0:8e01dca41002 962 MEMCPY(ethhdr->dest.addr, dest, sizeof(ethhdr->dest.addr));
donatien 0:8e01dca41002 963 MEMCPY(ethhdr->src.addr, ((struct eth_addr *)outgoing_if->hwaddr)->addr, sizeof(ethhdr->src.addr));
donatien 0:8e01dca41002 964
donatien 0:8e01dca41002 965 p = (u8_t*)(ethhdr + 1);
donatien 0:8e01dca41002 966 PPPOE_ADD_HEADER(p, PPPOE_CODE_PADT, session, 0);
donatien 0:8e01dca41002 967
donatien 0:8e01dca41002 968 res = outgoing_if->linkoutput(outgoing_if, pb);
donatien 0:8e01dca41002 969
donatien 0:8e01dca41002 970 pbuf_free(pb);
donatien 0:8e01dca41002 971
donatien 0:8e01dca41002 972 return res;
donatien 0:8e01dca41002 973 }
donatien 0:8e01dca41002 974
donatien 0:8e01dca41002 975 #ifdef PPPOE_SERVER
donatien 0:8e01dca41002 976 static err_t
donatien 0:8e01dca41002 977 pppoe_send_pado(struct pppoe_softc *sc)
donatien 0:8e01dca41002 978 {
donatien 0:8e01dca41002 979 struct pbuf *pb;
donatien 0:8e01dca41002 980 u8_t *p;
donatien 0:8e01dca41002 981 size_t len;
donatien 0:8e01dca41002 982
donatien 0:8e01dca41002 983 if (sc->sc_state != PPPOE_STATE_PADO_SENT) {
donatien 0:8e01dca41002 984 return ERR_CONN;
donatien 0:8e01dca41002 985 }
donatien 0:8e01dca41002 986
donatien 0:8e01dca41002 987 /* calc length */
donatien 0:8e01dca41002 988 len = 0;
donatien 0:8e01dca41002 989 /* include ac_cookie */
donatien 0:8e01dca41002 990 len += 2 + 2 + sizeof(sc);
donatien 0:8e01dca41002 991 /* include hunique */
donatien 0:8e01dca41002 992 len += 2 + 2 + sc->sc_hunique_len;
donatien 0:8e01dca41002 993 pb = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len, PBUF_RAM);
donatien 0:8e01dca41002 994 if (!pb) {
donatien 0:8e01dca41002 995 return ERR_MEM;
donatien 0:8e01dca41002 996 }
donatien 0:8e01dca41002 997 LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len);
donatien 0:8e01dca41002 998 p = (u8_t*)pb->payload + sizeof (struct eth_hdr);
donatien 0:8e01dca41002 999 PPPOE_ADD_HEADER(p, PPPOE_CODE_PADO, 0, len);
donatien 0:8e01dca41002 1000 PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE);
donatien 0:8e01dca41002 1001 PPPOE_ADD_16(p, sizeof(sc));
donatien 0:8e01dca41002 1002 MEMCPY(p, &sc, sizeof(sc));
donatien 0:8e01dca41002 1003 p += sizeof(sc);
donatien 0:8e01dca41002 1004 PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE);
donatien 0:8e01dca41002 1005 PPPOE_ADD_16(p, sc->sc_hunique_len);
donatien 0:8e01dca41002 1006 MEMCPY(p, sc->sc_hunique, sc->sc_hunique_len);
donatien 0:8e01dca41002 1007 return pppoe_output(sc, pb);
donatien 0:8e01dca41002 1008 }
donatien 0:8e01dca41002 1009
donatien 0:8e01dca41002 1010 static err_t
donatien 0:8e01dca41002 1011 pppoe_send_pads(struct pppoe_softc *sc)
donatien 0:8e01dca41002 1012 {
donatien 0:8e01dca41002 1013 struct pbuf *pb;
donatien 0:8e01dca41002 1014 u8_t *p;
donatien 0:8e01dca41002 1015 size_t len, l1 = 0; /* XXX: gcc */
donatien 0:8e01dca41002 1016
donatien 0:8e01dca41002 1017 if (sc->sc_state != PPPOE_STATE_PADO_SENT) {
donatien 0:8e01dca41002 1018 return ERR_CONN;
donatien 0:8e01dca41002 1019 }
donatien 0:8e01dca41002 1020
donatien 0:8e01dca41002 1021 sc->sc_session = mono_time.tv_sec % 0xff + 1;
donatien 0:8e01dca41002 1022 /* calc length */
donatien 0:8e01dca41002 1023 len = 0;
donatien 0:8e01dca41002 1024 /* include hunique */
donatien 0:8e01dca41002 1025 len += 2 + 2 + 2 + 2 + sc->sc_hunique_len; /* service name, host unique*/
donatien 0:8e01dca41002 1026 if (sc->sc_service_name != NULL) { /* service name tag maybe empty */
donatien 0:8e01dca41002 1027 l1 = strlen(sc->sc_service_name);
donatien 0:8e01dca41002 1028 len += l1;
donatien 0:8e01dca41002 1029 }
donatien 0:8e01dca41002 1030 pb = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len, PBUF_RAM);
donatien 0:8e01dca41002 1031 if (!pb) {
donatien 0:8e01dca41002 1032 return ERR_MEM;
donatien 0:8e01dca41002 1033 }
donatien 0:8e01dca41002 1034 LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len);
donatien 0:8e01dca41002 1035 p = (u8_t*)pb->payload + sizeof (struct eth_hdr);
donatien 0:8e01dca41002 1036 PPPOE_ADD_HEADER(p, PPPOE_CODE_PADS, sc->sc_session, len);
donatien 0:8e01dca41002 1037 PPPOE_ADD_16(p, PPPOE_TAG_SNAME);
donatien 0:8e01dca41002 1038 if (sc->sc_service_name != NULL) {
donatien 0:8e01dca41002 1039 PPPOE_ADD_16(p, l1);
donatien 0:8e01dca41002 1040 MEMCPY(p, sc->sc_service_name, l1);
donatien 0:8e01dca41002 1041 p += l1;
donatien 0:8e01dca41002 1042 } else {
donatien 0:8e01dca41002 1043 PPPOE_ADD_16(p, 0);
donatien 0:8e01dca41002 1044 }
donatien 0:8e01dca41002 1045 PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE);
donatien 0:8e01dca41002 1046 PPPOE_ADD_16(p, sc->sc_hunique_len);
donatien 0:8e01dca41002 1047 MEMCPY(p, sc->sc_hunique, sc->sc_hunique_len);
donatien 0:8e01dca41002 1048 return pppoe_output(sc, pb);
donatien 0:8e01dca41002 1049 }
donatien 0:8e01dca41002 1050 #endif
donatien 0:8e01dca41002 1051
donatien 0:8e01dca41002 1052 err_t
donatien 0:8e01dca41002 1053 pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb)
donatien 0:8e01dca41002 1054 {
donatien 0:8e01dca41002 1055 u8_t *p;
donatien 0:8e01dca41002 1056 size_t len;
donatien 0:8e01dca41002 1057
donatien 0:8e01dca41002 1058 /* are we ready to process data yet? */
donatien 0:8e01dca41002 1059 if (sc->sc_state < PPPOE_STATE_SESSION) {
donatien 0:8e01dca41002 1060 /*sppp_flush(&sc->sc_sppp.pp_if);*/
donatien 0:8e01dca41002 1061 pbuf_free(pb);
donatien 0:8e01dca41002 1062 return ERR_CONN;
donatien 0:8e01dca41002 1063 }
donatien 0:8e01dca41002 1064
donatien 0:8e01dca41002 1065 len = pb->tot_len;
donatien 0:8e01dca41002 1066
donatien 0:8e01dca41002 1067 /* make room for Ethernet header - should not fail */
donatien 0:8e01dca41002 1068 if (pbuf_header(pb, sizeof(struct eth_hdr) + PPPOE_HEADERLEN) != 0) {
donatien 0:8e01dca41002 1069 /* bail out */
donatien 0:8e01dca41002 1070 PPPDEBUG(LOG_ERR, ("pppoe: %c%c%"U16_F": pppoe_xmit: could not allocate room for header\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num));
donatien 0:8e01dca41002 1071 LINK_STATS_INC(link.lenerr);
donatien 0:8e01dca41002 1072 pbuf_free(pb);
donatien 0:8e01dca41002 1073 return ERR_BUF;
donatien 0:8e01dca41002 1074 }
donatien 0:8e01dca41002 1075
donatien 0:8e01dca41002 1076 p = (u8_t*)pb->payload + sizeof(struct eth_hdr);
donatien 0:8e01dca41002 1077 PPPOE_ADD_HEADER(p, 0, sc->sc_session, len);
donatien 0:8e01dca41002 1078
donatien 0:8e01dca41002 1079 return pppoe_output(sc, pb);
donatien 0:8e01dca41002 1080 }
donatien 0:8e01dca41002 1081
donatien 0:8e01dca41002 1082 #if 0 /*def PFIL_HOOKS*/
donatien 0:8e01dca41002 1083 static int
donatien 0:8e01dca41002 1084 pppoe_ifattach_hook(void *arg, struct pbuf **mp, struct netif *ifp, int dir)
donatien 0:8e01dca41002 1085 {
donatien 0:8e01dca41002 1086 struct pppoe_softc *sc;
donatien 0:8e01dca41002 1087 int s;
donatien 0:8e01dca41002 1088
donatien 0:8e01dca41002 1089 if (mp != (struct pbuf **)PFIL_IFNET_DETACH) {
donatien 0:8e01dca41002 1090 return 0;
donatien 0:8e01dca41002 1091 }
donatien 0:8e01dca41002 1092
donatien 0:8e01dca41002 1093 LIST_FOREACH(sc, &pppoe_softc_list, sc_list) {
donatien 0:8e01dca41002 1094 if (sc->sc_ethif != ifp) {
donatien 0:8e01dca41002 1095 continue;
donatien 0:8e01dca41002 1096 }
donatien 0:8e01dca41002 1097 if (sc->sc_sppp.pp_if.if_flags & IFF_UP) {
donatien 0:8e01dca41002 1098 sc->sc_sppp.pp_if.if_flags &= ~(IFF_UP|IFF_RUNNING);
donatien 0:8e01dca41002 1099 printf("%c%c%"U16_F": ethernet interface detached, going down\n",
donatien 0:8e01dca41002 1100 sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num);
donatien 0:8e01dca41002 1101 }
donatien 0:8e01dca41002 1102 sc->sc_ethif = NULL;
donatien 0:8e01dca41002 1103 pppoe_clear_softc(sc, "ethernet interface detached");
donatien 0:8e01dca41002 1104 }
donatien 0:8e01dca41002 1105
donatien 0:8e01dca41002 1106 return 0;
donatien 0:8e01dca41002 1107 }
donatien 0:8e01dca41002 1108 #endif
donatien 0:8e01dca41002 1109
donatien 0:8e01dca41002 1110 static void
donatien 0:8e01dca41002 1111 pppoe_clear_softc(struct pppoe_softc *sc, const char *message)
donatien 0:8e01dca41002 1112 {
donatien 0:8e01dca41002 1113 LWIP_UNUSED_ARG(message);
donatien 0:8e01dca41002 1114
donatien 0:8e01dca41002 1115 /* stop timer */
donatien 0:8e01dca41002 1116 sys_untimeout(pppoe_timeout, sc);
donatien 0:8e01dca41002 1117 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));
donatien 0:8e01dca41002 1118
donatien 0:8e01dca41002 1119 /* fix our state */
donatien 0:8e01dca41002 1120 sc->sc_state = PPPOE_STATE_INITIAL;
donatien 0:8e01dca41002 1121
donatien 0:8e01dca41002 1122 /* notify upper layers */
donatien 0:8e01dca41002 1123 sc->sc_linkStatusCB(sc->sc_pd, 0);
donatien 0:8e01dca41002 1124
donatien 0:8e01dca41002 1125 /* clean up softc */
donatien 0:8e01dca41002 1126 MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest));
donatien 0:8e01dca41002 1127 sc->sc_ac_cookie_len = 0;
donatien 0:8e01dca41002 1128 sc->sc_session = 0;
donatien 0:8e01dca41002 1129 }
donatien 0:8e01dca41002 1130
donatien 0:8e01dca41002 1131 #endif /* PPPOE_SUPPORT */
donatien 0:8e01dca41002 1132