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