Darran Shepherd
/
AutoIpNetStack
Net stack with AutoIP enabled
Embed:
(wiki syntax)
Show/hide line numbers
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 "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 15:37:05 by 1.7.2