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.
Fork of mbed-os by
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 13:15:54 by
