uc-sdk
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ppp_oe.c
Go to the documentation of this file.
1 /*****************************************************************************
2 * ppp_oe.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 "lwip/opt.h"
72 
73 #if PPPOE_SUPPORT /* don't build if not configured for use in lwipopts.h */
74 
75 #include "netif/ppp_oe.h"
76 
77 #include "ppp.h"
78 #include "pppdebug.h"
79 
80 #include "lwip/timers.h"
81 #include "lwip/memp.h"
82 
83 #include <string.h>
84 #include <stdio.h>
85 
86 
87 /* Add a 16 bit unsigned value to a buffer pointed to by PTR */
88 #define PPPOE_ADD_16(PTR, VAL) \
89  *(PTR)++ = (u8_t)((VAL) / 256); \
90  *(PTR)++ = (u8_t)((VAL) % 256)
91 
92 /* Add a complete PPPoE header to the buffer pointed to by PTR */
93 #define PPPOE_ADD_HEADER(PTR, CODE, SESS, LEN) \
94  *(PTR)++ = PPPOE_VERTYPE; \
95  *(PTR)++ = (CODE); \
96  PPPOE_ADD_16(PTR, SESS); \
97  PPPOE_ADD_16(PTR, LEN)
98 
99 #define PPPOE_DISC_TIMEOUT (5*1000) /* base for quick timeout calculation */
100 #define PPPOE_SLOW_RETRY (60*1000) /* persistent retry interval */
101 #define PPPOE_DISC_MAXPADI 4 /* retry PADI four times (quickly) */
102 #define PPPOE_DISC_MAXPADR 2 /* retry PADR twice */
103 
104 #ifdef PPPOE_SERVER
105 #error "PPPOE_SERVER is not yet supported under lwIP!"
106 /* from if_spppsubr.c */
107 #define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */
108 #endif
109 
110 #ifndef PPPOE_ERRORSTRING_LEN
111 #define PPPOE_ERRORSTRING_LEN 64
112 #endif
113 static char pppoe_error_tmp[PPPOE_ERRORSTRING_LEN];
114 
115 
116 /* input routines */
117 static void pppoe_dispatch_disc_pkt(struct netif *, struct pbuf *);
118 
119 /* management routines */
120 static int pppoe_do_disconnect(struct pppoe_softc *);
121 static void pppoe_abort_connect(struct pppoe_softc *);
122 static void pppoe_clear_softc(struct pppoe_softc *, const char *);
123 
124 /* internal timeout handling */
125 static void pppoe_timeout(void *);
126 
127 /* sending actual protocol controll packets */
128 static err_t pppoe_send_padi(struct pppoe_softc *);
129 static err_t pppoe_send_padr(struct pppoe_softc *);
130 #ifdef PPPOE_SERVER
131 static err_t pppoe_send_pado(struct pppoe_softc *);
132 static err_t pppoe_send_pads(struct pppoe_softc *);
133 #endif
134 static err_t pppoe_send_padt(struct netif *, u_int, const u8_t *);
135 
136 /* internal helper functions */
137 static struct pppoe_softc * pppoe_find_softc_by_session(u_int, struct netif *);
138 static struct pppoe_softc * pppoe_find_softc_by_hunique(u8_t *, size_t, struct netif *);
139 
141 static struct pppoe_softc *pppoe_softc_list;
142 
143 err_t
144 pppoe_create(struct netif *ethif, int pd, void (*linkStatusCB)(int pd, int up), struct pppoe_softc **scptr)
145 {
146  struct pppoe_softc *sc;
147 
148  sc = (struct pppoe_softc *)memp_malloc(MEMP_PPPOE_IF);
149  if (sc == NULL) {
150  *scptr = NULL;
151  return ERR_MEM;
152  }
153  memset(sc, 0, sizeof(struct pppoe_softc));
154 
155  /* changed to real address later */
156  MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest));
157 
158  sc->sc_pd = pd;
159  sc->sc_linkStatusCB = linkStatusCB;
160  sc->sc_ethif = ethif;
161 
162  /* put the new interface at the head of the list */
163  sc->next = pppoe_softc_list;
164  pppoe_softc_list = sc;
165 
166  *scptr = sc;
167 
168  return ERR_OK;
169 }
170 
171 err_t
172 pppoe_destroy(struct netif *ifp)
173 {
174  struct pppoe_softc *sc, *prev = NULL;
175 
176  for (sc = pppoe_softc_list; sc != NULL; prev = sc, sc = sc->next) {
177  if (sc->sc_ethif == ifp) {
178  break;
179  }
180  }
181 
182  if(!(sc && (sc->sc_ethif == ifp))) {
183  return ERR_IF;
184  }
185 
186  sys_untimeout(pppoe_timeout, sc);
187  if (prev == NULL) {
188  /* remove sc from the head of the list */
189  pppoe_softc_list = sc->next;
190  } else {
191  /* remove sc from the list */
192  prev->next = sc->next;
193  }
194 
195 #ifdef PPPOE_TODO
196  if (sc->sc_concentrator_name) {
197  mem_free(sc->sc_concentrator_name);
198  }
199  if (sc->sc_service_name) {
200  mem_free(sc->sc_service_name);
201  }
202 #endif /* PPPOE_TODO */
203  memp_free(MEMP_PPPOE_IF, sc);
204 
205  return ERR_OK;
206 }
207 
208 /*
209  * Find the interface handling the specified session.
210  * Note: O(number of sessions open), this is a client-side only, mean
211  * and lean implementation, so number of open sessions typically should
212  * be 1.
213  */
214 static struct pppoe_softc *
215 pppoe_find_softc_by_session(u_int session, struct netif *rcvif)
216 {
217  struct pppoe_softc *sc;
218 
219  if (session == 0) {
220  return NULL;
221  }
222 
223  for (sc = pppoe_softc_list; sc != NULL; sc = sc->next) {
224  if (sc->sc_state == PPPOE_STATE_SESSION
225  && sc->sc_session == session) {
226  if (sc->sc_ethif == rcvif) {
227  return sc;
228  } else {
229  return NULL;
230  }
231  }
232  }
233  return NULL;
234 }
235 
236 /* Check host unique token passed and return appropriate softc pointer,
237  * or NULL if token is bogus. */
238 static struct pppoe_softc *
239 pppoe_find_softc_by_hunique(u8_t *token, size_t len, struct netif *rcvif)
240 {
241  struct pppoe_softc *sc, *t;
242 
243  if (pppoe_softc_list == NULL) {
244  return NULL;
245  }
246 
247  if (len != sizeof sc) {
248  return NULL;
249  }
250  MEMCPY(&t, token, len);
251 
252  for (sc = pppoe_softc_list; sc != NULL; sc = sc->next) {
253  if (sc == t) {
254  break;
255  }
256  }
257 
258  if (sc == NULL) {
259  PPPDEBUG(LOG_DEBUG, ("pppoe: alien host unique tag, no session found\n"));
260  return NULL;
261  }
262 
263  /* should be safe to access *sc now */
264  if (sc->sc_state < PPPOE_STATE_PADI_SENT || sc->sc_state >= PPPOE_STATE_SESSION) {
265  printf("%c%c%"U16_F": host unique tag found, but it belongs to a connection in state %d\n",
266  sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_state);
267  return NULL;
268  }
269  if (sc->sc_ethif != rcvif) {
270  printf("%c%c%"U16_F": wrong interface, not accepting host unique\n",
271  sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num);
272  return NULL;
273  }
274  return sc;
275 }
276 
277 static void
278 pppoe_linkstatus_up(struct pppoe_softc *sc)
279 {
280  sc->sc_linkStatusCB(sc->sc_pd, 1);
281 }
282 
283 /* analyze and handle a single received packet while not in session state */
284 static void
285 pppoe_dispatch_disc_pkt(struct netif *netif, struct pbuf *pb)
286 {
287  u16_t tag, len;
288  u16_t session, plen;
289  struct pppoe_softc *sc;
290  const char *err_msg;
291  char devname[6];
292  u8_t *ac_cookie;
293  u16_t ac_cookie_len;
294 #ifdef PPPOE_SERVER
295  u8_t *hunique;
296  size_t hunique_len;
297 #endif
298  struct pppoehdr *ph;
299  struct pppoetag pt;
300  int off, err, errortag;
301  struct eth_hdr *ethhdr;
302 
303  pb = pppSingleBuf(pb);
304 
305  strcpy(devname, "pppoe"); /* as long as we don't know which instance */
306  err_msg = NULL;
307  errortag = 0;
308  if (pb->len < sizeof(*ethhdr)) {
309  goto done;
310  }
311  ethhdr = (struct eth_hdr *)pb->payload;
312  off = sizeof(*ethhdr);
313 
314  ac_cookie = NULL;
315  ac_cookie_len = 0;
316 #ifdef PPPOE_SERVER
317  hunique = NULL;
318  hunique_len = 0;
319 #endif
320  session = 0;
321  if (pb->len - off < PPPOE_HEADERLEN) {
322  printf("pppoe: packet too short: %d\n", pb->len);
323  goto done;
324  }
325 
326  ph = (struct pppoehdr *) (ethhdr + 1);
327  if (ph->vertype != PPPOE_VERTYPE) {
328  printf("pppoe: unknown version/type packet: 0x%x\n", ph->vertype);
329  goto done;
330  }
331  session = ntohs(ph->session);
332  plen = ntohs(ph->plen);
333  off += sizeof(*ph);
334 
335  if (plen + off > pb->len) {
336  printf("pppoe: packet content does not fit: data available = %d, packet size = %u\n",
337  pb->len - off, plen);
338  goto done;
339  }
340  if(pb->tot_len == pb->len) {
341  pb->tot_len = pb->len = (u16_t)off + plen; /* ignore trailing garbage */
342  }
343  tag = 0;
344  len = 0;
345  sc = NULL;
346  while (off + sizeof(pt) <= pb->len) {
347  MEMCPY(&pt, (u8_t*)pb->payload + off, sizeof(pt));
348  tag = ntohs(pt.tag);
349  len = ntohs(pt.len);
350  if (off + sizeof(pt) + len > pb->len) {
351  printf("pppoe: tag 0x%x len 0x%x is too long\n", tag, len);
352  goto done;
353  }
354  switch (tag) {
355  case PPPOE_TAG_EOL:
356  goto breakbreak;
357  case PPPOE_TAG_SNAME:
358  break; /* ignored */
359  case PPPOE_TAG_ACNAME:
360  break; /* ignored */
361  case PPPOE_TAG_HUNIQUE:
362  if (sc != NULL) {
363  break;
364  }
365 #ifdef PPPOE_SERVER
366  hunique = (u8_t*)pb->payload + off + sizeof(pt);
367  hunique_len = len;
368 #endif
369  sc = pppoe_find_softc_by_hunique((u8_t*)pb->payload + off + sizeof(pt), len, netif);
370  if (sc != NULL) {
371  snprintf(devname, sizeof(devname), "%c%c%"U16_F, sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num);
372  }
373  break;
374  case PPPOE_TAG_ACCOOKIE:
375  if (ac_cookie == NULL) {
376  ac_cookie = (u8_t*)pb->payload + off + sizeof(pt);
377  ac_cookie_len = len;
378  }
379  break;
380  case PPPOE_TAG_SNAME_ERR:
381  err_msg = "SERVICE NAME ERROR";
382  errortag = 1;
383  break;
384  case PPPOE_TAG_ACSYS_ERR:
385  err_msg = "AC SYSTEM ERROR";
386  errortag = 1;
387  break;
388  case PPPOE_TAG_GENERIC_ERR:
389  err_msg = "GENERIC ERROR";
390  errortag = 1;
391  break;
392  }
393  if (err_msg) {
394  if (errortag && len) {
395  u16_t error_len = LWIP_MIN(len, sizeof(pppoe_error_tmp)-1);
396  strncpy(pppoe_error_tmp, (char*)pb->payload + off + sizeof(pt), error_len);
397  pppoe_error_tmp[error_len-1] = '\0';
398  printf("%s: %s: %s\n", devname, err_msg, pppoe_error_tmp);
399  } else {
400  printf("%s: %s\n", devname, err_msg);
401  }
402  if (errortag) {
403  goto done;
404  }
405  }
406  off += sizeof(pt) + len;
407  }
408 
409 breakbreak:;
410  switch (ph->code) {
411  case PPPOE_CODE_PADI:
412 #ifdef PPPOE_SERVER
413  /*
414  * got service name, concentrator name, and/or host unique.
415  * ignore if we have no interfaces with IFF_PASSIVE|IFF_UP.
416  */
417  if (LIST_EMPTY(&pppoe_softc_list)) {
418  goto done;
419  }
420  LIST_FOREACH(sc, &pppoe_softc_list, sc_list) {
421  if (!(sc->sc_sppp.pp_if.if_flags & IFF_UP)) {
422  continue;
423  }
424  if (!(sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) {
425  continue;
426  }
427  if (sc->sc_state == PPPOE_STATE_INITIAL) {
428  break;
429  }
430  }
431  if (sc == NULL) {
432  /* printf("pppoe: free passive interface is not found\n"); */
433  goto done;
434  }
435  if (hunique) {
436  if (sc->sc_hunique) {
437  mem_free(sc->sc_hunique);
438  }
439  sc->sc_hunique = mem_malloc(hunique_len);
440  if (sc->sc_hunique == NULL) {
441  goto done;
442  }
443  sc->sc_hunique_len = hunique_len;
444  MEMCPY(sc->sc_hunique, hunique, hunique_len);
445  }
446  MEMCPY(&sc->sc_dest, eh->ether_shost, sizeof sc->sc_dest);
447  sc->sc_state = PPPOE_STATE_PADO_SENT;
448  pppoe_send_pado(sc);
449  break;
450 #endif /* PPPOE_SERVER */
451  case PPPOE_CODE_PADR:
452 #ifdef PPPOE_SERVER
453  /*
454  * get sc from ac_cookie if IFF_PASSIVE
455  */
456  if (ac_cookie == NULL) {
457  /* be quiet if there is not a single pppoe instance */
458  printf("pppoe: received PADR but not includes ac_cookie\n");
459  goto done;
460  }
461  sc = pppoe_find_softc_by_hunique(ac_cookie, ac_cookie_len, netif);
462  if (sc == NULL) {
463  /* be quiet if there is not a single pppoe instance */
464  if (!LIST_EMPTY(&pppoe_softc_list)) {
465  printf("pppoe: received PADR but could not find request for it\n");
466  }
467  goto done;
468  }
469  if (sc->sc_state != PPPOE_STATE_PADO_SENT) {
470  printf("%c%c%"U16_F": received unexpected PADR\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num);
471  goto done;
472  }
473  if (hunique) {
474  if (sc->sc_hunique) {
475  mem_free(sc->sc_hunique);
476  }
477  sc->sc_hunique = mem_malloc(hunique_len);
478  if (sc->sc_hunique == NULL) {
479  goto done;
480  }
481  sc->sc_hunique_len = hunique_len;
482  MEMCPY(sc->sc_hunique, hunique, hunique_len);
483  }
484  pppoe_send_pads(sc);
485  sc->sc_state = PPPOE_STATE_SESSION;
486  pppoe_linkstatus_up(sc); /* notify upper layers */
487  break;
488 #else
489  /* ignore, we are no access concentrator */
490  goto done;
491 #endif /* PPPOE_SERVER */
492  case PPPOE_CODE_PADO:
493  if (sc == NULL) {
494  /* be quiet if there is not a single pppoe instance */
495  if (pppoe_softc_list != NULL) {
496  printf("pppoe: received PADO but could not find request for it\n");
497  }
498  goto done;
499  }
500  if (sc->sc_state != PPPOE_STATE_PADI_SENT) {
501  printf("%c%c%"U16_F": received unexpected PADO\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num);
502  goto done;
503  }
504  if (ac_cookie) {
505  sc->sc_ac_cookie_len = ac_cookie_len;
506  MEMCPY(sc->sc_ac_cookie, ac_cookie, ac_cookie_len);
507  }
508  MEMCPY(&sc->sc_dest, ethhdr->src.addr, sizeof(sc->sc_dest.addr));
509  sys_untimeout(pppoe_timeout, sc);
510  sc->sc_padr_retried = 0;
511  sc->sc_state = PPPOE_STATE_PADR_SENT;
512  if ((err = pppoe_send_padr(sc)) != 0) {
513  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));
514  }
515  sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc);
516  break;
517  case PPPOE_CODE_PADS:
518  if (sc == NULL) {
519  goto done;
520  }
521  sc->sc_session = session;
522  sys_untimeout(pppoe_timeout, sc);
523  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));
524  sc->sc_state = PPPOE_STATE_SESSION;
525  pppoe_linkstatus_up(sc); /* notify upper layers */
526  break;
527  case PPPOE_CODE_PADT:
528  if (sc == NULL) {
529  goto done;
530  }
531  pppoe_clear_softc(sc, "received PADT");
532  break;
533  default:
534  if(sc) {
535  printf("%c%c%"U16_F": unknown code (0x%"X16_F") session = 0x%"X16_F"\n",
536  sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num,
537  (u16_t)ph->code, session);
538  } else {
539  printf("pppoe: unknown code (0x%"X16_F") session = 0x%"X16_F"\n", (u16_t)ph->code, session);
540  }
541  break;
542  }
543 
544 done:
545  pbuf_free(pb);
546  return;
547 }
548 
549 void
550 pppoe_disc_input(struct netif *netif, struct pbuf *p)
551 {
552  /* avoid error messages if there is not a single pppoe instance */
553  if (pppoe_softc_list != NULL) {
554  pppoe_dispatch_disc_pkt(netif, p);
555  } else {
556  pbuf_free(p);
557  }
558 }
559 
560 void
561 pppoe_data_input(struct netif *netif, struct pbuf *pb)
562 {
563  u16_t session, plen;
564  struct pppoe_softc *sc;
565  struct pppoehdr *ph;
566 #ifdef PPPOE_TERM_UNKNOWN_SESSIONS
567  u8_t shost[ETHER_ADDR_LEN];
568 #endif
569 
570 #ifdef PPPOE_TERM_UNKNOWN_SESSIONS
571  MEMCPY(shost, ((struct eth_hdr *)pb->payload)->src.addr, sizeof(shost));
572 #endif
573  if (pbuf_header(pb, -(int)sizeof(struct eth_hdr)) != 0) {
574  /* bail out */
575  PPPDEBUG(LOG_ERR, ("pppoe_data_input: pbuf_header failed\n"));
576  LINK_STATS_INC(link.lenerr);
577  goto drop;
578  }
579 
580  pb = pppSingleBuf (pb);
581 
582  if (pb->len <= PPPOE_HEADERLEN) {
583  printf("pppoe (data): dropping too short packet: %d bytes\n", pb->len);
584  goto drop;
585  }
586 
587  if (pb->len < sizeof(*ph)) {
588  printf("pppoe_data_input: could not get PPPoE header\n");
589  goto drop;
590  }
591  ph = (struct pppoehdr *)pb->payload;
592 
593  if (ph->vertype != PPPOE_VERTYPE) {
594  printf("pppoe (data): unknown version/type packet: 0x%x\n", ph->vertype);
595  goto drop;
596  }
597  if (ph->code != 0) {
598  goto drop;
599  }
600 
601  session = ntohs(ph->session);
602  sc = pppoe_find_softc_by_session(session, netif);
603  if (sc == NULL) {
604 #ifdef PPPOE_TERM_UNKNOWN_SESSIONS
605  printf("pppoe: input for unknown session 0x%x, sending PADT\n", session);
606  pppoe_send_padt(netif, session, shost);
607 #endif
608  goto drop;
609  }
610 
611  plen = ntohs(ph->plen);
612 
613  if (pbuf_header(pb, -(int)(PPPOE_HEADERLEN)) != 0) {
614  /* bail out */
615  PPPDEBUG(LOG_ERR, ("pppoe_data_input: pbuf_header PPPOE_HEADERLEN failed\n"));
616  LINK_STATS_INC(link.lenerr);
617  goto drop;
618  }
619 
620  PPPDEBUG(LOG_DEBUG, ("pppoe_data_input: %c%c%"U16_F": pkthdr.len=%d, pppoe.len=%d\n",
621  sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num,
622  pb->len, plen));
623 
624  if (pb->len < plen) {
625  goto drop;
626  }
627 
628  pppInProcOverEthernet(sc->sc_pd, pb);
629 
630  return;
631 
632 drop:
633  pbuf_free(pb);
634 }
635 
636 static err_t
637 pppoe_output(struct pppoe_softc *sc, struct pbuf *pb)
638 {
639  struct eth_hdr *ethhdr;
640  u16_t etype;
641  err_t res;
642 
643  if (!sc->sc_ethif) {
644  pbuf_free(pb);
645  return ERR_IF;
646  }
647 
648  ethhdr = (struct eth_hdr *)pb->payload;
649  etype = sc->sc_state == PPPOE_STATE_SESSION ? ETHTYPE_PPPOE : ETHTYPE_PPPOEDISC;
650  ethhdr->type = htons(etype);
651  MEMCPY(ethhdr->dest.addr, sc->sc_dest.addr, sizeof(ethhdr->dest.addr));
652  MEMCPY(ethhdr->src.addr, ((struct eth_addr *)sc->sc_ethif->hwaddr)->addr, sizeof(ethhdr->src.addr));
653 
654  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",
655  sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, etype,
656  sc->sc_state, sc->sc_session,
657  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],
658  pb->tot_len));
659 
660  res = sc->sc_ethif->linkoutput(sc->sc_ethif, pb);
661 
662  pbuf_free(pb);
663 
664  return res;
665 }
666 
667 static err_t
668 pppoe_send_padi(struct pppoe_softc *sc)
669 {
670  struct pbuf *pb;
671  u8_t *p;
672  int len;
673 #ifdef PPPOE_TODO
674  int l1 = 0, l2 = 0; /* XXX: gcc */
675 #endif /* PPPOE_TODO */
676 
677  if (sc->sc_state >PPPOE_STATE_PADI_SENT) {
678  PPPDEBUG(LOG_ERR, ("ERROR: pppoe_send_padi in state %d", sc->sc_state));
679  }
680 
681  /* calculate length of frame (excluding ethernet header + pppoe header) */
682  len = 2 + 2 + 2 + 2 + sizeof sc; /* service name tag is required, host unique is send too */
683 #ifdef PPPOE_TODO
684  if (sc->sc_service_name != NULL) {
685  l1 = (int)strlen(sc->sc_service_name);
686  len += l1;
687  }
688  if (sc->sc_concentrator_name != NULL) {
689  l2 = (int)strlen(sc->sc_concentrator_name);
690  len += 2 + 2 + l2;
691  }
692 #endif /* PPPOE_TODO */
693  LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff",
694  sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff);
695 
696  /* allocate a buffer */
697  pb = pbuf_alloc(PBUF_LINK, (u16_t)(sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len), PBUF_RAM);
698  if (!pb) {
699  return ERR_MEM;
700  }
701  LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len);
702 
703  p = (u8_t*)pb->payload + sizeof (struct eth_hdr);
704  /* fill in pkt */
705  PPPOE_ADD_HEADER(p, PPPOE_CODE_PADI, 0, (u16_t)len);
706  PPPOE_ADD_16(p, PPPOE_TAG_SNAME);
707 #ifdef PPPOE_TODO
708  if (sc->sc_service_name != NULL) {
709  PPPOE_ADD_16(p, l1);
710  MEMCPY(p, sc->sc_service_name, l1);
711  p += l1;
712  } else
713 #endif /* PPPOE_TODO */
714  {
715  PPPOE_ADD_16(p, 0);
716  }
717 #ifdef PPPOE_TODO
718  if (sc->sc_concentrator_name != NULL) {
719  PPPOE_ADD_16(p, PPPOE_TAG_ACNAME);
720  PPPOE_ADD_16(p, l2);
721  MEMCPY(p, sc->sc_concentrator_name, l2);
722  p += l2;
723  }
724 #endif /* PPPOE_TODO */
725  PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE);
726  PPPOE_ADD_16(p, sizeof(sc));
727  MEMCPY(p, &sc, sizeof sc);
728 
729  /* send pkt */
730  return pppoe_output(sc, pb);
731 }
732 
733 static void
734 pppoe_timeout(void *arg)
735 {
736  int retry_wait, err;
737  struct pppoe_softc *sc = (struct pppoe_softc*)arg;
738 
739  PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": timeout\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num));
740 
741  switch (sc->sc_state) {
742  case PPPOE_STATE_PADI_SENT:
743  /*
744  * We have two basic ways of retrying:
745  * - Quick retry mode: try a few times in short sequence
746  * - Slow retry mode: we already had a connection successfully
747  * established and will try infinitely (without user
748  * intervention)
749  * We only enter slow retry mode if IFF_LINK1 (aka autodial)
750  * is not set.
751  */
752 
753  /* initialize for quick retry mode */
754  retry_wait = PPPOE_DISC_TIMEOUT * (1 + sc->sc_padi_retried);
755 
756  sc->sc_padi_retried++;
757  if (sc->sc_padi_retried >= PPPOE_DISC_MAXPADI) {
758 #if 0
759  if ((sc->sc_sppp.pp_if.if_flags & IFF_LINK1) == 0) {
760  /* slow retry mode */
761  retry_wait = PPPOE_SLOW_RETRY;
762  } else
763 #endif
764  {
765  pppoe_abort_connect(sc);
766  return;
767  }
768  }
769  if ((err = pppoe_send_padi(sc)) != 0) {
770  sc->sc_padi_retried--;
771  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));
772  }
773  sys_timeout(retry_wait, pppoe_timeout, sc);
774  break;
775 
776  case PPPOE_STATE_PADR_SENT:
777  sc->sc_padr_retried++;
778  if (sc->sc_padr_retried >= PPPOE_DISC_MAXPADR) {
779  MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest));
780  sc->sc_state = PPPOE_STATE_PADI_SENT;
781  sc->sc_padr_retried = 0;
782  if ((err = pppoe_send_padi(sc)) != 0) {
783  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));
784  }
785  sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padi_retried), pppoe_timeout, sc);
786  return;
787  }
788  if ((err = pppoe_send_padr(sc)) != 0) {
789  sc->sc_padr_retried--;
790  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));
791  }
792  sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc);
793  break;
794  case PPPOE_STATE_CLOSING:
795  pppoe_do_disconnect(sc);
796  break;
797  default:
798  return; /* all done, work in peace */
799  }
800 }
801 
802 /* Start a connection (i.e. initiate discovery phase) */
803 int
804 pppoe_connect(struct pppoe_softc *sc)
805 {
806  int err;
807 
808  if (sc->sc_state != PPPOE_STATE_INITIAL) {
809  return EBUSY;
810  }
811 
812 #ifdef PPPOE_SERVER
813  /* wait PADI if IFF_PASSIVE */
814  if ((sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) {
815  return 0;
816  }
817 #endif
818  /* save state, in case we fail to send PADI */
819  sc->sc_state = PPPOE_STATE_PADI_SENT;
820  sc->sc_padr_retried = 0;
821  err = pppoe_send_padi(sc);
822  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));
823  sys_timeout(PPPOE_DISC_TIMEOUT, pppoe_timeout, sc);
824  return err;
825 }
826 
827 /* disconnect */
828 void
829 pppoe_disconnect(struct pppoe_softc *sc)
830 {
831  if (sc->sc_state < PPPOE_STATE_SESSION) {
832  return;
833  }
834  /*
835  * Do not call pppoe_disconnect here, the upper layer state
836  * machine gets confused by this. We must return from this
837  * function and defer disconnecting to the timeout handler.
838  */
839  sc->sc_state = PPPOE_STATE_CLOSING;
840  sys_timeout(20, pppoe_timeout, sc);
841 }
842 
843 static int
844 pppoe_do_disconnect(struct pppoe_softc *sc)
845 {
846  int err;
847 
848  if (sc->sc_state < PPPOE_STATE_SESSION) {
849  err = EBUSY;
850  } else {
851  PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": disconnecting\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num));
852  err = pppoe_send_padt(sc->sc_ethif, sc->sc_session, (const u8_t *)&sc->sc_dest);
853  }
854 
855  /* cleanup softc */
856  sc->sc_state = PPPOE_STATE_INITIAL;
857  MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest));
858  sc->sc_ac_cookie_len = 0;
859 #ifdef PPPOE_SERVER
860  if (sc->sc_hunique) {
861  mem_free(sc->sc_hunique);
862  sc->sc_hunique = NULL;
863  }
864  sc->sc_hunique_len = 0;
865 #endif
866  sc->sc_session = 0;
867 
868  sc->sc_linkStatusCB(sc->sc_pd, 0); /* notify upper layers */
869 
870  return err;
871 }
872 
873 /* Connection attempt aborted */
874 static void
875 pppoe_abort_connect(struct pppoe_softc *sc)
876 {
877  printf("%c%c%"U16_F": could not establish connection\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num);
878  sc->sc_state = PPPOE_STATE_CLOSING;
879 
880  sc->sc_linkStatusCB(sc->sc_pd, 0); /* notify upper layers */
881 
882  /* clear connection state */
883  MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest));
884  sc->sc_state = PPPOE_STATE_INITIAL;
885 }
886 
887 /* Send a PADR packet */
888 static err_t
889 pppoe_send_padr(struct pppoe_softc *sc)
890 {
891  struct pbuf *pb;
892  u8_t *p;
893  size_t len;
894 #ifdef PPPOE_TODO
895  size_t l1 = 0; /* XXX: gcc */
896 #endif /* PPPOE_TODO */
897 
898  if (sc->sc_state != PPPOE_STATE_PADR_SENT) {
899  return ERR_CONN;
900  }
901 
902  len = 2 + 2 + 2 + 2 + sizeof(sc); /* service name, host unique */
903 #ifdef PPPOE_TODO
904  if (sc->sc_service_name != NULL) { /* service name tag maybe empty */
905  l1 = strlen(sc->sc_service_name);
906  len += l1;
907  }
908 #endif /* PPPOE_TODO */
909  if (sc->sc_ac_cookie_len > 0) {
910  len += 2 + 2 + sc->sc_ac_cookie_len; /* AC cookie */
911  }
912  LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff",
913  sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff);
914  pb = pbuf_alloc(PBUF_LINK, (u16_t)(sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len), PBUF_RAM);
915  if (!pb) {
916  return ERR_MEM;
917  }
918  LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len);
919  p = (u8_t*)pb->payload + sizeof (struct eth_hdr);
920  PPPOE_ADD_HEADER(p, PPPOE_CODE_PADR, 0, len);
921  PPPOE_ADD_16(p, PPPOE_TAG_SNAME);
922 #ifdef PPPOE_TODO
923  if (sc->sc_service_name != NULL) {
924  PPPOE_ADD_16(p, l1);
925  MEMCPY(p, sc->sc_service_name, l1);
926  p += l1;
927  } else
928 #endif /* PPPOE_TODO */
929  {
930  PPPOE_ADD_16(p, 0);
931  }
932  if (sc->sc_ac_cookie_len > 0) {
933  PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE);
934  PPPOE_ADD_16(p, sc->sc_ac_cookie_len);
935  MEMCPY(p, sc->sc_ac_cookie, sc->sc_ac_cookie_len);
936  p += sc->sc_ac_cookie_len;
937  }
938  PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE);
939  PPPOE_ADD_16(p, sizeof(sc));
940  MEMCPY(p, &sc, sizeof sc);
941 
942  return pppoe_output(sc, pb);
943 }
944 
945 /* send a PADT packet */
946 static err_t
947 pppoe_send_padt(struct netif *outgoing_if, u_int session, const u8_t *dest)
948 {
949  struct pbuf *pb;
950  struct eth_hdr *ethhdr;
951  err_t res;
952  u8_t *p;
953 
954  pb = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr) + PPPOE_HEADERLEN, PBUF_RAM);
955  if (!pb) {
956  return ERR_MEM;
957  }
958  LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len);
959 
960  ethhdr = (struct eth_hdr *)pb->payload;
961  ethhdr->type = PP_HTONS(ETHTYPE_PPPOEDISC);
962  MEMCPY(ethhdr->dest.addr, dest, sizeof(ethhdr->dest.addr));
963  MEMCPY(ethhdr->src.addr, ((struct eth_addr *)outgoing_if->hwaddr)->addr, sizeof(ethhdr->src.addr));
964 
965  p = (u8_t*)(ethhdr + 1);
966  PPPOE_ADD_HEADER(p, PPPOE_CODE_PADT, session, 0);
967 
968  res = outgoing_if->linkoutput(outgoing_if, pb);
969 
970  pbuf_free(pb);
971 
972  return res;
973 }
974 
975 #ifdef PPPOE_SERVER
976 static err_t
977 pppoe_send_pado(struct pppoe_softc *sc)
978 {
979  struct pbuf *pb;
980  u8_t *p;
981  size_t len;
982 
983  if (sc->sc_state != PPPOE_STATE_PADO_SENT) {
984  return ERR_CONN;
985  }
986 
987  /* calc length */
988  len = 0;
989  /* include ac_cookie */
990  len += 2 + 2 + sizeof(sc);
991  /* include hunique */
992  len += 2 + 2 + sc->sc_hunique_len;
993  pb = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len, PBUF_RAM);
994  if (!pb) {
995  return ERR_MEM;
996  }
997  LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len);
998  p = (u8_t*)pb->payload + sizeof (struct eth_hdr);
999  PPPOE_ADD_HEADER(p, PPPOE_CODE_PADO, 0, len);
1000  PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE);
1001  PPPOE_ADD_16(p, sizeof(sc));
1002  MEMCPY(p, &sc, sizeof(sc));
1003  p += sizeof(sc);
1004  PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE);
1005  PPPOE_ADD_16(p, sc->sc_hunique_len);
1006  MEMCPY(p, sc->sc_hunique, sc->sc_hunique_len);
1007  return pppoe_output(sc, pb);
1008 }
1009 
1010 static err_t
1011 pppoe_send_pads(struct pppoe_softc *sc)
1012 {
1013  struct pbuf *pb;
1014  u8_t *p;
1015  size_t len, l1 = 0; /* XXX: gcc */
1016 
1017  if (sc->sc_state != PPPOE_STATE_PADO_SENT) {
1018  return ERR_CONN;
1019  }
1020 
1021  sc->sc_session = mono_time.tv_sec % 0xff + 1;
1022  /* calc length */
1023  len = 0;
1024  /* include hunique */
1025  len += 2 + 2 + 2 + 2 + sc->sc_hunique_len; /* service name, host unique*/
1026  if (sc->sc_service_name != NULL) { /* service name tag maybe empty */
1027  l1 = strlen(sc->sc_service_name);
1028  len += l1;
1029  }
1030  pb = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len, PBUF_RAM);
1031  if (!pb) {
1032  return ERR_MEM;
1033  }
1034  LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len);
1035  p = (u8_t*)pb->payload + sizeof (struct eth_hdr);
1036  PPPOE_ADD_HEADER(p, PPPOE_CODE_PADS, sc->sc_session, len);
1037  PPPOE_ADD_16(p, PPPOE_TAG_SNAME);
1038  if (sc->sc_service_name != NULL) {
1039  PPPOE_ADD_16(p, l1);
1040  MEMCPY(p, sc->sc_service_name, l1);
1041  p += l1;
1042  } else {
1043  PPPOE_ADD_16(p, 0);
1044  }
1045  PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE);
1046  PPPOE_ADD_16(p, sc->sc_hunique_len);
1047  MEMCPY(p, sc->sc_hunique, sc->sc_hunique_len);
1048  return pppoe_output(sc, pb);
1049 }
1050 #endif
1051 
1052 err_t
1053 pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb)
1054 {
1055  u8_t *p;
1056  size_t len;
1057 
1058  /* are we ready to process data yet? */
1059  if (sc->sc_state < PPPOE_STATE_SESSION) {
1060  /*sppp_flush(&sc->sc_sppp.pp_if);*/
1061  pbuf_free(pb);
1062  return ERR_CONN;
1063  }
1064 
1065  len = pb->tot_len;
1066 
1067  /* make room for Ethernet header - should not fail */
1068  if (pbuf_header(pb, sizeof(struct eth_hdr) + PPPOE_HEADERLEN) != 0) {
1069  /* bail out */
1070  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));
1071  LINK_STATS_INC(link.lenerr);
1072  pbuf_free(pb);
1073  return ERR_BUF;
1074  }
1075 
1076  p = (u8_t*)pb->payload + sizeof(struct eth_hdr);
1077  PPPOE_ADD_HEADER(p, 0, sc->sc_session, len);
1078 
1079  return pppoe_output(sc, pb);
1080 }
1081 
1082 #if 0 /*def PFIL_HOOKS*/
1083 static int
1084 pppoe_ifattach_hook(void *arg, struct pbuf **mp, struct netif *ifp, int dir)
1085 {
1086  struct pppoe_softc *sc;
1087  int s;
1088 
1089  if (mp != (struct pbuf **)PFIL_IFNET_DETACH) {
1090  return 0;
1091  }
1092 
1093  LIST_FOREACH(sc, &pppoe_softc_list, sc_list) {
1094  if (sc->sc_ethif != ifp) {
1095  continue;
1096  }
1097  if (sc->sc_sppp.pp_if.if_flags & IFF_UP) {
1098  sc->sc_sppp.pp_if.if_flags &= ~(IFF_UP|IFF_RUNNING);
1099  printf("%c%c%"U16_F": ethernet interface detached, going down\n",
1100  sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num);
1101  }
1102  sc->sc_ethif = NULL;
1103  pppoe_clear_softc(sc, "ethernet interface detached");
1104  }
1105 
1106  return 0;
1107 }
1108 #endif
1109 
1110 static void
1111 pppoe_clear_softc(struct pppoe_softc *sc, const char *message)
1112 {
1113  LWIP_UNUSED_ARG(message);
1114 
1115  /* stop timer */
1116  sys_untimeout(pppoe_timeout, sc);
1117  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));
1118 
1119  /* fix our state */
1120  sc->sc_state = PPPOE_STATE_INITIAL;
1121 
1122  /* notify upper layers */
1123  sc->sc_linkStatusCB(sc->sc_pd, 0);
1124 
1125  /* clean up softc */
1126  MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest));
1127  sc->sc_ac_cookie_len = 0;
1128  sc->sc_session = 0;
1129 }
1130 
1131 #endif /* PPPOE_SUPPORT */
1132