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