]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/ankh/lib/lwip/lib/contrib/src/netif/ppp/ppp_oe.c
update
[l4.git] / l4 / pkg / ankh / lib / lwip / lib / contrib / src / netif / ppp / ppp_oe.c
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
140 /** linked list of created pppoe interfaces */
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