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