Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510
lwip_pppoe.c
00001 /***************************************************************************** 00002 * pppoe.c - PPP Over Ethernet implementation for lwIP. 00003 * 00004 * Copyright (c) 2006 by Marc Boucher, Services Informatiques (MBSI) inc. 00005 * 00006 * The authors hereby grant permission to use, copy, modify, distribute, 00007 * and license this software and its documentation for any purpose, provided 00008 * that existing copyright notices are retained in all copies and that this 00009 * notice and the following disclaimer are included verbatim in any 00010 * distributions. No written agreement, license, or royalty fee is required 00011 * for any of the authorized uses. 00012 * 00013 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR 00014 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00015 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00016 * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00017 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 00018 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00019 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00020 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00021 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00022 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00023 * 00024 ****************************************************************************** 00025 * REVISION HISTORY 00026 * 00027 * 06-01-01 Marc Boucher <marc@mbsi.ca> 00028 * Ported to lwIP. 00029 *****************************************************************************/ 00030 00031 00032 00033 /* based on NetBSD: if_pppoe.c,v 1.64 2006/01/31 23:50:15 martin Exp */ 00034 00035 /*- 00036 * Copyright (c) 2002 The NetBSD Foundation, Inc. 00037 * All rights reserved. 00038 * 00039 * This code is derived from software contributed to The NetBSD Foundation 00040 * by Martin Husemann <martin@NetBSD.org>. 00041 * 00042 * Redistribution and use in source and binary forms, with or without 00043 * modification, are permitted provided that the following conditions 00044 * are met: 00045 * 1. Redistributions of source code must retain the above copyright 00046 * notice, this list of conditions and the following disclaimer. 00047 * 2. Redistributions in binary form must reproduce the above copyright 00048 * notice, this list of conditions and the following disclaimer in the 00049 * documentation and/or other materials provided with the distribution. 00050 * 3. All advertising materials mentioning features or use of this software 00051 * must display the following acknowledgement: 00052 * This product includes software developed by the NetBSD 00053 * Foundation, Inc. and its contributors. 00054 * 4. Neither the name of The NetBSD Foundation nor the names of its 00055 * contributors may be used to endorse or promote products derived 00056 * from this software without specific prior written permission. 00057 * 00058 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 00059 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 00060 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00061 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 00062 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00063 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00064 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00065 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00066 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00067 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00068 * POSSIBILITY OF SUCH DAMAGE. 00069 */ 00070 00071 #include "netif/ppp/ppp_opts.h" 00072 #if PPP_SUPPORT && PPPOE_SUPPORT /* don't build if not configured for use in lwipopts.h */ 00073 00074 #if 0 /* UNUSED */ 00075 #include <string.h> 00076 #include <stdio.h> 00077 #endif /* UNUSED */ 00078 00079 #include "lwip/timeouts.h" 00080 #include "lwip/memp.h" 00081 #include "lwip/stats.h" 00082 #include "lwip/snmp.h" 00083 00084 #include "netif/ppp/ppp_impl.h" 00085 #include "netif/ppp/lcp.h" 00086 #include "netif/ppp/ipcp.h" 00087 #include "netif/ppp/pppoe.h" 00088 00089 /* Memory pool */ 00090 LWIP_MEMPOOL_DECLARE(PPPOE_IF, MEMP_NUM_PPPOE_INTERFACES, sizeof(struct pppoe_softc), "PPPOE_IF") 00091 00092 /* Add a 16 bit unsigned value to a buffer pointed to by PTR */ 00093 #define PPPOE_ADD_16(PTR, VAL) \ 00094 *(PTR)++ = (u8_t)((VAL) / 256); \ 00095 *(PTR)++ = (u8_t)((VAL) % 256) 00096 00097 /* Add a complete PPPoE header to the buffer pointed to by PTR */ 00098 #define PPPOE_ADD_HEADER(PTR, CODE, SESS, LEN) \ 00099 *(PTR)++ = PPPOE_VERTYPE; \ 00100 *(PTR)++ = (CODE); \ 00101 PPPOE_ADD_16(PTR, SESS); \ 00102 PPPOE_ADD_16(PTR, LEN) 00103 00104 #define PPPOE_DISC_TIMEOUT (5*1000) /* base for quick timeout calculation */ 00105 #define PPPOE_SLOW_RETRY (60*1000) /* persistent retry interval */ 00106 #define PPPOE_DISC_MAXPADI 4 /* retry PADI four times (quickly) */ 00107 #define PPPOE_DISC_MAXPADR 2 /* retry PADR twice */ 00108 00109 #ifdef PPPOE_SERVER 00110 #error "PPPOE_SERVER is not yet supported under lwIP!" 00111 /* from if_spppsubr.c */ 00112 #define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */ 00113 #endif 00114 00115 #define PPPOE_ERRORSTRING_LEN 64 00116 00117 00118 /* callbacks called from PPP core */ 00119 static err_t pppoe_write(ppp_pcb *ppp, void *ctx, struct pbuf *p); 00120 static err_t pppoe_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *p, u_short protocol); 00121 static err_t pppoe_connect(ppp_pcb *ppp, void *ctx); 00122 static void pppoe_disconnect(ppp_pcb *ppp, void *ctx); 00123 static err_t pppoe_destroy(ppp_pcb *ppp, void *ctx); 00124 00125 /* management routines */ 00126 static void pppoe_abort_connect(struct pppoe_softc *); 00127 #if 0 /* UNUSED */ 00128 static void pppoe_clear_softc(struct pppoe_softc *, const char *); 00129 #endif /* UNUSED */ 00130 00131 /* internal timeout handling */ 00132 static void pppoe_timeout(void *); 00133 00134 /* sending actual protocol controll packets */ 00135 static err_t pppoe_send_padi(struct pppoe_softc *); 00136 static err_t pppoe_send_padr(struct pppoe_softc *); 00137 #ifdef PPPOE_SERVER 00138 static err_t pppoe_send_pado(struct pppoe_softc *); 00139 static err_t pppoe_send_pads(struct pppoe_softc *); 00140 #endif 00141 static err_t pppoe_send_padt(struct netif *, u_int, const u8_t *); 00142 00143 /* internal helper functions */ 00144 static err_t pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb); 00145 static struct pppoe_softc* pppoe_find_softc_by_session(u_int session, struct netif *rcvif); 00146 static struct pppoe_softc* pppoe_find_softc_by_hunique(u8_t *token, size_t len, struct netif *rcvif); 00147 00148 /** linked list of created pppoe interfaces */ 00149 static struct pppoe_softc *pppoe_softc_list; 00150 00151 /* Callbacks structure for PPP core */ 00152 static const struct link_callbacks pppoe_callbacks = { 00153 pppoe_connect, 00154 #if PPP_SERVER 00155 NULL, 00156 #endif /* PPP_SERVER */ 00157 pppoe_disconnect, 00158 pppoe_destroy, 00159 pppoe_write, 00160 pppoe_netif_output, 00161 NULL, 00162 NULL 00163 }; 00164 00165 /* 00166 * Create a new PPP Over Ethernet (PPPoE) connection. 00167 * 00168 * Return 0 on success, an error code on failure. 00169 */ 00170 ppp_pcb *pppoe_create(struct netif *pppif, 00171 struct netif *ethif, 00172 const char *service_name, const char *concentrator_name, 00173 ppp_link_status_cb_fn link_status_cb, void *ctx_cb) 00174 { 00175 ppp_pcb *ppp; 00176 struct pppoe_softc *sc; 00177 LWIP_UNUSED_ARG(service_name); 00178 LWIP_UNUSED_ARG(concentrator_name); 00179 00180 sc = (struct pppoe_softc *)LWIP_MEMPOOL_ALLOC(PPPOE_IF); 00181 if (sc == NULL) { 00182 return NULL; 00183 } 00184 00185 ppp = ppp_new(pppif, &pppoe_callbacks, sc, link_status_cb, ctx_cb); 00186 if (ppp == NULL) { 00187 LWIP_MEMPOOL_FREE(PPPOE_IF, sc); 00188 return NULL; 00189 } 00190 00191 memset(sc, 0, sizeof(struct pppoe_softc)); 00192 /* changed to real address later */ 00193 MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); 00194 sc->pcb = ppp; 00195 sc->sc_ethif = ethif; 00196 /* put the new interface at the head of the list */ 00197 sc->next = pppoe_softc_list; 00198 pppoe_softc_list = sc; 00199 return ppp; 00200 } 00201 00202 /* Called by PPP core */ 00203 static err_t pppoe_write(ppp_pcb *ppp, void *ctx, struct pbuf *p) { 00204 struct pppoe_softc *sc = (struct pppoe_softc *)ctx; 00205 struct pbuf *ph; /* Ethernet + PPPoE header */ 00206 err_t ret; 00207 #if MIB2_STATS 00208 u16_t tot_len; 00209 #else /* MIB2_STATS */ 00210 LWIP_UNUSED_ARG(ppp); 00211 #endif /* MIB2_STATS */ 00212 00213 /* skip address & flags */ 00214 pbuf_header(p, -(s16_t)2); 00215 00216 ph = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN), PBUF_RAM); 00217 if(!ph) { 00218 LINK_STATS_INC(link.memerr); 00219 LINK_STATS_INC(link.proterr); 00220 MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); 00221 pbuf_free(p); 00222 return ERR_MEM; 00223 } 00224 00225 pbuf_header(ph, -(s16_t)PPPOE_HEADERLEN); /* hide PPPoE header */ 00226 pbuf_cat(ph, p); 00227 #if MIB2_STATS 00228 tot_len = ph->tot_len; 00229 #endif /* MIB2_STATS */ 00230 00231 ret = pppoe_xmit(sc, ph); 00232 if (ret != ERR_OK) { 00233 LINK_STATS_INC(link.err); 00234 MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); 00235 return ret; 00236 } 00237 00238 MIB2_STATS_NETIF_ADD(ppp->netif, ifoutoctets, (u16_t)tot_len); 00239 MIB2_STATS_NETIF_INC(ppp->netif, ifoutucastpkts); 00240 LINK_STATS_INC(link.xmit); 00241 return ERR_OK; 00242 } 00243 00244 /* Called by PPP core */ 00245 static err_t pppoe_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *p, u_short protocol) { 00246 struct pppoe_softc *sc = (struct pppoe_softc *)ctx; 00247 struct pbuf *pb; 00248 u8_t *pl; 00249 err_t err; 00250 #if MIB2_STATS 00251 u16_t tot_len; 00252 #else /* MIB2_STATS */ 00253 LWIP_UNUSED_ARG(ppp); 00254 #endif /* MIB2_STATS */ 00255 00256 /* @todo: try to use pbuf_header() here! */ 00257 pb = pbuf_alloc(PBUF_LINK, PPPOE_HEADERLEN + sizeof(protocol), PBUF_RAM); 00258 if(!pb) { 00259 LINK_STATS_INC(link.memerr); 00260 LINK_STATS_INC(link.proterr); 00261 MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); 00262 return ERR_MEM; 00263 } 00264 00265 pbuf_header(pb, -(s16_t)PPPOE_HEADERLEN); 00266 00267 pl = (u8_t*)pb->payload; 00268 PUTSHORT(protocol, pl); 00269 00270 pbuf_chain(pb, p); 00271 #if MIB2_STATS 00272 tot_len = pb->tot_len; 00273 #endif /* MIB2_STATS */ 00274 00275 if( (err = pppoe_xmit(sc, pb)) != ERR_OK) { 00276 LINK_STATS_INC(link.err); 00277 MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); 00278 return err; 00279 } 00280 00281 MIB2_STATS_NETIF_ADD(ppp->netif, ifoutoctets, tot_len); 00282 MIB2_STATS_NETIF_INC(ppp->netif, ifoutucastpkts); 00283 LINK_STATS_INC(link.xmit); 00284 return ERR_OK; 00285 } 00286 00287 static err_t 00288 pppoe_destroy(ppp_pcb *ppp, void *ctx) 00289 { 00290 struct pppoe_softc *sc = (struct pppoe_softc *)ctx; 00291 struct pppoe_softc **copp, *freep; 00292 LWIP_UNUSED_ARG(ppp); 00293 00294 sys_untimeout(pppoe_timeout, sc); 00295 00296 /* remove interface from list */ 00297 for (copp = &pppoe_softc_list; (freep = *copp); copp = &freep->next) { 00298 if (freep == sc) { 00299 *copp = freep->next; 00300 break; 00301 } 00302 } 00303 00304 #ifdef PPPOE_TODO 00305 if (sc->sc_concentrator_name) { 00306 mem_free(sc->sc_concentrator_name); 00307 } 00308 if (sc->sc_service_name) { 00309 mem_free(sc->sc_service_name); 00310 } 00311 #endif /* PPPOE_TODO */ 00312 LWIP_MEMPOOL_FREE(PPPOE_IF, sc); 00313 00314 return ERR_OK; 00315 } 00316 00317 /* 00318 * Find the interface handling the specified session. 00319 * Note: O(number of sessions open), this is a client-side only, mean 00320 * and lean implementation, so number of open sessions typically should 00321 * be 1. 00322 */ 00323 static struct pppoe_softc* pppoe_find_softc_by_session(u_int session, struct netif *rcvif) { 00324 struct pppoe_softc *sc; 00325 00326 if (session == 0) { 00327 return NULL; 00328 } 00329 00330 for (sc = pppoe_softc_list; sc != NULL; sc = sc->next) { 00331 if (sc->sc_state == PPPOE_STATE_SESSION 00332 && sc->sc_session == session 00333 && sc->sc_ethif == rcvif) { 00334 return sc; 00335 } 00336 } 00337 return NULL; 00338 } 00339 00340 /* Check host unique token passed and return appropriate softc pointer, 00341 * or NULL if token is bogus. */ 00342 static struct pppoe_softc* pppoe_find_softc_by_hunique(u8_t *token, size_t len, struct netif *rcvif) { 00343 struct pppoe_softc *sc, *t; 00344 00345 if (pppoe_softc_list == NULL) { 00346 return NULL; 00347 } 00348 00349 if (len != sizeof sc) { 00350 return NULL; 00351 } 00352 MEMCPY(&t, token, len); 00353 00354 for (sc = pppoe_softc_list; sc != NULL; sc = sc->next) { 00355 if (sc == t) { 00356 break; 00357 } 00358 } 00359 00360 if (sc == NULL) { 00361 PPPDEBUG(LOG_DEBUG, ("pppoe: alien host unique tag, no session found\n")); 00362 return NULL; 00363 } 00364 00365 /* should be safe to access *sc now */ 00366 if (sc->sc_state < PPPOE_STATE_PADI_SENT || sc->sc_state >= PPPOE_STATE_SESSION) { 00367 PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": host unique tag found, but it belongs to a connection in state %d\n", 00368 sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_state)); 00369 return NULL; 00370 } 00371 if (sc->sc_ethif != rcvif) { 00372 PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": wrong interface, not accepting host unique\n", 00373 sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); 00374 return NULL; 00375 } 00376 return sc; 00377 } 00378 00379 /* analyze and handle a single received packet while not in session state */ 00380 void 00381 pppoe_disc_input(struct netif *netif, struct pbuf *pb) 00382 { 00383 u16_t tag, len; 00384 u16_t session, plen; 00385 struct pppoe_softc *sc; 00386 #if PPP_DEBUG 00387 const char *err_msg = NULL; 00388 #endif /* PPP_DEBUG */ 00389 u8_t *ac_cookie; 00390 u16_t ac_cookie_len; 00391 #ifdef PPPOE_SERVER 00392 u8_t *hunique; 00393 size_t hunique_len; 00394 #endif 00395 struct pppoehdr *ph; 00396 struct pppoetag pt; 00397 int off, err; 00398 struct eth_hdr *ethhdr; 00399 00400 /* don't do anything if there is not a single PPPoE instance */ 00401 if (pppoe_softc_list == NULL) { 00402 pbuf_free(pb); 00403 return; 00404 } 00405 00406 pb = ppp_singlebuf(pb); 00407 00408 if (pb->len < sizeof(*ethhdr)) { 00409 goto done; 00410 } 00411 ethhdr = (struct eth_hdr *)pb->payload; 00412 off = sizeof(*ethhdr); 00413 00414 ac_cookie = NULL; 00415 ac_cookie_len = 0; 00416 #ifdef PPPOE_SERVER 00417 hunique = NULL; 00418 hunique_len = 0; 00419 #endif 00420 session = 0; 00421 if (pb->len - off < (u16_t)PPPOE_HEADERLEN) { 00422 PPPDEBUG(LOG_DEBUG, ("pppoe: packet too short: %d\n", pb->len)); 00423 goto done; 00424 } 00425 00426 ph = (struct pppoehdr *) (ethhdr + 1); 00427 if (ph->vertype != PPPOE_VERTYPE) { 00428 PPPDEBUG(LOG_DEBUG, ("pppoe: unknown version/type packet: 0x%x\n", ph->vertype)); 00429 goto done; 00430 } 00431 session = ntohs(ph->session); 00432 plen = ntohs(ph->plen); 00433 off += sizeof(*ph); 00434 00435 if (plen + off > pb->len) { 00436 PPPDEBUG(LOG_DEBUG, ("pppoe: packet content does not fit: data available = %d, packet size = %u\n", 00437 pb->len - off, plen)); 00438 goto done; 00439 } 00440 if(pb->tot_len == pb->len) { 00441 pb->tot_len = pb->len = (u16_t)off + plen; /* ignore trailing garbage */ 00442 } 00443 tag = 0; 00444 len = 0; 00445 sc = NULL; 00446 while (off + sizeof(pt) <= pb->len) { 00447 MEMCPY(&pt, (u8_t*)pb->payload + off, sizeof(pt)); 00448 tag = ntohs(pt.tag); 00449 len = ntohs(pt.len); 00450 if (off + sizeof(pt) + len > pb->len) { 00451 PPPDEBUG(LOG_DEBUG, ("pppoe: tag 0x%x len 0x%x is too long\n", tag, len)); 00452 goto done; 00453 } 00454 switch (tag) { 00455 case PPPOE_TAG_EOL: 00456 goto breakbreak; 00457 case PPPOE_TAG_SNAME: 00458 break; /* ignored */ 00459 case PPPOE_TAG_ACNAME: 00460 break; /* ignored */ 00461 case PPPOE_TAG_HUNIQUE: 00462 if (sc != NULL) { 00463 break; 00464 } 00465 #ifdef PPPOE_SERVER 00466 hunique = (u8_t*)pb->payload + off + sizeof(pt); 00467 hunique_len = len; 00468 #endif 00469 sc = pppoe_find_softc_by_hunique((u8_t*)pb->payload + off + sizeof(pt), len, netif); 00470 break; 00471 case PPPOE_TAG_ACCOOKIE: 00472 if (ac_cookie == NULL) { 00473 if (len > PPPOE_MAX_AC_COOKIE_LEN) { 00474 PPPDEBUG(LOG_DEBUG, ("pppoe: AC cookie is too long: len = %d, max = %d\n", len, PPPOE_MAX_AC_COOKIE_LEN)); 00475 goto done; 00476 } 00477 ac_cookie = (u8_t*)pb->payload + off + sizeof(pt); 00478 ac_cookie_len = len; 00479 } 00480 break; 00481 #if PPP_DEBUG 00482 case PPPOE_TAG_SNAME_ERR: 00483 err_msg = "SERVICE NAME ERROR"; 00484 break; 00485 case PPPOE_TAG_ACSYS_ERR: 00486 err_msg = "AC SYSTEM ERROR"; 00487 break; 00488 case PPPOE_TAG_GENERIC_ERR: 00489 err_msg = "GENERIC ERROR"; 00490 break; 00491 #endif /* PPP_DEBUG */ 00492 default: 00493 break; 00494 } 00495 #if PPP_DEBUG 00496 if (err_msg != NULL) { 00497 char error_tmp[PPPOE_ERRORSTRING_LEN]; 00498 u16_t error_len = LWIP_MIN(len, sizeof(error_tmp)-1); 00499 strncpy(error_tmp, (char*)pb->payload + off + sizeof(pt), error_len); 00500 error_tmp[error_len] = '\0'; 00501 if (sc) { 00502 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)); 00503 } else { 00504 PPPDEBUG(LOG_DEBUG, ("pppoe: %s: %s\n", err_msg, error_tmp)); 00505 } 00506 } 00507 #endif /* PPP_DEBUG */ 00508 off += sizeof(pt) + len; 00509 } 00510 00511 breakbreak:; 00512 switch (ph->code) { 00513 case PPPOE_CODE_PADI: 00514 #ifdef PPPOE_SERVER 00515 /* 00516 * got service name, concentrator name, and/or host unique. 00517 * ignore if we have no interfaces with IFF_PASSIVE|IFF_UP. 00518 */ 00519 if (LIST_EMPTY(&pppoe_softc_list)) { 00520 goto done; 00521 } 00522 LIST_FOREACH(sc, &pppoe_softc_list, sc_list) { 00523 if (!(sc->sc_sppp.pp_if.if_flags & IFF_UP)) { 00524 continue; 00525 } 00526 if (!(sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) { 00527 continue; 00528 } 00529 if (sc->sc_state == PPPOE_STATE_INITIAL) { 00530 break; 00531 } 00532 } 00533 if (sc == NULL) { 00534 /* PPPDEBUG(LOG_DEBUG, ("pppoe: free passive interface is not found\n")); */ 00535 goto done; 00536 } 00537 if (hunique) { 00538 if (sc->sc_hunique) { 00539 mem_free(sc->sc_hunique); 00540 } 00541 sc->sc_hunique = mem_malloc(hunique_len); 00542 if (sc->sc_hunique == NULL) { 00543 goto done; 00544 } 00545 sc->sc_hunique_len = hunique_len; 00546 MEMCPY(sc->sc_hunique, hunique, hunique_len); 00547 } 00548 MEMCPY(&sc->sc_dest, eh->ether_shost, sizeof sc->sc_dest); 00549 sc->sc_state = PPPOE_STATE_PADO_SENT; 00550 pppoe_send_pado(sc); 00551 break; 00552 #endif /* PPPOE_SERVER */ 00553 case PPPOE_CODE_PADR: 00554 #ifdef PPPOE_SERVER 00555 /* 00556 * get sc from ac_cookie if IFF_PASSIVE 00557 */ 00558 if (ac_cookie == NULL) { 00559 /* be quiet if there is not a single pppoe instance */ 00560 PPPDEBUG(LOG_DEBUG, ("pppoe: received PADR but not includes ac_cookie\n")); 00561 goto done; 00562 } 00563 sc = pppoe_find_softc_by_hunique(ac_cookie, ac_cookie_len, netif); 00564 if (sc == NULL) { 00565 /* be quiet if there is not a single pppoe instance */ 00566 if (!LIST_EMPTY(&pppoe_softc_list)) { 00567 PPPDEBUG(LOG_DEBUG, ("pppoe: received PADR but could not find request for it\n")); 00568 } 00569 goto done; 00570 } 00571 if (sc->sc_state != PPPOE_STATE_PADO_SENT) { 00572 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)); 00573 goto done; 00574 } 00575 if (hunique) { 00576 if (sc->sc_hunique) { 00577 mem_free(sc->sc_hunique); 00578 } 00579 sc->sc_hunique = mem_malloc(hunique_len); 00580 if (sc->sc_hunique == NULL) { 00581 goto done; 00582 } 00583 sc->sc_hunique_len = hunique_len; 00584 MEMCPY(sc->sc_hunique, hunique, hunique_len); 00585 } 00586 pppoe_send_pads(sc); 00587 sc->sc_state = PPPOE_STATE_SESSION; 00588 ppp_start(sc->pcb); /* notify upper layers */ 00589 break; 00590 #else 00591 /* ignore, we are no access concentrator */ 00592 goto done; 00593 #endif /* PPPOE_SERVER */ 00594 case PPPOE_CODE_PADO: 00595 if (sc == NULL) { 00596 /* be quiet if there is not a single pppoe instance */ 00597 if (pppoe_softc_list != NULL) { 00598 PPPDEBUG(LOG_DEBUG, ("pppoe: received PADO but could not find request for it\n")); 00599 } 00600 goto done; 00601 } 00602 if (sc->sc_state != PPPOE_STATE_PADI_SENT) { 00603 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)); 00604 goto done; 00605 } 00606 if (ac_cookie) { 00607 sc->sc_ac_cookie_len = ac_cookie_len; 00608 MEMCPY(sc->sc_ac_cookie, ac_cookie, ac_cookie_len); 00609 } 00610 MEMCPY(&sc->sc_dest, ethhdr->src.addr, sizeof(sc->sc_dest.addr)); 00611 sys_untimeout(pppoe_timeout, sc); 00612 sc->sc_padr_retried = 0; 00613 sc->sc_state = PPPOE_STATE_PADR_SENT; 00614 if ((err = pppoe_send_padr(sc)) != 0) { 00615 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)); 00616 } 00617 sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc); 00618 break; 00619 case PPPOE_CODE_PADS: 00620 if (sc == NULL) { 00621 goto done; 00622 } 00623 sc->sc_session = session; 00624 sys_untimeout(pppoe_timeout, sc); 00625 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)); 00626 sc->sc_state = PPPOE_STATE_SESSION; 00627 ppp_start(sc->pcb); /* notify upper layers */ 00628 break; 00629 case PPPOE_CODE_PADT: 00630 /* Don't disconnect here, we let the LCP Echo/Reply find the fact 00631 * that PPP session is down. Asking the PPP stack to end the session 00632 * require strict checking about the PPP phase to prevent endless 00633 * disconnection loops. 00634 */ 00635 #if 0 /* UNUSED */ 00636 if (sc == NULL) { /* PADT frames are rarely sent with a hunique tag, this is actually almost always true */ 00637 goto done; 00638 } 00639 pppoe_clear_softc(sc, "received PADT"); 00640 #endif /* UNUSED */ 00641 break; 00642 default: 00643 if(sc) { 00644 PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": unknown code (0x%"X16_F") session = 0x%"X16_F"\n", 00645 sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, 00646 (u16_t)ph->code, session)); 00647 } else { 00648 PPPDEBUG(LOG_DEBUG, ("pppoe: unknown code (0x%"X16_F") session = 0x%"X16_F"\n", (u16_t)ph->code, session)); 00649 } 00650 break; 00651 } 00652 00653 done: 00654 pbuf_free(pb); 00655 return; 00656 } 00657 00658 void 00659 pppoe_data_input(struct netif *netif, struct pbuf *pb) 00660 { 00661 u16_t session, plen; 00662 struct pppoe_softc *sc; 00663 struct pppoehdr *ph; 00664 #ifdef PPPOE_TERM_UNKNOWN_SESSIONS 00665 u8_t shost[ETHER_ADDR_LEN]; 00666 #endif 00667 00668 #ifdef PPPOE_TERM_UNKNOWN_SESSIONS 00669 MEMCPY(shost, ((struct eth_hdr *)pb->payload)->src.addr, sizeof(shost)); 00670 #endif 00671 if (pbuf_header(pb, -(s16_t)sizeof(struct eth_hdr)) != 0) { 00672 /* bail out */ 00673 PPPDEBUG(LOG_ERR, ("pppoe_data_input: pbuf_header failed\n")); 00674 LINK_STATS_INC(link.lenerr); 00675 goto drop; 00676 } 00677 00678 if (pb->len < sizeof(*ph)) { 00679 PPPDEBUG(LOG_DEBUG, ("pppoe_data_input: could not get PPPoE header\n")); 00680 goto drop; 00681 } 00682 ph = (struct pppoehdr *)pb->payload; 00683 00684 if (ph->vertype != PPPOE_VERTYPE) { 00685 PPPDEBUG(LOG_DEBUG, ("pppoe (data): unknown version/type packet: 0x%x\n", ph->vertype)); 00686 goto drop; 00687 } 00688 if (ph->code != 0) { 00689 goto drop; 00690 } 00691 00692 session = ntohs(ph->session); 00693 sc = pppoe_find_softc_by_session(session, netif); 00694 if (sc == NULL) { 00695 #ifdef PPPOE_TERM_UNKNOWN_SESSIONS 00696 PPPDEBUG(LOG_DEBUG, ("pppoe: input for unknown session 0x%x, sending PADT\n", session)); 00697 pppoe_send_padt(netif, session, shost); 00698 #endif 00699 goto drop; 00700 } 00701 00702 plen = ntohs(ph->plen); 00703 00704 if (pbuf_header(pb, -(s16_t)(PPPOE_HEADERLEN)) != 0) { 00705 /* bail out */ 00706 PPPDEBUG(LOG_ERR, ("pppoe_data_input: pbuf_header PPPOE_HEADERLEN failed\n")); 00707 LINK_STATS_INC(link.lenerr); 00708 goto drop; 00709 } 00710 00711 PPPDEBUG(LOG_DEBUG, ("pppoe_data_input: %c%c%"U16_F": pkthdr.len=%d, pppoe.len=%d\n", 00712 sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, 00713 pb->len, plen)); 00714 00715 if (pb->tot_len < plen) { 00716 goto drop; 00717 } 00718 00719 /* Dispatch the packet thereby consuming it. */ 00720 ppp_input(sc->pcb, pb); 00721 return; 00722 00723 drop: 00724 pbuf_free(pb); 00725 } 00726 00727 static err_t 00728 pppoe_output(struct pppoe_softc *sc, struct pbuf *pb) 00729 { 00730 struct eth_hdr *ethhdr; 00731 u16_t etype; 00732 err_t res; 00733 00734 if (!sc->sc_ethif) { 00735 pbuf_free(pb); 00736 return ERR_IF; 00737 } 00738 00739 /* make room for Ethernet header - should not fail */ 00740 if (pbuf_header(pb, (s16_t)(sizeof(struct eth_hdr))) != 0) { 00741 /* bail out */ 00742 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)); 00743 LINK_STATS_INC(link.lenerr); 00744 pbuf_free(pb); 00745 return ERR_BUF; 00746 } 00747 ethhdr = (struct eth_hdr *)pb->payload; 00748 etype = sc->sc_state == PPPOE_STATE_SESSION ? ETHTYPE_PPPOE : ETHTYPE_PPPOEDISC; 00749 ethhdr->type = htons(etype); 00750 MEMCPY(ðhdr->dest.addr, &sc->sc_dest.addr, sizeof(ethhdr->dest.addr)); 00751 MEMCPY(ðhdr->src.addr, &sc->sc_ethif->hwaddr, sizeof(ethhdr->src.addr)); 00752 00753 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", 00754 sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, etype, 00755 sc->sc_state, sc->sc_session, 00756 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], 00757 pb->tot_len)); 00758 00759 res = sc->sc_ethif->linkoutput(sc->sc_ethif, pb); 00760 00761 pbuf_free(pb); 00762 00763 return res; 00764 } 00765 00766 static err_t 00767 pppoe_send_padi(struct pppoe_softc *sc) 00768 { 00769 struct pbuf *pb; 00770 u8_t *p; 00771 int len; 00772 #ifdef PPPOE_TODO 00773 int l1 = 0, l2 = 0; /* XXX: gcc */ 00774 #endif /* PPPOE_TODO */ 00775 00776 if (sc->sc_state >PPPOE_STATE_PADI_SENT) { 00777 PPPDEBUG(LOG_ERR, ("ERROR: pppoe_send_padi in state %d", sc->sc_state)); 00778 } 00779 00780 /* calculate length of frame (excluding ethernet header + pppoe header) */ 00781 len = 2 + 2 + 2 + 2 + sizeof sc; /* service name tag is required, host unique is send too */ 00782 #ifdef PPPOE_TODO 00783 if (sc->sc_service_name != NULL) { 00784 l1 = (int)strlen(sc->sc_service_name); 00785 len += l1; 00786 } 00787 if (sc->sc_concentrator_name != NULL) { 00788 l2 = (int)strlen(sc->sc_concentrator_name); 00789 len += 2 + 2 + l2; 00790 } 00791 #endif /* PPPOE_TODO */ 00792 LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff", 00793 sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff); 00794 00795 /* allocate a buffer */ 00796 pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN + len), PBUF_RAM); 00797 if (!pb) { 00798 return ERR_MEM; 00799 } 00800 LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); 00801 00802 p = (u8_t*)pb->payload; 00803 /* fill in pkt */ 00804 PPPOE_ADD_HEADER(p, PPPOE_CODE_PADI, 0, (u16_t)len); 00805 PPPOE_ADD_16(p, PPPOE_TAG_SNAME); 00806 #ifdef PPPOE_TODO 00807 if (sc->sc_service_name != NULL) { 00808 PPPOE_ADD_16(p, l1); 00809 MEMCPY(p, sc->sc_service_name, l1); 00810 p += l1; 00811 } else 00812 #endif /* PPPOE_TODO */ 00813 { 00814 PPPOE_ADD_16(p, 0); 00815 } 00816 #ifdef PPPOE_TODO 00817 if (sc->sc_concentrator_name != NULL) { 00818 PPPOE_ADD_16(p, PPPOE_TAG_ACNAME); 00819 PPPOE_ADD_16(p, l2); 00820 MEMCPY(p, sc->sc_concentrator_name, l2); 00821 p += l2; 00822 } 00823 #endif /* PPPOE_TODO */ 00824 PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); 00825 PPPOE_ADD_16(p, sizeof(sc)); 00826 MEMCPY(p, &sc, sizeof sc); 00827 00828 /* send pkt */ 00829 return pppoe_output(sc, pb); 00830 } 00831 00832 static void 00833 pppoe_timeout(void *arg) 00834 { 00835 u32_t retry_wait; 00836 int err; 00837 struct pppoe_softc *sc = (struct pppoe_softc*)arg; 00838 00839 PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": timeout\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); 00840 00841 switch (sc->sc_state) { 00842 case PPPOE_STATE_PADI_SENT: 00843 /* 00844 * We have two basic ways of retrying: 00845 * - Quick retry mode: try a few times in short sequence 00846 * - Slow retry mode: we already had a connection successfully 00847 * established and will try infinitely (without user 00848 * intervention) 00849 * We only enter slow retry mode if IFF_LINK1 (aka autodial) 00850 * is not set. 00851 */ 00852 if (sc->sc_padi_retried < 0xff) { 00853 sc->sc_padi_retried++; 00854 } 00855 if (!sc->pcb->settings.persist && sc->sc_padi_retried >= PPPOE_DISC_MAXPADI) { 00856 #if 0 00857 if ((sc->sc_sppp.pp_if.if_flags & IFF_LINK1) == 0) { 00858 /* slow retry mode */ 00859 retry_wait = PPPOE_SLOW_RETRY; 00860 } else 00861 #endif 00862 { 00863 pppoe_abort_connect(sc); 00864 return; 00865 } 00866 } 00867 /* initialize for quick retry mode */ 00868 retry_wait = LWIP_MIN(PPPOE_DISC_TIMEOUT * sc->sc_padi_retried, PPPOE_SLOW_RETRY); 00869 if ((err = pppoe_send_padi(sc)) != 0) { 00870 sc->sc_padi_retried--; 00871 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)); 00872 } 00873 sys_timeout(retry_wait, pppoe_timeout, sc); 00874 break; 00875 00876 case PPPOE_STATE_PADR_SENT: 00877 sc->sc_padr_retried++; 00878 if (sc->sc_padr_retried >= PPPOE_DISC_MAXPADR) { 00879 MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); 00880 sc->sc_state = PPPOE_STATE_PADI_SENT; 00881 sc->sc_padr_retried = 0; 00882 if ((err = pppoe_send_padi(sc)) != 0) { 00883 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)); 00884 } 00885 sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padi_retried), pppoe_timeout, sc); 00886 return; 00887 } 00888 if ((err = pppoe_send_padr(sc)) != 0) { 00889 sc->sc_padr_retried--; 00890 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)); 00891 } 00892 sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc); 00893 break; 00894 default: 00895 return; /* all done, work in peace */ 00896 } 00897 } 00898 00899 /* Start a connection (i.e. initiate discovery phase) */ 00900 static err_t 00901 pppoe_connect(ppp_pcb *ppp, void *ctx) 00902 { 00903 int err; 00904 struct pppoe_softc *sc = (struct pppoe_softc *)ctx; 00905 lcp_options *lcp_wo; 00906 lcp_options *lcp_ao; 00907 #if PPP_IPV4_SUPPORT && VJ_SUPPORT 00908 ipcp_options *ipcp_wo; 00909 ipcp_options *ipcp_ao; 00910 #endif /* PPP_IPV4_SUPPORT && VJ_SUPPORT */ 00911 00912 if (sc->sc_state != PPPOE_STATE_INITIAL) { 00913 return EBUSY; 00914 } 00915 00916 /* stop any timer */ 00917 sys_untimeout(pppoe_timeout, sc); 00918 sc->sc_session = 0; 00919 sc->sc_padi_retried = 0; 00920 sc->sc_padr_retried = 0; 00921 #ifdef PPPOE_SERVER 00922 /* wait PADI if IFF_PASSIVE */ 00923 if ((sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) { 00924 return 0; 00925 } 00926 #endif 00927 00928 ppp_link_start(ppp); 00929 00930 lcp_wo = &ppp->lcp_wantoptions; 00931 lcp_wo->mru = sc->sc_ethif->mtu-PPPOE_HEADERLEN-2; /* two byte PPP protocol discriminator, then IP data */ 00932 lcp_wo->neg_asyncmap = 0; 00933 lcp_wo->neg_pcompression = 0; 00934 lcp_wo->neg_accompression = 0; 00935 lcp_wo->passive = 0; 00936 lcp_wo->silent = 0; 00937 00938 lcp_ao = &ppp->lcp_allowoptions; 00939 lcp_ao->mru = sc->sc_ethif->mtu-PPPOE_HEADERLEN-2; /* two byte PPP protocol discriminator, then IP data */ 00940 lcp_ao->neg_asyncmap = 0; 00941 lcp_ao->neg_pcompression = 0; 00942 lcp_ao->neg_accompression = 0; 00943 00944 #if PPP_IPV4_SUPPORT && VJ_SUPPORT 00945 ipcp_wo = &ppp->ipcp_wantoptions; 00946 ipcp_wo->neg_vj = 0; 00947 ipcp_wo->old_vj = 0; 00948 00949 ipcp_ao = &ppp->ipcp_allowoptions; 00950 ipcp_ao->neg_vj = 0; 00951 ipcp_ao->old_vj = 0; 00952 #endif /* PPP_IPV4_SUPPORT && VJ_SUPPORT */ 00953 00954 /* save state, in case we fail to send PADI */ 00955 sc->sc_state = PPPOE_STATE_PADI_SENT; 00956 if ((err = pppoe_send_padi(sc)) != 0) { 00957 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)); 00958 } 00959 sys_timeout(PPPOE_DISC_TIMEOUT, pppoe_timeout, sc); 00960 return err; 00961 } 00962 00963 /* disconnect */ 00964 static void 00965 pppoe_disconnect(ppp_pcb *ppp, void *ctx) 00966 { 00967 struct pppoe_softc *sc = (struct pppoe_softc *)ctx; 00968 00969 if (sc->sc_state < PPPOE_STATE_SESSION) { 00970 return; 00971 } 00972 00973 PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": disconnecting\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); 00974 pppoe_send_padt(sc->sc_ethif, sc->sc_session, (const u8_t *)&sc->sc_dest); 00975 00976 /* cleanup softc */ 00977 sc->sc_state = PPPOE_STATE_INITIAL; 00978 MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); 00979 sc->sc_ac_cookie_len = 0; 00980 #ifdef PPPOE_SERVER 00981 if (sc->sc_hunique) { 00982 mem_free(sc->sc_hunique); 00983 sc->sc_hunique = NULL; 00984 } 00985 sc->sc_hunique_len = 0; 00986 #endif 00987 sc->sc_session = 0; 00988 sc->sc_padi_retried = 0; 00989 sc->sc_padr_retried = 0; 00990 00991 ppp_link_end(ppp); /* notify upper layers */ 00992 return; 00993 } 00994 00995 /* Connection attempt aborted */ 00996 static void 00997 pppoe_abort_connect(struct pppoe_softc *sc) 00998 { 00999 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)); 01000 01001 /* clear connection state */ 01002 sc->sc_state = PPPOE_STATE_INITIAL; 01003 MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); 01004 sc->sc_ac_cookie_len = 0; 01005 sc->sc_session = 0; 01006 sc->sc_padi_retried = 0; 01007 sc->sc_padr_retried = 0; 01008 01009 ppp_link_failed(sc->pcb); /* notify upper layers */ 01010 } 01011 01012 /* Send a PADR packet */ 01013 static err_t 01014 pppoe_send_padr(struct pppoe_softc *sc) 01015 { 01016 struct pbuf *pb; 01017 u8_t *p; 01018 size_t len; 01019 #ifdef PPPOE_TODO 01020 size_t l1 = 0; /* XXX: gcc */ 01021 #endif /* PPPOE_TODO */ 01022 01023 if (sc->sc_state != PPPOE_STATE_PADR_SENT) { 01024 return ERR_CONN; 01025 } 01026 01027 len = 2 + 2 + 2 + 2 + sizeof(sc); /* service name, host unique */ 01028 #ifdef PPPOE_TODO 01029 if (sc->sc_service_name != NULL) { /* service name tag maybe empty */ 01030 l1 = strlen(sc->sc_service_name); 01031 len += l1; 01032 } 01033 #endif /* PPPOE_TODO */ 01034 if (sc->sc_ac_cookie_len > 0) { 01035 len += 2 + 2 + sc->sc_ac_cookie_len; /* AC cookie */ 01036 } 01037 LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff", 01038 sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff); 01039 pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN + len), PBUF_RAM); 01040 if (!pb) { 01041 return ERR_MEM; 01042 } 01043 LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); 01044 p = (u8_t*)pb->payload; 01045 PPPOE_ADD_HEADER(p, PPPOE_CODE_PADR, 0, len); 01046 PPPOE_ADD_16(p, PPPOE_TAG_SNAME); 01047 #ifdef PPPOE_TODO 01048 if (sc->sc_service_name != NULL) { 01049 PPPOE_ADD_16(p, l1); 01050 MEMCPY(p, sc->sc_service_name, l1); 01051 p += l1; 01052 } else 01053 #endif /* PPPOE_TODO */ 01054 { 01055 PPPOE_ADD_16(p, 0); 01056 } 01057 if (sc->sc_ac_cookie_len > 0) { 01058 PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE); 01059 PPPOE_ADD_16(p, sc->sc_ac_cookie_len); 01060 MEMCPY(p, sc->sc_ac_cookie, sc->sc_ac_cookie_len); 01061 p += sc->sc_ac_cookie_len; 01062 } 01063 PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); 01064 PPPOE_ADD_16(p, sizeof(sc)); 01065 MEMCPY(p, &sc, sizeof sc); 01066 01067 return pppoe_output(sc, pb); 01068 } 01069 01070 /* send a PADT packet */ 01071 static err_t 01072 pppoe_send_padt(struct netif *outgoing_if, u_int session, const u8_t *dest) 01073 { 01074 struct pbuf *pb; 01075 struct eth_hdr *ethhdr; 01076 err_t res; 01077 u8_t *p; 01078 01079 pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN), PBUF_RAM); 01080 if (!pb) { 01081 return ERR_MEM; 01082 } 01083 LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); 01084 01085 pbuf_header(pb, (s16_t)sizeof(struct eth_hdr)); 01086 ethhdr = (struct eth_hdr *)pb->payload; 01087 ethhdr->type = PP_HTONS(ETHTYPE_PPPOEDISC); 01088 MEMCPY(ðhdr->dest.addr, dest, sizeof(ethhdr->dest.addr)); 01089 MEMCPY(ðhdr->src.addr, &outgoing_if->hwaddr, sizeof(ethhdr->src.addr)); 01090 01091 p = (u8_t*)(ethhdr + 1); 01092 PPPOE_ADD_HEADER(p, PPPOE_CODE_PADT, session, 0); 01093 01094 res = outgoing_if->linkoutput(outgoing_if, pb); 01095 01096 pbuf_free(pb); 01097 01098 return res; 01099 } 01100 01101 #ifdef PPPOE_SERVER 01102 static err_t 01103 pppoe_send_pado(struct pppoe_softc *sc) 01104 { 01105 struct pbuf *pb; 01106 u8_t *p; 01107 size_t len; 01108 01109 if (sc->sc_state != PPPOE_STATE_PADO_SENT) { 01110 return ERR_CONN; 01111 } 01112 01113 /* calc length */ 01114 len = 0; 01115 /* include ac_cookie */ 01116 len += 2 + 2 + sizeof(sc); 01117 /* include hunique */ 01118 len += 2 + 2 + sc->sc_hunique_len; 01119 pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN + len), PBUF_RAM); 01120 if (!pb) { 01121 return ERR_MEM; 01122 } 01123 LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); 01124 p = (u8_t*)pb->payload; 01125 PPPOE_ADD_HEADER(p, PPPOE_CODE_PADO, 0, len); 01126 PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE); 01127 PPPOE_ADD_16(p, sizeof(sc)); 01128 MEMCPY(p, &sc, sizeof(sc)); 01129 p += sizeof(sc); 01130 PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); 01131 PPPOE_ADD_16(p, sc->sc_hunique_len); 01132 MEMCPY(p, sc->sc_hunique, sc->sc_hunique_len); 01133 return pppoe_output(sc, pb); 01134 } 01135 01136 static err_t 01137 pppoe_send_pads(struct pppoe_softc *sc) 01138 { 01139 struct pbuf *pb; 01140 u8_t *p; 01141 size_t len, l1 = 0; /* XXX: gcc */ 01142 01143 if (sc->sc_state != PPPOE_STATE_PADO_SENT) { 01144 return ERR_CONN; 01145 } 01146 01147 sc->sc_session = mono_time.tv_sec % 0xff + 1; 01148 /* calc length */ 01149 len = 0; 01150 /* include hunique */ 01151 len += 2 + 2 + 2 + 2 + sc->sc_hunique_len; /* service name, host unique*/ 01152 if (sc->sc_service_name != NULL) { /* service name tag maybe empty */ 01153 l1 = strlen(sc->sc_service_name); 01154 len += l1; 01155 } 01156 pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN + len), PBUF_RAM); 01157 if (!pb) { 01158 return ERR_MEM; 01159 } 01160 LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); 01161 p = (u8_t*)pb->payload; 01162 PPPOE_ADD_HEADER(p, PPPOE_CODE_PADS, sc->sc_session, len); 01163 PPPOE_ADD_16(p, PPPOE_TAG_SNAME); 01164 if (sc->sc_service_name != NULL) { 01165 PPPOE_ADD_16(p, l1); 01166 MEMCPY(p, sc->sc_service_name, l1); 01167 p += l1; 01168 } else { 01169 PPPOE_ADD_16(p, 0); 01170 } 01171 PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); 01172 PPPOE_ADD_16(p, sc->sc_hunique_len); 01173 MEMCPY(p, sc->sc_hunique, sc->sc_hunique_len); 01174 return pppoe_output(sc, pb); 01175 } 01176 #endif 01177 01178 static err_t 01179 pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb) 01180 { 01181 u8_t *p; 01182 size_t len; 01183 01184 /* are we ready to process data yet? */ 01185 if (sc->sc_state < PPPOE_STATE_SESSION) { 01186 /*sppp_flush(&sc->sc_sppp.pp_if);*/ 01187 pbuf_free(pb); 01188 return ERR_CONN; 01189 } 01190 01191 len = pb->tot_len; 01192 01193 /* make room for PPPoE header - should not fail */ 01194 if (pbuf_header(pb, (s16_t)(PPPOE_HEADERLEN)) != 0) { 01195 /* bail out */ 01196 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)); 01197 LINK_STATS_INC(link.lenerr); 01198 pbuf_free(pb); 01199 return ERR_BUF; 01200 } 01201 01202 p = (u8_t*)pb->payload; 01203 PPPOE_ADD_HEADER(p, 0, sc->sc_session, len); 01204 01205 return pppoe_output(sc, pb); 01206 } 01207 01208 #if 0 /*def PFIL_HOOKS*/ 01209 static int 01210 pppoe_ifattach_hook(void *arg, struct pbuf **mp, struct netif *ifp, int dir) 01211 { 01212 struct pppoe_softc *sc; 01213 int s; 01214 01215 if (mp != (struct pbuf **)PFIL_IFNET_DETACH) { 01216 return 0; 01217 } 01218 01219 LIST_FOREACH(sc, &pppoe_softc_list, sc_list) { 01220 if (sc->sc_ethif != ifp) { 01221 continue; 01222 } 01223 if (sc->sc_sppp.pp_if.if_flags & IFF_UP) { 01224 sc->sc_sppp.pp_if.if_flags &= ~(IFF_UP|IFF_RUNNING); 01225 PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": ethernet interface detached, going down\n", 01226 sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); 01227 } 01228 sc->sc_ethif = NULL; 01229 pppoe_clear_softc(sc, "ethernet interface detached"); 01230 } 01231 01232 return 0; 01233 } 01234 #endif 01235 01236 #if 0 /* UNUSED */ 01237 static void 01238 pppoe_clear_softc(struct pppoe_softc *sc, const char *message) 01239 { 01240 LWIP_UNUSED_ARG(message); 01241 01242 /* stop timer */ 01243 sys_untimeout(pppoe_timeout, sc); 01244 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)); 01245 /* fix our state */ 01246 sc->sc_state = PPPOE_STATE_INITIAL; 01247 01248 /* notify upper layers */ 01249 ppp_link_end(sc->pcb); /* /!\ dangerous /!\ */ 01250 01251 /* clean up softc */ 01252 MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); 01253 sc->sc_ac_cookie_len = 0; 01254 sc->sc_session = 0; 01255 sc->sc_padi_retried = 0; 01256 sc->sc_padr_retried = 0; 01257 } 01258 #endif /* UNUSED */ 01259 #endif /* PPP_SUPPORT && PPPOE_SUPPORT */
Generated on Tue Jul 12 2022 11:02:42 by
