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