NetServices Stack source
Dependents: HelloWorld ServoInterfaceBoardExample1 4180_Lab4
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:52:58 by 1.7.2