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