ReactOS 0.4.16-dev-819-g75c0dc0
pppoe.c
Go to the documentation of this file.
1/*****************************************************************************
2* pppoe.c - PPP Over Ethernet implementation for lwIP.
3*
4* Copyright (c) 2006 by Marc Boucher, Services Informatiques (MBSI) inc.
5*
6* The authors hereby grant permission to use, copy, modify, distribute,
7* and license this software and its documentation for any purpose, provided
8* that existing copyright notices are retained in all copies and that this
9* notice and the following disclaimer are included verbatim in any
10* distributions. No written agreement, license, or royalty fee is required
11* for any of the authorized uses.
12*
13* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
14* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
17* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23*
24******************************************************************************
25* REVISION HISTORY
26*
27* 06-01-01 Marc Boucher <marc@mbsi.ca>
28* Ported to lwIP.
29*****************************************************************************/
30
31
32
33/* based on NetBSD: if_pppoe.c,v 1.64 2006/01/31 23:50:15 martin Exp */
34
35/*-
36 * Copyright (c) 2002 The NetBSD Foundation, Inc.
37 * All rights reserved.
38 *
39 * This code is derived from software contributed to The NetBSD Foundation
40 * by Martin Husemann <martin@NetBSD.org>.
41 *
42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions
44 * are met:
45 * 1. Redistributions of source code must retain the above copyright
46 * notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above copyright
48 * notice, this list of conditions and the following disclaimer in the
49 * documentation and/or other materials provided with the distribution.
50 * 3. All advertising materials mentioning features or use of this software
51 * must display the following acknowledgement:
52 * This product includes software developed by the NetBSD
53 * Foundation, Inc. and its contributors.
54 * 4. Neither the name of The NetBSD Foundation nor the names of its
55 * contributors may be used to endorse or promote products derived
56 * from this software without specific prior written permission.
57 *
58 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
59 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
60 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
61 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
62 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
63 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
64 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
65 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
66 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
67 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
68 * POSSIBILITY OF SUCH DAMAGE.
69 */
70
71#include "netif/ppp/ppp_opts.h"
72#if PPP_SUPPORT && PPPOE_SUPPORT /* don't build if not configured for use in lwipopts.h */
73
74#if 0 /* UNUSED */
75#include <string.h>
76#include <stdio.h>
77#endif /* UNUSED */
78
79#include "lwip/timeouts.h"
80#include "lwip/memp.h"
81#include "lwip/stats.h"
82#include "lwip/snmp.h"
83
84#include "netif/ethernet.h"
85#include "netif/ppp/ppp_impl.h"
86#include "netif/ppp/lcp.h"
87#include "netif/ppp/ipcp.h"
88#include "netif/ppp/pppoe.h"
89
90/* Memory pool */
91LWIP_MEMPOOL_DECLARE(PPPOE_IF, MEMP_NUM_PPPOE_INTERFACES, sizeof(struct pppoe_softc), "PPPOE_IF")
92
93/* Add a 16 bit unsigned value to a buffer pointed to by PTR */
94#define PPPOE_ADD_16(PTR, VAL) \
95 *(PTR)++ = (u8_t)((VAL) / 256); \
96 *(PTR)++ = (u8_t)((VAL) % 256)
97
98/* Add a complete PPPoE header to the buffer pointed to by PTR */
99#define PPPOE_ADD_HEADER(PTR, CODE, SESS, LEN) \
100 *(PTR)++ = PPPOE_VERTYPE; \
101 *(PTR)++ = (CODE); \
102 PPPOE_ADD_16(PTR, SESS); \
103 PPPOE_ADD_16(PTR, LEN)
104
105#define PPPOE_DISC_TIMEOUT (5*1000) /* base for quick timeout calculation */
106#define PPPOE_SLOW_RETRY (60*1000) /* persistent retry interval */
107#define PPPOE_DISC_MAXPADI 4 /* retry PADI four times (quickly) */
108#define PPPOE_DISC_MAXPADR 2 /* retry PADR twice */
109
110#ifdef PPPOE_SERVER
111#error "PPPOE_SERVER is not yet supported under lwIP!"
112/* from if_spppsubr.c */
113#define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */
114#endif
115
116#define PPPOE_ERRORSTRING_LEN 64
117
118
119/* callbacks called from PPP core */
120static err_t pppoe_write(ppp_pcb *ppp, void *ctx, struct pbuf *p);
121static err_t pppoe_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *p, u_short protocol);
122static void pppoe_connect(ppp_pcb *ppp, void *ctx);
123static void pppoe_disconnect(ppp_pcb *ppp, void *ctx);
124static err_t pppoe_destroy(ppp_pcb *ppp, void *ctx);
125
126/* management routines */
127static void pppoe_abort_connect(struct pppoe_softc *);
128#if 0 /* UNUSED */
129static void pppoe_clear_softc(struct pppoe_softc *, const char *);
130#endif /* UNUSED */
131
132/* internal timeout handling */
133static void pppoe_timeout(void *);
134
135/* sending actual protocol control packets */
136static err_t pppoe_send_padi(struct pppoe_softc *);
137static err_t pppoe_send_padr(struct pppoe_softc *);
138#ifdef PPPOE_SERVER
139static err_t pppoe_send_pado(struct pppoe_softc *);
140static err_t pppoe_send_pads(struct pppoe_softc *);
141#endif
142static err_t pppoe_send_padt(struct netif *, u_int, const u8_t *);
143
144/* internal helper functions */
145static err_t pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb);
146static struct pppoe_softc* pppoe_find_softc_by_session(u_int session, struct netif *rcvif);
147static struct pppoe_softc* pppoe_find_softc_by_hunique(u8_t *token, size_t len, struct netif *rcvif);
148
150static struct pppoe_softc *pppoe_softc_list;
151
152/* Callbacks structure for PPP core */
153static const struct link_callbacks pppoe_callbacks = {
154 pppoe_connect,
155#if PPP_SERVER
156 NULL,
157#endif /* PPP_SERVER */
158 pppoe_disconnect,
159 pppoe_destroy,
160 pppoe_write,
161 pppoe_netif_output,
162 NULL,
163 NULL
164};
165
166/*
167 * Create a new PPP Over Ethernet (PPPoE) connection.
168 *
169 * Return 0 on success, an error code on failure.
170 */
171ppp_pcb *pppoe_create(struct netif *pppif,
172 struct netif *ethif,
173 const char *service_name, const char *concentrator_name,
174 ppp_link_status_cb_fn link_status_cb, void *ctx_cb)
175{
176 ppp_pcb *ppp;
177 struct pppoe_softc *sc;
178#if PPPOE_SCNAME_SUPPORT
179 size_t l;
180#else /* PPPOE_SCNAME_SUPPORT */
182 LWIP_UNUSED_ARG(concentrator_name);
183#endif /* PPPOE_SCNAME_SUPPORT */
185
186#if PPPOE_SCNAME_SUPPORT
187 /*
188 * Check that service_name and concentrator_name strings length will
189 * not trigger integer overflows when computing packets length.
190 */
192 if (l > 1024) {
193 return NULL;
194 }
195 l = strlen(concentrator_name);
196 if (l > 1024) {
197 return NULL;
198 }
199#endif /* PPPOE_SCNAME_SUPPORT */
200
201 sc = (struct pppoe_softc *)LWIP_MEMPOOL_ALLOC(PPPOE_IF);
202 if (sc == NULL) {
203 return NULL;
204 }
205
206 ppp = ppp_new(pppif, &pppoe_callbacks, sc, link_status_cb, ctx_cb);
207 if (ppp == NULL) {
208 LWIP_MEMPOOL_FREE(PPPOE_IF, sc);
209 return NULL;
210 }
211
212 memset(sc, 0, sizeof(struct pppoe_softc));
213 sc->pcb = ppp;
214 sc->sc_ethif = ethif;
215#if PPPOE_SCNAME_SUPPORT
216 sc->sc_service_name = service_name;
217 sc->sc_concentrator_name = concentrator_name;
218#endif /* PPPOE_SCNAME_SUPPORT */
219 /* put the new interface at the head of the list */
220 sc->next = pppoe_softc_list;
221 pppoe_softc_list = sc;
222 return ppp;
223}
224
225/* Called by PPP core */
226static err_t pppoe_write(ppp_pcb *ppp, void *ctx, struct pbuf *p) {
227 struct pppoe_softc *sc = (struct pppoe_softc *)ctx;
228 struct pbuf *ph; /* Ethernet + PPPoE header */
229 err_t ret;
230#if MIB2_STATS
232#else /* MIB2_STATS */
233 LWIP_UNUSED_ARG(ppp);
234#endif /* MIB2_STATS */
235
236 /* skip address & flags */
238
239 ph = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN), PBUF_RAM);
240 if(!ph) {
241 LINK_STATS_INC(link.memerr);
242 LINK_STATS_INC(link.proterr);
243 MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards);
244 pbuf_free(p);
245 return ERR_MEM;
246 }
247
248 pbuf_remove_header(ph, PPPOE_HEADERLEN); /* hide PPPoE header */
249 pbuf_cat(ph, p);
250#if MIB2_STATS
251 tot_len = ph->tot_len;
252#endif /* MIB2_STATS */
253
254 ret = pppoe_xmit(sc, ph);
255 if (ret != ERR_OK) {
256 LINK_STATS_INC(link.err);
257 MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards);
258 return ret;
259 }
260
261 MIB2_STATS_NETIF_ADD(ppp->netif, ifoutoctets, (u16_t)tot_len);
262 MIB2_STATS_NETIF_INC(ppp->netif, ifoutucastpkts);
263 LINK_STATS_INC(link.xmit);
264 return ERR_OK;
265}
266
267/* Called by PPP core */
268static err_t pppoe_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *p, u_short protocol) {
269 struct pppoe_softc *sc = (struct pppoe_softc *)ctx;
270 struct pbuf *pb;
271 u8_t *pl;
272 err_t err;
273#if MIB2_STATS
275#else /* MIB2_STATS */
276 LWIP_UNUSED_ARG(ppp);
277#endif /* MIB2_STATS */
278
279 /* @todo: try to use pbuf_header() here! */
280 pb = pbuf_alloc(PBUF_LINK, PPPOE_HEADERLEN + sizeof(protocol), PBUF_RAM);
281 if(!pb) {
282 LINK_STATS_INC(link.memerr);
283 LINK_STATS_INC(link.proterr);
284 MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards);
285 return ERR_MEM;
286 }
287
288 pbuf_remove_header(pb, PPPOE_HEADERLEN);
289
290 pl = (u8_t*)pb->payload;
291 PUTSHORT(protocol, pl);
292
293 pbuf_chain(pb, p);
294#if MIB2_STATS
295 tot_len = pb->tot_len;
296#endif /* MIB2_STATS */
297
298 if( (err = pppoe_xmit(sc, pb)) != ERR_OK) {
299 LINK_STATS_INC(link.err);
300 MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards);
301 return err;
302 }
303
304 MIB2_STATS_NETIF_ADD(ppp->netif, ifoutoctets, tot_len);
305 MIB2_STATS_NETIF_INC(ppp->netif, ifoutucastpkts);
306 LINK_STATS_INC(link.xmit);
307 return ERR_OK;
308}
309
310static err_t
311pppoe_destroy(ppp_pcb *ppp, void *ctx)
312{
313 struct pppoe_softc *sc = (struct pppoe_softc *)ctx;
314 struct pppoe_softc **copp, *freep;
315 LWIP_UNUSED_ARG(ppp);
316
317 sys_untimeout(pppoe_timeout, sc);
318
319 /* remove interface from list */
320 for (copp = &pppoe_softc_list; (freep = *copp); copp = &freep->next) {
321 if (freep == sc) {
322 *copp = freep->next;
323 break;
324 }
325 }
326 LWIP_MEMPOOL_FREE(PPPOE_IF, sc);
327
328 return ERR_OK;
329}
330
331/*
332 * Find the interface handling the specified session.
333 * Note: O(number of sessions open), this is a client-side only, mean
334 * and lean implementation, so number of open sessions typically should
335 * be 1.
336 */
337static struct pppoe_softc* pppoe_find_softc_by_session(u_int session, struct netif *rcvif) {
338 struct pppoe_softc *sc;
339
340 for (sc = pppoe_softc_list; sc != NULL; sc = sc->next) {
341 if (sc->sc_state == PPPOE_STATE_SESSION
342 && sc->sc_session == session
343 && sc->sc_ethif == rcvif) {
344 return sc;
345 }
346 }
347 return NULL;
348}
349
350/* Check host unique token passed and return appropriate softc pointer,
351 * or NULL if token is bogus. */
352static struct pppoe_softc* pppoe_find_softc_by_hunique(u8_t *token, size_t len, struct netif *rcvif) {
353 struct pppoe_softc *sc, *t;
354
355 if (len != sizeof sc) {
356 return NULL;
357 }
358 MEMCPY(&t, token, len);
359
360 for (sc = pppoe_softc_list; sc != NULL; sc = sc->next) {
361 if (sc == t) {
362 break;
363 }
364 }
365
366 if (sc == NULL) {
367 PPPDEBUG(LOG_DEBUG, ("pppoe: alien host unique tag, no session found\n"));
368 return NULL;
369 }
370
371 /* should be safe to access *sc now */
372 if (sc->sc_state < PPPOE_STATE_PADI_SENT || sc->sc_state >= PPPOE_STATE_SESSION) {
373 PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": host unique tag found, but it belongs to a connection in state %d\n",
374 sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_state));
375 return NULL;
376 }
377 if (sc->sc_ethif != rcvif) {
378 PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": wrong interface, not accepting host unique\n",
379 sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num));
380 return NULL;
381 }
382 return sc;
383}
384
385/* analyze and handle a single received packet while not in session state */
386void
387pppoe_disc_input(struct netif *netif, struct pbuf *pb)
388{
389 u16_t tag, len, off;
390 u16_t session, plen;
391 struct pppoe_softc *sc;
392#if PPP_DEBUG
393 const char *err_msg = NULL;
394#endif /* PPP_DEBUG */
395 u8_t *ac_cookie;
396 u16_t ac_cookie_len;
397#ifdef PPPOE_SERVER
398 u8_t *hunique;
399 size_t hunique_len;
400#endif
401 struct pppoehdr *ph;
402 struct pppoetag pt;
403 int err;
404 struct eth_hdr *ethhdr;
405
406 /* don't do anything if there is not a single PPPoE instance */
407 if (pppoe_softc_list == NULL) {
408 pbuf_free(pb);
409 return;
410 }
411
412 pb = pbuf_coalesce(pb, PBUF_RAW);
413 if (pb->next != NULL) {
414 PPPDEBUG(LOG_DEBUG, ("pppoe: pbuf_coalesce failed: %d\n", pb->tot_len));
415 goto done;
416 }
417
418 ethhdr = (struct eth_hdr *)pb->payload;
419
420 ac_cookie = NULL;
421 ac_cookie_len = 0;
422#ifdef PPPOE_SERVER
423 hunique = NULL;
424 hunique_len = 0;
425#endif
426 session = 0;
427 off = sizeof(struct eth_hdr) + sizeof(struct pppoehdr);
428 if (pb->len < off) {
429 PPPDEBUG(LOG_DEBUG, ("pppoe: packet too short: %d\n", pb->len));
430 goto done;
431 }
432
433 ph = (struct pppoehdr *) (ethhdr + 1);
434 if (ph->vertype != PPPOE_VERTYPE) {
435 PPPDEBUG(LOG_DEBUG, ("pppoe: unknown version/type packet: 0x%x\n", ph->vertype));
436 goto done;
437 }
438 session = lwip_ntohs(ph->session);
439 plen = lwip_ntohs(ph->plen);
440
441 if (plen > (pb->len - off)) {
442 PPPDEBUG(LOG_DEBUG, ("pppoe: packet content does not fit: data available = %d, packet size = %u\n",
443 pb->len - off, plen));
444 goto done;
445 }
446 if(pb->tot_len == pb->len) {
447 u16_t framelen = off + plen;
448 if (framelen < pb->len) {
449 /* ignore trailing garbage */
450 pb->tot_len = pb->len = framelen;
451 }
452 }
453 tag = 0;
454 len = 0;
455 sc = NULL;
456 while (off + sizeof(pt) <= pb->len) {
457 MEMCPY(&pt, (u8_t*)pb->payload + off, sizeof(pt));
458 tag = lwip_ntohs(pt.tag);
459 len = lwip_ntohs(pt.len);
460 if (off + sizeof(pt) + len > pb->len) {
461 PPPDEBUG(LOG_DEBUG, ("pppoe: tag 0x%x len 0x%x is too long\n", tag, len));
462 goto done;
463 }
464 switch (tag) {
465 case PPPOE_TAG_EOL:
466 goto breakbreak;
467 case PPPOE_TAG_SNAME:
468 break; /* ignored */
469 case PPPOE_TAG_ACNAME:
470 break; /* ignored */
471 case PPPOE_TAG_HUNIQUE:
472 if (sc != NULL) {
473 break;
474 }
475#ifdef PPPOE_SERVER
476 hunique = (u8_t*)pb->payload + off + sizeof(pt);
477 hunique_len = len;
478#endif
479 sc = pppoe_find_softc_by_hunique((u8_t*)pb->payload + off + sizeof(pt), len, netif);
480 break;
481 case PPPOE_TAG_ACCOOKIE:
482 if (ac_cookie == NULL) {
483 if (len > PPPOE_MAX_AC_COOKIE_LEN) {
484 PPPDEBUG(LOG_DEBUG, ("pppoe: AC cookie is too long: len = %d, max = %d\n", len, PPPOE_MAX_AC_COOKIE_LEN));
485 goto done;
486 }
487 ac_cookie = (u8_t*)pb->payload + off + sizeof(pt);
488 ac_cookie_len = len;
489 }
490 break;
491#if PPP_DEBUG
492 case PPPOE_TAG_SNAME_ERR:
493 err_msg = "SERVICE NAME ERROR";
494 break;
495 case PPPOE_TAG_ACSYS_ERR:
496 err_msg = "AC SYSTEM ERROR";
497 break;
498 case PPPOE_TAG_GENERIC_ERR:
499 err_msg = "GENERIC ERROR";
500 break;
501#endif /* PPP_DEBUG */
502 default:
503 break;
504 }
505#if PPP_DEBUG
506 if (err_msg != NULL) {
507 char error_tmp[PPPOE_ERRORSTRING_LEN];
508 u16_t error_len = LWIP_MIN(len, sizeof(error_tmp)-1);
509 strncpy(error_tmp, (char*)pb->payload + off + sizeof(pt), error_len);
510 error_tmp[error_len] = '\0';
511 if (sc) {
512 PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": %s: %s\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err_msg, error_tmp));
513 } else {
514 PPPDEBUG(LOG_DEBUG, ("pppoe: %s: %s\n", err_msg, error_tmp));
515 }
516 }
517#endif /* PPP_DEBUG */
518 off += sizeof(pt) + len;
519 }
520
521breakbreak:;
522 switch (ph->code) {
523 case PPPOE_CODE_PADI:
524#ifdef PPPOE_SERVER
525 /*
526 * got service name, concentrator name, and/or host unique.
527 * ignore if we have no interfaces with IFF_PASSIVE|IFF_UP.
528 */
529 if (LIST_EMPTY(&pppoe_softc_list)) {
530 goto done;
531 }
532 LIST_FOREACH(sc, &pppoe_softc_list, sc_list) {
533 if (!(sc->sc_sppp.pp_if.if_flags & IFF_UP)) {
534 continue;
535 }
536 if (!(sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) {
537 continue;
538 }
539 if (sc->sc_state == PPPOE_STATE_INITIAL) {
540 break;
541 }
542 }
543 if (sc == NULL) {
544 /* PPPDEBUG(LOG_DEBUG, ("pppoe: free passive interface is not found\n")); */
545 goto done;
546 }
547 if (hunique) {
548 if (sc->sc_hunique) {
549 mem_free(sc->sc_hunique);
550 }
551 sc->sc_hunique = mem_malloc(hunique_len);
552 if (sc->sc_hunique == NULL) {
553 goto done;
554 }
555 sc->sc_hunique_len = hunique_len;
556 MEMCPY(sc->sc_hunique, hunique, hunique_len);
557 }
558 MEMCPY(&sc->sc_dest, eh->ether_shost, sizeof sc->sc_dest);
559 sc->sc_state = PPPOE_STATE_PADO_SENT;
560 pppoe_send_pado(sc);
561 break;
562#endif /* PPPOE_SERVER */
563 case PPPOE_CODE_PADR:
564#ifdef PPPOE_SERVER
565 /*
566 * get sc from ac_cookie if IFF_PASSIVE
567 */
568 if (ac_cookie == NULL) {
569 /* be quiet if there is not a single pppoe instance */
570 PPPDEBUG(LOG_DEBUG, ("pppoe: received PADR but not includes ac_cookie\n"));
571 goto done;
572 }
573 sc = pppoe_find_softc_by_hunique(ac_cookie, ac_cookie_len, netif);
574 if (sc == NULL) {
575 /* be quiet if there is not a single pppoe instance */
576 if (!LIST_EMPTY(&pppoe_softc_list)) {
577 PPPDEBUG(LOG_DEBUG, ("pppoe: received PADR but could not find request for it\n"));
578 }
579 goto done;
580 }
581 if (sc->sc_state != PPPOE_STATE_PADO_SENT) {
582 PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": received unexpected PADR\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num));
583 goto done;
584 }
585 if (hunique) {
586 if (sc->sc_hunique) {
587 mem_free(sc->sc_hunique);
588 }
589 sc->sc_hunique = mem_malloc(hunique_len);
590 if (sc->sc_hunique == NULL) {
591 goto done;
592 }
593 sc->sc_hunique_len = hunique_len;
594 MEMCPY(sc->sc_hunique, hunique, hunique_len);
595 }
596 pppoe_send_pads(sc);
597 sc->sc_state = PPPOE_STATE_SESSION;
598 ppp_start(sc->pcb); /* notify upper layers */
599 break;
600#else
601 /* ignore, we are no access concentrator */
602 goto done;
603#endif /* PPPOE_SERVER */
604 case PPPOE_CODE_PADO:
605 if (sc == NULL) {
606 /* be quiet if there is not a single pppoe instance */
607 if (pppoe_softc_list != NULL) {
608 PPPDEBUG(LOG_DEBUG, ("pppoe: received PADO but could not find request for it\n"));
609 }
610 goto done;
611 }
612 if (sc->sc_state != PPPOE_STATE_PADI_SENT) {
613 PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": received unexpected PADO\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num));
614 goto done;
615 }
616 if (ac_cookie) {
617 sc->sc_ac_cookie_len = ac_cookie_len;
618 MEMCPY(sc->sc_ac_cookie, ac_cookie, ac_cookie_len);
619 }
620 MEMCPY(&sc->sc_dest, ethhdr->src.addr, sizeof(sc->sc_dest.addr));
621 sys_untimeout(pppoe_timeout, sc);
622 sc->sc_padr_retried = 0;
623 sc->sc_state = PPPOE_STATE_PADR_SENT;
624 if ((err = pppoe_send_padr(sc)) != 0) {
625 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));
626 LWIP_UNUSED_ARG(err); /* if PPPDEBUG is disabled */
627 }
628 sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc);
629 break;
630 case PPPOE_CODE_PADS:
631 if (sc == NULL) {
632 goto done;
633 }
634 sc->sc_session = session;
635 sys_untimeout(pppoe_timeout, sc);
636 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));
637 sc->sc_state = PPPOE_STATE_SESSION;
638 ppp_start(sc->pcb); /* notify upper layers */
639 break;
640 case PPPOE_CODE_PADT:
641 /* Don't disconnect here, we let the LCP Echo/Reply find the fact
642 * that PPP session is down. Asking the PPP stack to end the session
643 * require strict checking about the PPP phase to prevent endless
644 * disconnection loops.
645 */
646#if 0 /* UNUSED */
647 if (sc == NULL) { /* PADT frames are rarely sent with a hunique tag, this is actually almost always true */
648 goto done;
649 }
650 pppoe_clear_softc(sc, "received PADT");
651#endif /* UNUSED */
652 break;
653 default:
654 if(sc) {
655 PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": unknown code (0x%"X16_F") session = 0x%"X16_F"\n",
656 sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num,
657 (u16_t)ph->code, session));
658 } else {
659 PPPDEBUG(LOG_DEBUG, ("pppoe: unknown code (0x%"X16_F") session = 0x%"X16_F"\n", (u16_t)ph->code, session));
660 }
661 break;
662 }
663
664done:
665 pbuf_free(pb);
666 return;
667}
668
669void
670pppoe_data_input(struct netif *netif, struct pbuf *pb)
671{
672 u16_t session, plen;
673 struct pppoe_softc *sc;
674 struct pppoehdr *ph;
675#ifdef PPPOE_TERM_UNKNOWN_SESSIONS
676 u8_t shost[ETHER_ADDR_LEN];
677#endif
678
679#ifdef PPPOE_TERM_UNKNOWN_SESSIONS
680 MEMCPY(shost, ((struct eth_hdr *)pb->payload)->src.addr, sizeof(shost));
681#endif
682 if (pbuf_remove_header(pb, sizeof(struct eth_hdr)) != 0) {
683 /* bail out */
684 PPPDEBUG(LOG_ERR, ("pppoe_data_input: pbuf_remove_header failed\n"));
685 LINK_STATS_INC(link.lenerr);
686 goto drop;
687 }
688
689 if (pb->len < sizeof(*ph)) {
690 PPPDEBUG(LOG_DEBUG, ("pppoe_data_input: could not get PPPoE header\n"));
691 goto drop;
692 }
693 ph = (struct pppoehdr *)pb->payload;
694
695 if (ph->vertype != PPPOE_VERTYPE) {
696 PPPDEBUG(LOG_DEBUG, ("pppoe (data): unknown version/type packet: 0x%x\n", ph->vertype));
697 goto drop;
698 }
699 if (ph->code != 0) {
700 goto drop;
701 }
702
703 session = lwip_ntohs(ph->session);
704 sc = pppoe_find_softc_by_session(session, netif);
705 if (sc == NULL) {
706#ifdef PPPOE_TERM_UNKNOWN_SESSIONS
707 PPPDEBUG(LOG_DEBUG, ("pppoe: input for unknown session 0x%x, sending PADT\n", session));
708 pppoe_send_padt(netif, session, shost);
709#endif
710 goto drop;
711 }
712
713 plen = lwip_ntohs(ph->plen);
714
715 if (pbuf_remove_header(pb, PPPOE_HEADERLEN) != 0) {
716 /* bail out */
717 PPPDEBUG(LOG_ERR, ("pppoe_data_input: pbuf_remove_header PPPOE_HEADERLEN failed\n"));
718 LINK_STATS_INC(link.lenerr);
719 goto drop;
720 }
721
722 PPPDEBUG(LOG_DEBUG, ("pppoe_data_input: %c%c%"U16_F": pkthdr.len=%d, pppoe.len=%d\n",
723 sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num,
724 pb->len, plen));
725
726 if (pb->tot_len < plen) {
727 goto drop;
728 }
729
730 /* Dispatch the packet thereby consuming it. */
731 ppp_input(sc->pcb, pb);
732 return;
733
734drop:
735 pbuf_free(pb);
736}
737
738static err_t
739pppoe_output(struct pppoe_softc *sc, struct pbuf *pb)
740{
741 struct eth_hdr *ethhdr;
742 u16_t etype;
743 err_t res;
744
745 /* make room for Ethernet header - should not fail */
746 if (pbuf_add_header(pb, sizeof(struct eth_hdr)) != 0) {
747 /* bail out */
748 PPPDEBUG(LOG_ERR, ("pppoe: %c%c%"U16_F": pppoe_output: could not allocate room for Ethernet header\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num));
749 LINK_STATS_INC(link.lenerr);
750 pbuf_free(pb);
751 return ERR_BUF;
752 }
753 ethhdr = (struct eth_hdr *)pb->payload;
754 etype = sc->sc_state == PPPOE_STATE_SESSION ? ETHTYPE_PPPOE : ETHTYPE_PPPOEDISC;
755 ethhdr->type = lwip_htons(etype);
756 MEMCPY(&ethhdr->dest.addr, &sc->sc_dest.addr, sizeof(ethhdr->dest.addr));
757 MEMCPY(&ethhdr->src.addr, &sc->sc_ethif->hwaddr, sizeof(ethhdr->src.addr));
758
759 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",
760 sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, etype,
761 sc->sc_state, sc->sc_session,
762 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],
763 pb->tot_len));
764
765 res = sc->sc_ethif->linkoutput(sc->sc_ethif, pb);
766
767 pbuf_free(pb);
768
769 return res;
770}
771
772static err_t
773pppoe_send_padi(struct pppoe_softc *sc)
774{
775 struct pbuf *pb;
776 u8_t *p;
777 size_t len;
778#if PPPOE_SCNAME_SUPPORT
779 size_t l1 = 0, l2 = 0; /* XXX: gcc */
780#endif /* PPPOE_SCNAME_SUPPORT */
781
782 /* calculate length of frame (excluding ethernet header + pppoe header) */
783 len = 2 + 2 + 2 + 2 + sizeof sc; /* service name tag is required, host unique is send too */
784#if PPPOE_SCNAME_SUPPORT
785 if (sc->sc_service_name != NULL) {
786 l1 = strlen(sc->sc_service_name);
787 len += l1;
788 }
789 if (sc->sc_concentrator_name != NULL) {
790 l2 = strlen(sc->sc_concentrator_name);
791 len += 2 + 2 + l2;
792 }
793#endif /* PPPOE_SCNAME_SUPPORT */
794 LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff",
795 sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff);
796
797 /* allocate a buffer */
798 pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN + len), PBUF_RAM);
799 if (!pb) {
800 return ERR_MEM;
801 }
802 LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len);
803
804 p = (u8_t*)pb->payload;
805 /* fill in pkt */
806 PPPOE_ADD_HEADER(p, PPPOE_CODE_PADI, 0, (u16_t)len);
807 PPPOE_ADD_16(p, PPPOE_TAG_SNAME);
808#if PPPOE_SCNAME_SUPPORT
809 if (sc->sc_service_name != NULL) {
810 PPPOE_ADD_16(p, l1);
811 MEMCPY(p, sc->sc_service_name, l1);
812 p += l1;
813 } else
814#endif /* PPPOE_SCNAME_SUPPORT */
815 {
816 PPPOE_ADD_16(p, 0);
817 }
818#if PPPOE_SCNAME_SUPPORT
819 if (sc->sc_concentrator_name != NULL) {
820 PPPOE_ADD_16(p, PPPOE_TAG_ACNAME);
821 PPPOE_ADD_16(p, l2);
822 MEMCPY(p, sc->sc_concentrator_name, l2);
823 p += l2;
824 }
825#endif /* PPPOE_SCNAME_SUPPORT */
826 PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE);
827 PPPOE_ADD_16(p, sizeof(sc));
828 MEMCPY(p, &sc, sizeof sc);
829
830 /* send pkt */
831 return pppoe_output(sc, pb);
832}
833
834static void
835pppoe_timeout(void *arg)
836{
837 u32_t retry_wait;
838 int err;
839 struct pppoe_softc *sc = (struct pppoe_softc*)arg;
840
841 PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": timeout\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num));
842
843 switch (sc->sc_state) {
844 case PPPOE_STATE_PADI_SENT:
845 /*
846 * We have two basic ways of retrying:
847 * - Quick retry mode: try a few times in short sequence
848 * - Slow retry mode: we already had a connection successfully
849 * established and will try infinitely (without user
850 * intervention)
851 * We only enter slow retry mode if IFF_LINK1 (aka autodial)
852 * is not set.
853 */
854 if (sc->sc_padi_retried < 0xff) {
855 sc->sc_padi_retried++;
856 }
857 if (!sc->pcb->settings.persist && sc->sc_padi_retried >= PPPOE_DISC_MAXPADI) {
858#if 0
859 if ((sc->sc_sppp.pp_if.if_flags & IFF_LINK1) == 0) {
860 /* slow retry mode */
861 retry_wait = PPPOE_SLOW_RETRY;
862 } else
863#endif
864 {
865 pppoe_abort_connect(sc);
866 return;
867 }
868 }
869 /* initialize for quick retry mode */
870 retry_wait = LWIP_MIN(PPPOE_DISC_TIMEOUT * sc->sc_padi_retried, PPPOE_SLOW_RETRY);
871 if ((err = pppoe_send_padi(sc)) != 0) {
872 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));
873 LWIP_UNUSED_ARG(err); /* if PPPDEBUG is disabled */
874 }
875 sys_timeout(retry_wait, pppoe_timeout, sc);
876 break;
877
878 case PPPOE_STATE_PADR_SENT:
879 sc->sc_padr_retried++;
880 if (sc->sc_padr_retried >= PPPOE_DISC_MAXPADR) {
881 MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest));
882 sc->sc_state = PPPOE_STATE_PADI_SENT;
883 sc->sc_padr_retried = 0;
884 if ((err = pppoe_send_padi(sc)) != 0) {
885 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));
886 LWIP_UNUSED_ARG(err); /* if PPPDEBUG is disabled */
887 }
888 sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padi_retried), pppoe_timeout, sc);
889 return;
890 }
891 if ((err = pppoe_send_padr(sc)) != 0) {
892 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));
893 LWIP_UNUSED_ARG(err); /* if PPPDEBUG is disabled */
894 }
895 sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc);
896 break;
897 default:
898 return; /* all done, work in peace */
899 }
900}
901
902/* Start a connection (i.e. initiate discovery phase) */
903static void
904pppoe_connect(ppp_pcb *ppp, void *ctx)
905{
906 err_t err;
907 struct pppoe_softc *sc = (struct pppoe_softc *)ctx;
908 lcp_options *lcp_wo;
909 lcp_options *lcp_ao;
910#if PPP_IPV4_SUPPORT && VJ_SUPPORT
911 ipcp_options *ipcp_wo;
912 ipcp_options *ipcp_ao;
913#endif /* PPP_IPV4_SUPPORT && VJ_SUPPORT */
914
915 sc->sc_session = 0;
916 sc->sc_ac_cookie_len = 0;
917 sc->sc_padi_retried = 0;
918 sc->sc_padr_retried = 0;
919 /* changed to real address later */
920 MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest));
921#ifdef PPPOE_SERVER
922 /* wait PADI if IFF_PASSIVE */
923 if ((sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) {
924 return 0;
925 }
926#endif
927
928 lcp_wo = &ppp->lcp_wantoptions;
929 lcp_wo->mru = sc->sc_ethif->mtu-PPPOE_HEADERLEN-2; /* two byte PPP protocol discriminator, then IP data */
930 lcp_wo->neg_asyncmap = 0;
931 lcp_wo->neg_pcompression = 0;
932 lcp_wo->neg_accompression = 0;
933 lcp_wo->passive = 0;
934 lcp_wo->silent = 0;
935
936 lcp_ao = &ppp->lcp_allowoptions;
937 lcp_ao->mru = sc->sc_ethif->mtu-PPPOE_HEADERLEN-2; /* two byte PPP protocol discriminator, then IP data */
938 lcp_ao->neg_asyncmap = 0;
939 lcp_ao->neg_pcompression = 0;
940 lcp_ao->neg_accompression = 0;
941
942#if PPP_IPV4_SUPPORT && VJ_SUPPORT
943 ipcp_wo = &ppp->ipcp_wantoptions;
944 ipcp_wo->neg_vj = 0;
945 ipcp_wo->old_vj = 0;
946
947 ipcp_ao = &ppp->ipcp_allowoptions;
948 ipcp_ao->neg_vj = 0;
949 ipcp_ao->old_vj = 0;
950#endif /* PPP_IPV4_SUPPORT && VJ_SUPPORT */
951
952 /* save state, in case we fail to send PADI */
953 sc->sc_state = PPPOE_STATE_PADI_SENT;
954 if ((err = pppoe_send_padi(sc)) != 0) {
955 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));
956 }
957 sys_timeout(PPPOE_DISC_TIMEOUT, pppoe_timeout, sc);
958}
959
960/* disconnect */
961static void
962pppoe_disconnect(ppp_pcb *ppp, void *ctx)
963{
964 struct pppoe_softc *sc = (struct pppoe_softc *)ctx;
965
966 PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": disconnecting\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num));
967 if (sc->sc_state == PPPOE_STATE_SESSION) {
968 pppoe_send_padt(sc->sc_ethif, sc->sc_session, (const u8_t *)&sc->sc_dest);
969 }
970
971 /* stop any timer, disconnect can be called while initiating is in progress */
972 sys_untimeout(pppoe_timeout, sc);
973 sc->sc_state = PPPOE_STATE_INITIAL;
974#ifdef PPPOE_SERVER
975 if (sc->sc_hunique) {
976 mem_free(sc->sc_hunique);
977 sc->sc_hunique = NULL; /* probably not necessary, if state is initial we shouldn't have to access hunique anyway */
978 }
979 sc->sc_hunique_len = 0; /* probably not necessary, if state is initial we shouldn't have to access hunique anyway */
980#endif
981 ppp_link_end(ppp); /* notify upper layers */
982 return;
983}
984
985/* Connection attempt aborted */
986static void
987pppoe_abort_connect(struct pppoe_softc *sc)
988{
989 PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": could not establish connection\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num));
990 sc->sc_state = PPPOE_STATE_INITIAL;
991 ppp_link_failed(sc->pcb); /* notify upper layers */
992}
993
994/* Send a PADR packet */
995static err_t
996pppoe_send_padr(struct pppoe_softc *sc)
997{
998 struct pbuf *pb;
999 u8_t *p;
1000 size_t len;
1001#if PPPOE_SCNAME_SUPPORT
1002 size_t l1 = 0; /* XXX: gcc */
1003#endif /* PPPOE_SCNAME_SUPPORT */
1004
1005 len = 2 + 2 + 2 + 2 + sizeof(sc); /* service name, host unique */
1006#if PPPOE_SCNAME_SUPPORT
1007 if (sc->sc_service_name != NULL) { /* service name tag maybe empty */
1008 l1 = strlen(sc->sc_service_name);
1009 len += l1;
1010 }
1011#endif /* PPPOE_SCNAME_SUPPORT */
1012 if (sc->sc_ac_cookie_len > 0) {
1013 len += 2 + 2 + sc->sc_ac_cookie_len; /* AC cookie */
1014 }
1015 LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff",
1016 sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff);
1017 pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN + len), PBUF_RAM);
1018 if (!pb) {
1019 return ERR_MEM;
1020 }
1021 LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len);
1022 p = (u8_t*)pb->payload;
1023 PPPOE_ADD_HEADER(p, PPPOE_CODE_PADR, 0, len);
1024 PPPOE_ADD_16(p, PPPOE_TAG_SNAME);
1025#if PPPOE_SCNAME_SUPPORT
1026 if (sc->sc_service_name != NULL) {
1027 PPPOE_ADD_16(p, l1);
1028 MEMCPY(p, sc->sc_service_name, l1);
1029 p += l1;
1030 } else
1031#endif /* PPPOE_SCNAME_SUPPORT */
1032 {
1033 PPPOE_ADD_16(p, 0);
1034 }
1035 if (sc->sc_ac_cookie_len > 0) {
1036 PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE);
1037 PPPOE_ADD_16(p, sc->sc_ac_cookie_len);
1038 MEMCPY(p, sc->sc_ac_cookie, sc->sc_ac_cookie_len);
1039 p += sc->sc_ac_cookie_len;
1040 }
1041 PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE);
1042 PPPOE_ADD_16(p, sizeof(sc));
1043 MEMCPY(p, &sc, sizeof sc);
1044
1045 return pppoe_output(sc, pb);
1046}
1047
1048/* send a PADT packet */
1049static err_t
1050pppoe_send_padt(struct netif *outgoing_if, u_int session, const u8_t *dest)
1051{
1052 struct pbuf *pb;
1053 struct eth_hdr *ethhdr;
1054 err_t res;
1055 u8_t *p;
1056
1057 pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN), PBUF_RAM);
1058 if (!pb) {
1059 return ERR_MEM;
1060 }
1061 LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len);
1062
1063 if (pbuf_add_header(pb, sizeof(struct eth_hdr))) {
1064 PPPDEBUG(LOG_ERR, ("pppoe: pppoe_send_padt: could not allocate room for PPPoE header\n"));
1065 LINK_STATS_INC(link.lenerr);
1066 pbuf_free(pb);
1067 return ERR_BUF;
1068 }
1069 ethhdr = (struct eth_hdr *)pb->payload;
1070 ethhdr->type = PP_HTONS(ETHTYPE_PPPOEDISC);
1071 MEMCPY(&ethhdr->dest.addr, dest, sizeof(ethhdr->dest.addr));
1072 MEMCPY(&ethhdr->src.addr, &outgoing_if->hwaddr, sizeof(ethhdr->src.addr));
1073
1074 p = (u8_t*)(ethhdr + 1);
1075 PPPOE_ADD_HEADER(p, PPPOE_CODE_PADT, session, 0);
1076
1077 res = outgoing_if->linkoutput(outgoing_if, pb);
1078
1079 pbuf_free(pb);
1080
1081 return res;
1082}
1083
1084#ifdef PPPOE_SERVER
1085static err_t
1086pppoe_send_pado(struct pppoe_softc *sc)
1087{
1088 struct pbuf *pb;
1089 u8_t *p;
1090 size_t len;
1091
1092 /* calc length */
1093 len = 0;
1094 /* include ac_cookie */
1095 len += 2 + 2 + sizeof(sc);
1096 /* include hunique */
1097 len += 2 + 2 + sc->sc_hunique_len;
1098 pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN + len), PBUF_RAM);
1099 if (!pb) {
1100 return ERR_MEM;
1101 }
1102 LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len);
1103 p = (u8_t*)pb->payload;
1104 PPPOE_ADD_HEADER(p, PPPOE_CODE_PADO, 0, len);
1105 PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE);
1106 PPPOE_ADD_16(p, sizeof(sc));
1107 MEMCPY(p, &sc, sizeof(sc));
1108 p += sizeof(sc);
1109 PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE);
1110 PPPOE_ADD_16(p, sc->sc_hunique_len);
1111 MEMCPY(p, sc->sc_hunique, sc->sc_hunique_len);
1112 return pppoe_output(sc, pb);
1113}
1114
1115static err_t
1116pppoe_send_pads(struct pppoe_softc *sc)
1117{
1118 struct pbuf *pb;
1119 u8_t *p;
1120 size_t len, l1 = 0; /* XXX: gcc */
1121
1122 sc->sc_session = mono_time.tv_sec % 0xff + 1;
1123 /* calc length */
1124 len = 0;
1125 /* include hunique */
1126 len += 2 + 2 + 2 + 2 + sc->sc_hunique_len; /* service name, host unique*/
1127 if (sc->sc_service_name != NULL) { /* service name tag maybe empty */
1128 l1 = strlen(sc->sc_service_name);
1129 len += l1;
1130 }
1131 pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN + len), PBUF_RAM);
1132 if (!pb) {
1133 return ERR_MEM;
1134 }
1135 LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len);
1136 p = (u8_t*)pb->payload;
1137 PPPOE_ADD_HEADER(p, PPPOE_CODE_PADS, sc->sc_session, len);
1138 PPPOE_ADD_16(p, PPPOE_TAG_SNAME);
1139 if (sc->sc_service_name != NULL) {
1140 PPPOE_ADD_16(p, l1);
1141 MEMCPY(p, sc->sc_service_name, l1);
1142 p += l1;
1143 } else {
1144 PPPOE_ADD_16(p, 0);
1145 }
1146 PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE);
1147 PPPOE_ADD_16(p, sc->sc_hunique_len);
1148 MEMCPY(p, sc->sc_hunique, sc->sc_hunique_len);
1149 return pppoe_output(sc, pb);
1150}
1151#endif
1152
1153static err_t
1154pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb)
1155{
1156 u8_t *p;
1157 size_t len;
1158
1159 len = pb->tot_len;
1160
1161 /* make room for PPPoE header - should not fail */
1162 if (pbuf_add_header(pb, PPPOE_HEADERLEN) != 0) {
1163 /* bail out */
1164 PPPDEBUG(LOG_ERR, ("pppoe: %c%c%"U16_F": pppoe_xmit: could not allocate room for PPPoE header\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num));
1165 LINK_STATS_INC(link.lenerr);
1166 pbuf_free(pb);
1167 return ERR_BUF;
1168 }
1169
1170 p = (u8_t*)pb->payload;
1171 PPPOE_ADD_HEADER(p, 0, sc->sc_session, len);
1172
1173 return pppoe_output(sc, pb);
1174}
1175
1176#if 0 /*def PFIL_HOOKS*/
1177static int
1178pppoe_ifattach_hook(void *arg, struct pbuf **mp, struct netif *ifp, int dir)
1179{
1180 struct pppoe_softc *sc;
1181 int s;
1182
1183 if (mp != (struct pbuf **)PFIL_IFNET_DETACH) {
1184 return 0;
1185 }
1186
1187 LIST_FOREACH(sc, &pppoe_softc_list, sc_list) {
1188 if (sc->sc_ethif != ifp) {
1189 continue;
1190 }
1191 if (sc->sc_sppp.pp_if.if_flags & IFF_UP) {
1192 sc->sc_sppp.pp_if.if_flags &= ~(IFF_UP|IFF_RUNNING);
1193 PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": ethernet interface detached, going down\n",
1194 sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num));
1195 }
1196 sc->sc_ethif = NULL;
1197 pppoe_clear_softc(sc, "ethernet interface detached");
1198 }
1199
1200 return 0;
1201}
1202#endif
1203
1204#if 0 /* UNUSED */
1205static void
1206pppoe_clear_softc(struct pppoe_softc *sc, const char *message)
1207{
1209
1210 /* stop timer */
1211 sys_untimeout(pppoe_timeout, sc);
1212 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));
1213 sc->sc_state = PPPOE_STATE_INITIAL;
1214 ppp_link_end(sc->pcb); /* notify upper layers - /!\ dangerous /!\ - see pppoe_disc_input() */
1215}
1216#endif /* UNUSED */
1217#endif /* PPP_SUPPORT && PPPOE_SUPPORT */
static char service_name[100]
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
unsigned int dir
Definition: maze.c:112
r l[0]
Definition: byte_order.h:168
static VOID freep(LPSTR *p)
Definition: cmdcons.c:98
const WCHAR * link
Definition: db.cpp:997
#define PP_HTONS(x)
Definition: def.h:90
#define lwip_htons(x)
Definition: def.h:86
#define LWIP_MIN(x, y)
Definition: def.h:66
#define lwip_ntohs(x)
Definition: def.h:87
#define ETHER_ADDR_LEN
Definition: dhcpd.h:51
UINT32 u_int
Definition: types.h:82
#define mem_free(ptr, bsize)
Definition: types.h:124
#define NULL
Definition: types.h:112
unsigned short u_short
Definition: types.h:81
#define pt(x, y)
Definition: drawing.c:79
#define X16_F
Definition: cc.h:21
#define U16_F
Definition: cc.h:19
void * mem_malloc(mem_size_t size_in)
Definition: mem.c:831
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:116
#define MIB2_STATS_NETIF_ADD(n, x, val)
Definition: snmp.h:140
#define MIB2_STATS_NETIF_INC(n, x)
Definition: snmp.h:139
#define ERR_MEM
Definition: fontsub.h:52
GLdouble s
Definition: gl.h:2039
GLdouble GLdouble t
Definition: gl.h:2047
GLuint res
Definition: glext.h:9613
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat token
Definition: glfuncs.h:210
uint32_t u32_t
Definition: arch.h:129
uint8_t u8_t
Definition: arch.h:125
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:373
uint16_t u16_t
Definition: arch.h:127
@ ETHTYPE_PPPOEDISC
Definition: ieee.h:66
@ ETHTYPE_PPPOE
Definition: ieee.h:68
s8_t err_t
Definition: err.h:96
@ ERR_BUF
Definition: err.h:59
@ ERR_OK
Definition: err.h:55
#define LWIP_ASSERT_CORE_LOCKED()
Definition: opt.h:227
#define LWIP_MEMPOOL_DECLARE(name, num, size, desc)
Definition: memp.h:95
#define LWIP_MEMPOOL_ALLOC(name)
Definition: memp.h:122
#define LWIP_MEMPOOL_FREE(name, x)
Definition: memp.h:127
struct pbuf * pbuf_coalesce(struct pbuf *p, pbuf_layer layer)
Definition: pbuf.c:1309
void pbuf_cat(struct pbuf *h, struct pbuf *t)
Definition: pbuf.c:855
void pbuf_chain(struct pbuf *h, struct pbuf *t)
Definition: pbuf.c:897
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
Definition: pbuf.c:224
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:727
@ PBUF_RAM
Definition: pbuf.h:152
@ PBUF_RAW
Definition: pbuf.h:111
@ PBUF_LINK
Definition: pbuf.h:102
if(dx< 0)
Definition: linetemp.h:194
#define MEMCPY(DST, SRC, BYTES)
Definition: macros.h:231
static char * dest
Definition: rtl.c:135
u8_t pbuf_add_header(struct pbuf *p, size_t header_size_increment)
Definition: pbuf.c:554
u8_t pbuf_remove_header(struct pbuf *p, size_t header_size_decrement)
Definition: pbuf.c:585
#define err(...)
strncpy
Definition: string.h:335
#define memset(x, y, z)
Definition: compat.h:39
#define LINK_STATS_INC(x)
Definition: stats.h:384
struct define * next
Definition: compiler.c:65
char * name
Definition: compiler.c:66
Definition: tftpd.h:60
Definition: netif.h:269
u8_t hwaddr[NETIF_MAX_HWADDR_LEN]
Definition: netif.h:350
netif_linkoutput_fn linkoutput
Definition: netif.h:308
Definition: pbuf.h:186
u16_t tot_len
Definition: pbuf.h:200
struct pbuf * next
Definition: pbuf.h:188
u16_t len
Definition: pbuf.h:203
void * payload
Definition: pbuf.h:191
Definition: ecma_167.h:138
#define LIST_FOREACH(var, head, field)
Definition: queue.h:189
#define LIST_EMPTY(head)
Definition: queue.h:186
#define LOG_DEBUG
Definition: syslog.h:52
#define LOG_ERR
Definition: syslog.h:48
int ret
#define IFF_UP
Definition: ws2ipdef.h:21