ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

ppp_oe.c
Go to the documentation of this file.
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 
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 Sat May 26 2012 04:35:01 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.