if_pppoe.c revision 1.16
1/* $NetBSD: if_pppoe.c,v 1.16 2002/01/13 10:57:57 aymeric Exp $ */
2
3/*
4 * Copyright (c) 2001 Martin Husemann. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 */
28
29#include <sys/cdefs.h>
30__KERNEL_RCSID(0, "$NetBSD: if_pppoe.c,v 1.16 2002/01/13 10:57:57 aymeric Exp $");
31
32#include "pppoe.h"
33#include "bpfilter.h"
34
35#include <sys/param.h>
36#include <sys/systm.h>
37#include <sys/kernel.h>
38#include <sys/callout.h>
39#include <sys/malloc.h>
40#include <sys/mbuf.h>
41#include <sys/socket.h>
42#include <sys/proc.h>
43#include <sys/ioctl.h>
44#include <net/if.h>
45#include <net/if_types.h>
46#include <net/if_ether.h>
47#include <net/if_sppp.h>
48#include <net/if_spppvar.h>
49#include <net/if_pppoe.h>
50
51#if NBPFILTER > 0
52#include <net/bpf.h>
53#endif
54
55#include <machine/types.h>
56#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
57#include <machine/intr.h>
58#endif
59
60#undef PPPOE_DEBUG		/* XXX - remove this or make it an option */
61/* #define PPPOE_DEBUG 1 */
62
63#define PPPOE_HEADERLEN	6
64#define	PPPOE_VERTYPE	0x11	/* VER=1, TYPE = 1 */
65
66#define	PPPOE_TAG_EOL		0x0000		/* end of list */
67#define	PPPOE_TAG_SNAME		0x0101		/* service name */
68#define	PPPOE_TAG_ACNAME	0x0102		/* access concentrator name */
69#define	PPPOE_TAG_HUNIQUE	0x0103		/* host unique */
70#define	PPPOE_TAG_ACCOOKIE	0x0104		/* AC cookie */
71#define	PPPOE_TAG_VENDOR	0x0105		/* vendor specific */
72#define	PPPOE_TAG_RELAYSID	0x0110		/* relay session id */
73#define	PPPOE_TAG_SNAME_ERR	0x0201		/* service name error */
74#define	PPPOE_TAG_ACSYS_ERR	0x0202		/* AC system error */
75#define	PPPOE_TAG_GENERIC_ERR	0x0203		/* gerneric error */
76
77#define PPPOE_CODE_PADI		0x09		/* Active Discovery Initiation */
78#define	PPPOE_CODE_PADO		0x07		/* Active Discovery Offer */
79#define	PPPOE_CODE_PADR		0x19		/* Active Discovery Request */
80#define	PPPOE_CODE_PADS		0x65		/* Active Discovery Session confirmation */
81#define	PPPOE_CODE_PADT		0xA7		/* Active Discovery Terminate */
82
83/* Read a 16 bit unsigned value from a buffer */
84#define PPPOE_READ_16(PTR, VAL)				\
85		(VAL) = ((PTR)[0] << 8) | (PTR)[1];	\
86		(PTR)+=2
87
88/* Add a 16 bit unsigned value to a buffer pointed to by PTR */
89#define	PPPOE_ADD_16(PTR, VAL)			\
90		*(PTR)++ = (VAL) / 256;		\
91		*(PTR)++ = (VAL) % 256
92
93/* Add a complete PPPoE header to the buffer pointed to by PTR */
94#define PPPOE_ADD_HEADER(PTR, CODE, SESS, LEN)	\
95		*(PTR)++ = PPPOE_VERTYPE;	\
96		*(PTR)++ = (CODE);		\
97		PPPOE_ADD_16(PTR, SESS);	\
98		PPPOE_ADD_16(PTR, LEN)
99
100#define	PPPOE_DISC_TIMEOUT	(hz*5)	/* base for quick timeout calculation */
101#define	PPPOE_SLOW_RETRY	(hz*240)	/* persistent retry interval */
102#define PPPOE_DISC_MAXPADI	4	/* retry PADI four times (quickly) */
103#define	PPPOE_DISC_MAXPADR	2	/* retry PADR twice */
104
105struct pppoe_softc {
106	struct sppp sc_sppp;		/* contains a struct ifnet as first element */
107	LIST_ENTRY(pppoe_softc) sc_list;
108	struct ifnet *sc_eth_if;	/* ethernet interface we are using */
109
110	int sc_state;			/* discovery phase or session connected */
111	struct ether_addr sc_dest;	/* hardware address of concentrator */
112	u_int16_t sc_session;		/* PPPoE session id */
113
114	char *sc_service_name;		/* if != NULL: requested name of service */
115	char *sc_concentrator_name;	/* if != NULL: requested concentrator id */
116	u_int8_t *sc_ac_cookie;		/* content of AC cookie we must echo back */
117	size_t sc_ac_cookie_len;	/* length of cookie data */
118	struct callout sc_timeout;	/* timeout while not in session state */
119	int sc_padi_retried;		/* number of PADI retries already done */
120	int sc_padr_retried;		/* number of PADR retries already done */
121};
122
123/* incoming traffic will be queued here */
124struct ifqueue ppoediscinq = { NULL };
125struct ifqueue ppoeinq = { NULL };
126
127#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
128void * pppoe_softintr = NULL;
129static void pppoe_softintr_handler(void *);
130#else
131struct callout pppoe_softintr = CALLOUT_INITIALIZER;
132void pppoe_softintr_handler(void*);
133#endif
134
135extern int sppp_ioctl(struct ifnet *ifp, unsigned long cmd, void *data);
136
137/* input routines */
138static void pppoe_input(void);
139static void pppoe_disc_input(struct mbuf *m);
140static void pppoe_dispatch_disc_pkt(u_int8_t *p, size_t size, struct ifnet *rcvif, struct ether_header *eh);
141static void pppoe_data_input(struct mbuf *m);
142
143/* management routines */
144void pppoeattach(int count);
145static int pppoe_connect(struct pppoe_softc *sc);
146static int pppoe_disconnect(struct pppoe_softc *sc);
147static void pppoe_abort_connect(struct pppoe_softc *sc);
148static int pppoe_ioctl(struct ifnet *ifp, unsigned long cmd, caddr_t data);
149static void pppoe_tls(struct sppp *sp);
150static void pppoe_tlf(struct sppp *sp);
151static void pppoe_start(struct ifnet *ifp);
152
153/* internal timeout handling */
154static void pppoe_timeout(void*);
155
156/* sending actual protocol controll packets */
157static int pppoe_send_padi(struct pppoe_softc *sc);
158static int pppoe_send_padr(struct pppoe_softc *sc);
159static int pppoe_send_padt(struct pppoe_softc *sc);
160
161/* raw output */
162static int pppoe_output(struct pppoe_softc *sc, struct mbuf *m);
163
164/* internal helper functions */
165static struct pppoe_softc * pppoe_find_softc_by_session(u_int session, struct ifnet *rcvif);
166static struct pppoe_softc * pppoe_find_softc_by_hunique(u_int8_t *token, size_t len, struct ifnet *rcvif);
167
168LIST_HEAD(pppoe_softc_head, pppoe_softc) pppoe_softc_list;
169
170int     pppoe_clone_create __P((struct if_clone *, int));
171void    pppoe_clone_destroy __P((struct ifnet *));
172
173struct if_clone pppoe_cloner =
174    IF_CLONE_INITIALIZER("pppoe", pppoe_clone_create, pppoe_clone_destroy);
175
176/* ARGSUSED */
177void
178pppoeattach(count)
179	int count;
180{
181	LIST_INIT(&pppoe_softc_list);
182	if_clone_attach(&pppoe_cloner);
183
184	ppoediscinq.ifq_maxlen = IFQ_MAXLEN;
185	ppoeinq.ifq_maxlen = IFQ_MAXLEN;
186
187#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
188	pppoe_softintr = softintr_establish(IPL_SOFTNET, pppoe_softintr_handler, NULL);
189#endif
190}
191
192int
193pppoe_clone_create(ifc, unit)
194	struct if_clone *ifc;
195	int unit;
196{
197	struct pppoe_softc *sc;
198
199	sc = malloc(sizeof(struct pppoe_softc), M_DEVBUF, M_WAITOK);
200	memset(sc, 0, sizeof(struct pppoe_softc));
201
202	sprintf(sc->sc_sppp.pp_if.if_xname, "pppoe%d", unit);
203	sc->sc_sppp.pp_if.if_softc = sc;
204	sc->sc_sppp.pp_if.if_mtu = ETHERMTU - PPPOE_HEADERLEN - 2; /* two byte PPP protocol discriminator, then IP data */
205	sc->sc_sppp.pp_if.if_flags = IFF_SIMPLEX|IFF_POINTOPOINT|IFF_MULTICAST;
206	sc->sc_sppp.pp_if.if_type = IFT_PPP;
207	sc->sc_sppp.pp_if.if_hdrlen = sizeof(struct ether_header)+PPPOE_HEADERLEN;
208	sc->sc_sppp.pp_if.if_dlt = DLT_PPP_ETHER;
209	sc->sc_sppp.pp_flags |= PP_KEEPALIVE|	/* use LCP keepalive */
210				PP_NOFRAMING;	/* no serial encapsulation */
211	sc->sc_sppp.pp_if.if_ioctl = pppoe_ioctl;
212	IFQ_SET_MAXLEN(&sc->sc_sppp.pp_if.if_snd, IFQ_MAXLEN);
213	IFQ_SET_READY(&sc->sc_sppp.pp_if.if_snd);
214
215	/* changed to real address later */
216	memcpy(&sc->sc_dest, etherbroadcastaddr, sizeof(sc->sc_dest));
217
218	callout_init(&sc->sc_timeout);
219
220	sc->sc_sppp.pp_if.if_start = pppoe_start;
221	sc->sc_sppp.pp_tls = pppoe_tls;
222	sc->sc_sppp.pp_tlf = pppoe_tlf;
223	sc->sc_sppp.pp_framebytes = PPPOE_HEADERLEN;	/* framing added to ppp packets */
224
225	if_attach(&sc->sc_sppp.pp_if);
226	sppp_attach(&sc->sc_sppp.pp_if);
227
228#if NBPFILTER > 0
229	bpfattach(&sc->sc_sppp.pp_if, DLT_PPP_ETHER, 0);
230#endif
231	LIST_INSERT_HEAD(&pppoe_softc_list, sc, sc_list);
232	return 0;
233}
234
235void
236pppoe_clone_destroy(ifp)
237	struct ifnet *ifp;
238{
239	struct pppoe_softc * sc = ifp->if_softc;
240
241	LIST_REMOVE(sc, sc_list);
242#if NBPFILTER > 0
243	bpfdetach(ifp);
244#endif
245	sppp_detach(&sc->sc_sppp.pp_if);
246	if_detach(ifp);
247	free(sc, M_DEVBUF);
248}
249
250/*
251 * Find the interface handling the specified session.
252 * Note: O(number of sessions open), this is a client-side only, mean
253 * and lean implementation, so number of open sessions typically should
254 * be 1.
255 */
256static struct pppoe_softc *
257pppoe_find_softc_by_session(u_int session, struct ifnet *rcvif)
258{
259	struct pppoe_softc *sc;
260
261	if (session == 0) return NULL;
262
263	LIST_FOREACH(sc, &pppoe_softc_list, sc_list) {
264		if (sc->sc_state == PPPOE_STATE_SESSION
265		    && sc->sc_session == session) {
266			if (sc->sc_eth_if == rcvif)
267				return sc;
268			else
269				return NULL;
270		}
271	}
272	return NULL;
273}
274
275/* Check host unique token passed and return appropriate softc pointer,
276 * or NULL if token is bogus. */
277static struct pppoe_softc *
278pppoe_find_softc_by_hunique(u_int8_t *token, size_t len, struct ifnet *rcvif)
279{
280	struct pppoe_softc *sc, *t;
281
282	if (LIST_EMPTY(&pppoe_softc_list)) return NULL;
283
284	if (len != sizeof sc) return NULL;
285	memcpy(&t, token, len);
286
287	LIST_FOREACH(sc, &pppoe_softc_list, sc_list)
288		if (sc == t) break;
289
290	if (sc != t) {
291#ifdef PPPOE_DEBUG
292		printf("pppoe: alien host unique tag, no session found\n");
293#endif
294		return NULL;
295	}
296
297	/* should be safe to access *sc now */
298	if (sc->sc_state < PPPOE_STATE_PADI_SENT || sc->sc_state >= PPPOE_STATE_SESSION) {
299		printf("%s: host unique tag found, but it belongs to a connection in state %d\n",
300			sc->sc_sppp.pp_if.if_xname, sc->sc_state);
301		return NULL;
302	}
303	if (sc->sc_eth_if != rcvif) {
304		printf("%s: wrong interface, not accepting host unique\n",
305			sc->sc_sppp.pp_if.if_xname);
306		return NULL;
307	}
308	return sc;
309}
310
311#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
312static void pppoe_softintr_handler(void *dummy)
313{
314	/* called at splsoftnet() */
315	pppoe_input();
316}
317#else
318void pppoe_softintr_handler(void *dummy)
319{
320	int s = splnet();
321	pppoe_input();
322	callout_deactivate(&pppoe_softintr);
323	splx(s);
324}
325#endif
326
327/* called at appropriate protection level */
328static void
329pppoe_input()
330{
331	struct mbuf *m;
332	int s, disc_done, data_done;
333
334	do {
335		disc_done = 0;
336		data_done = 0;
337		for (;;) {
338			s = splnet();
339			IF_DEQUEUE(&ppoediscinq, m);
340			splx(s);
341			if (m == NULL) break;
342			disc_done = 1;
343			pppoe_disc_input(m);
344		}
345
346		for (;;) {
347			s = splnet();
348			IF_DEQUEUE(&ppoeinq, m);
349			splx(s);
350			if (m == NULL) break;
351			data_done = 1;
352			pppoe_data_input(m);
353		}
354	} while (disc_done || data_done);
355}
356
357/* analyze and handle a single received packet while not in session state */
358static void pppoe_dispatch_disc_pkt(u_int8_t *p, size_t size, struct ifnet *rcvif, struct ether_header *eh)
359{
360	u_int16_t tag, len;
361	u_int8_t vertype, code;
362	u_int16_t session, plen;
363	struct pppoe_softc *sc;
364	const char *err_msg = NULL;
365	u_int8_t * ac_cookie;
366	size_t ac_cookie_len;
367
368	ac_cookie = NULL;
369	ac_cookie_len = 0;
370	session = 0;
371	if (size <= PPPOE_HEADERLEN) {
372		printf("pppoe: packet too short: %ld\n", (long)size);
373		return;
374	}
375	vertype = *p++;
376	if (vertype != PPPOE_VERTYPE) {
377		printf("pppoe: unknown version/type packet: 0x%x\n", vertype);
378		return;
379	}
380	code = *p++;
381	PPPOE_READ_16(p, session);
382	PPPOE_READ_16(p, plen);
383	size -= PPPOE_HEADERLEN;
384
385	if (plen > size) {
386		printf("pppoe: packet content does not fit: data available = %ld, packet size = %ld\n",
387			(long)size, (long)plen);
388		return;
389	}
390	size = plen;	/* ignore trailing garbage */
391	tag = 0;
392	len = 0;
393	sc = NULL;
394	while (size > 4) {
395		PPPOE_READ_16(p, tag);
396		PPPOE_READ_16(p, len);
397		if (len > size) {
398			printf("pppoe: tag 0x%x len 0x%x is too long\n", tag, len);
399			return;
400		}
401		switch (tag) {
402		case PPPOE_TAG_EOL:
403			size = 0; break;
404		case PPPOE_TAG_SNAME:
405			break;	/* ignored */
406		case PPPOE_TAG_ACNAME:
407			break;	/* ignored */
408		case PPPOE_TAG_HUNIQUE:
409			if (sc == NULL)
410				sc = pppoe_find_softc_by_hunique(p, len, rcvif);
411			break;
412		case PPPOE_TAG_ACCOOKIE:
413			if (ac_cookie == NULL) {
414				ac_cookie = p;
415				ac_cookie_len = len;
416			}
417			break;
418		case PPPOE_TAG_SNAME_ERR:
419			err_msg = "SERVICE NAME ERROR";
420			break;
421		case PPPOE_TAG_ACSYS_ERR:
422			err_msg = "AC SYSTEM ERROR";
423			break;
424		case PPPOE_TAG_GENERIC_ERR:
425			err_msg = "GENERIC ERROR";
426			break;
427		}
428		if (err_msg) {
429			printf("%s: %s\n", sc? sc->sc_sppp.pp_if.if_xname : "pppoe",
430					err_msg);
431			return;
432		}
433		if (size >= 0) {
434			size -= 4 + len;
435			if (len > 0)
436				p += len;
437		}
438	}
439	switch (code) {
440	case PPPOE_CODE_PADI:
441	case PPPOE_CODE_PADR:
442		/* ignore, we are no access concentrator */
443		return;
444	case PPPOE_CODE_PADO:
445		if (sc == NULL) {
446			printf("pppoe: received PADO but could not find request for it\n");
447			return;
448		}
449		if (sc->sc_state != PPPOE_STATE_PADI_SENT) {
450			printf("%s: received unexpected PADO\n", sc->sc_sppp.pp_if.if_xname);
451			return;
452		}
453		if (ac_cookie) {
454			sc->sc_ac_cookie = malloc(ac_cookie_len, M_DEVBUF, M_DONTWAIT);
455			if (sc->sc_ac_cookie == NULL)
456				return;
457			sc->sc_ac_cookie_len = ac_cookie_len;
458			memcpy(sc->sc_ac_cookie, ac_cookie, ac_cookie_len);
459		}
460		memcpy(&sc->sc_dest, eh->ether_shost, sizeof sc->sc_dest);
461		callout_stop(&sc->sc_timeout);
462		sc->sc_padr_retried = 0;
463		sc->sc_state = PPPOE_STATE_PADR_SENT;
464		if (pppoe_send_padr(sc) == 0)
465			callout_reset(&sc->sc_timeout, PPPOE_DISC_TIMEOUT*(1+sc->sc_padr_retried), pppoe_timeout, sc);
466		else
467			pppoe_abort_connect(sc);
468		break;
469	case PPPOE_CODE_PADS:
470		if (sc == NULL)
471			return;
472		sc->sc_session = session;
473		callout_stop(&sc->sc_timeout);
474		printf("%s: session 0x%x connected\n", sc->sc_sppp.pp_if.if_xname, session);
475		sc->sc_state = PPPOE_STATE_SESSION;
476		sc->sc_sppp.pp_up(&sc->sc_sppp);	/* notify upper layers */
477		break;
478	case PPPOE_CODE_PADT:
479		if (sc == NULL)
480			return;
481                /* stop timer (we might be about to transmit a PADT ourself) */
482                callout_stop(&sc->sc_timeout);
483                /* signal upper layer */
484                printf("%s: session 0x%x terminated, received PADT\n", sc->sc_sppp.pp_if.if_xname, session);
485                /* clean up softc */
486                sc->sc_state = PPPOE_STATE_INITIAL;
487                memcpy(&sc->sc_dest, etherbroadcastaddr, sizeof(sc->sc_dest));
488                if (sc->sc_ac_cookie) {
489                        free(sc->sc_ac_cookie, M_MBUF);
490                        sc->sc_ac_cookie = NULL;
491                }
492                sc->sc_ac_cookie_len = 0;
493                sc->sc_session = 0;
494                sc->sc_sppp.pp_down(&sc->sc_sppp);
495                break;
496        default:
497                printf("%s: unknown code (0x%04x) session = 0x%04x\n",
498                    sc? sc->sc_sppp.pp_if.if_xname : "pppoe",
499                    code, session);
500                break;
501        }
502}
503
504static void
505pppoe_disc_input(struct mbuf *m)
506{
507        u_int8_t *p;
508        struct ether_header *eh;
509
510        eh = mtod(m, struct ether_header*);
511        m_adj(m, sizeof(struct ether_header));
512        p = mtod(m, u_int8_t*);
513        KASSERT(m->m_flags & M_PKTHDR);
514        pppoe_dispatch_disc_pkt(p, m->m_len, m->m_pkthdr.rcvif, eh);
515        m_free(m);
516}
517
518static void
519pppoe_data_input(struct mbuf *m)
520{
521        u_int8_t *p, vertype;
522        u_int16_t session, plen, code;
523        struct pppoe_softc *sc;
524
525        KASSERT(m->m_flags & M_PKTHDR);
526
527        m_adj(m, sizeof(struct ether_header));
528        if (m->m_pkthdr.len <= PPPOE_HEADERLEN) {
529                printf("pppoe (data): dropping too short packet: %ld bytes\n", (long)m->m_pkthdr.len);
530                goto drop;
531        }
532
533        p = mtod(m, u_int8_t*);
534
535        vertype = *p++;
536        if (vertype != PPPOE_VERTYPE) {
537                printf("pppoe (data): unknown version/type packet: 0x%x\n", vertype);
538                goto drop;
539        }
540
541        code = *p++;
542        if (code != 0)
543                goto drop;
544
545        PPPOE_READ_16(p, session);
546        sc = pppoe_find_softc_by_session(session, m->m_pkthdr.rcvif);
547        if (sc == NULL)
548                goto drop;
549
550        PPPOE_READ_16(p, plen);
551
552#if NBPFILTER > 0
553        if(sc->sc_sppp.pp_if.if_bpf)
554                bpf_mtap(sc->sc_sppp.pp_if.if_bpf, m);
555#endif
556
557        m_adj(m, PPPOE_HEADERLEN);
558
559#ifdef PPPOE_DEBUG
560        {
561                struct mbuf *p;
562
563                printf("%s: pkthdr.len=%d, pppoe.len=%d",
564                        sc->sc_sppp.pp_if.if_xname,
565                        m->m_pkthdr.len, plen);
566                p = m;
567                while (p) {
568                        printf(" l=%d", p->m_len);
569                        p = p->m_next;
570                }
571                printf("\n");
572        }
573#endif
574
575        if (m->m_pkthdr.len < plen)
576                goto drop;
577
578        /* fix incoming interface pointer (not the raw ethernet interface anymore) */
579        m->m_pkthdr.rcvif = &sc->sc_sppp.pp_if;
580
581        /* pass packet up and account for it */
582        sc->sc_sppp.pp_if.if_ipackets++;
583        sppp_input(&sc->sc_sppp.pp_if, m);
584        return;
585
586drop:
587        m_free(m);
588}
589
590static int
591pppoe_output(struct pppoe_softc *sc, struct mbuf *m)
592{
593        struct sockaddr dst;
594        struct ether_header *eh;
595        u_int16_t etype;
596
597        if (sc->sc_eth_if == NULL)
598                return EIO;
599
600        memset(&dst, 0, sizeof dst);
601        dst.sa_family = AF_UNSPEC;
602        eh = (struct ether_header*)&dst.sa_data;
603        etype = sc->sc_state == PPPOE_STATE_SESSION? ETHERTYPE_PPPOE : ETHERTYPE_PPPOEDISC;
604        eh->ether_type = htons(etype);
605        memcpy(&eh->ether_dhost, &sc->sc_dest, sizeof sc->sc_dest);
606
607#ifdef PPPOE_DEBUG
608        printf("%s (%x) state=%d, session=0x%x output -> %s, len=%d\n",
609            sc->sc_sppp.pp_if.if_xname, etype,
610            sc->sc_state, sc->sc_session,
611	    ether_sprintf((const unsigned char *)&sc->sc_dest), m->m_pkthdr.len);
612#endif
613
614	sc->sc_sppp.pp_if.if_opackets++;
615	return sc->sc_eth_if->if_output(sc->sc_eth_if, m, &dst, NULL);
616}
617
618static int
619pppoe_ioctl(struct ifnet *ifp, unsigned long cmd, caddr_t data)
620{
621	struct proc *p = curproc;	/* XXX */
622	struct pppoe_softc *sc = (struct pppoe_softc*)ifp;
623	int error = 0;
624
625	switch (cmd) {
626	case PPPOESETPARMS:
627	{
628		struct pppoediscparms *parms = (struct pppoediscparms*)data;
629		if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
630			return error;
631		if (parms->eth_ifname[0] != 0) {
632			sc->sc_eth_if = ifunit(parms->eth_ifname);
633			if (sc->sc_eth_if == NULL)
634				return ENXIO;
635		}
636		if (parms->ac_name) {
637			size_t s;
638			char * p = malloc(parms->ac_name_len + 1, M_DEVBUF, M_WAITOK);
639			copyinstr(parms->ac_name, p, parms->ac_name_len, &s);
640			if (sc->sc_concentrator_name)
641				free(sc->sc_concentrator_name, M_DEVBUF);
642			sc->sc_concentrator_name = p;
643		}
644		if (parms->service_name) {
645			size_t s;
646			char * p = malloc(parms->service_name_len + 1, M_DEVBUF, M_WAITOK);
647			copyinstr(parms->service_name, p, parms->service_name_len, &s);
648			if (sc->sc_service_name)
649				free(sc->sc_service_name, M_DEVBUF);
650			sc->sc_service_name = p;
651		}
652		return 0;
653	}
654	break;
655	case PPPOEGETPARMS:
656	{
657		struct pppoediscparms *parms = (struct pppoediscparms*)data;
658		memset(parms, 0, sizeof *parms);
659		if (sc->sc_eth_if)
660			strncpy(parms->ifname, sc->sc_eth_if->if_xname, IFNAMSIZ);
661		return 0;
662	}
663	break;
664	case PPPOEGETSESSION:
665	{
666		struct pppoeconnectionstate *state = (struct pppoeconnectionstate*)data;
667		state->state = sc->sc_state;
668		state->session_id = sc->sc_session;
669		state->padi_retry_no = sc->sc_padi_retried;
670		state->padr_retry_no = sc->sc_padr_retried;
671		return 0;
672	}
673	break;
674	case SIOCSIFFLAGS:
675	{
676		struct ifreq *ifr = (struct ifreq*) data;
677		/*
678		 * Prevent running re-establishment timers overriding
679		 * administrators choice.
680		 */
681		if ((ifr->ifr_flags & IFF_UP) == 0
682		     && sc->sc_state >= PPPOE_STATE_PADI_SENT
683		     && sc->sc_state < PPPOE_STATE_SESSION) {
684			callout_stop(&sc->sc_timeout);
685			sc->sc_state = PPPOE_STATE_INITIAL;
686			sc->sc_padi_retried = 0;
687			sc->sc_padr_retried = 0;
688			memcpy(&sc->sc_dest, etherbroadcastaddr, sizeof(sc->sc_dest));
689		}
690	}
691	/* FALLTHROUGH */
692	default:
693		return sppp_ioctl(ifp, cmd, data);
694	}
695	return 0;
696}
697
698/*
699 * Allocate a mbuf/cluster with space to store the given data length
700 * of payload, leaving space for prepending an ethernet header
701 * in front.
702 */
703static struct mbuf *
704pppoe_get_mbuf(size_t len)
705{
706	struct mbuf *m;
707
708	MGETHDR(m, M_DONTWAIT, MT_DATA);
709	if (m == NULL)
710		return NULL;
711	if (len+sizeof(struct ether_header) > MHLEN) {
712		MCLGET(m, M_DONTWAIT);
713		if ((m->m_flags & M_EXT) == 0) {
714			struct mbuf *n;
715			MFREE(m, n);
716			return 0;
717		}
718	}
719	m->m_data += sizeof(struct ether_header);
720	m->m_len = len;
721	m->m_pkthdr.len = len;
722	m->m_pkthdr.rcvif = NULL;
723
724	return m;
725}
726
727static int
728pppoe_send_padi(struct pppoe_softc *sc)
729{
730	struct mbuf *m0;
731	int len, l1, l2;
732	u_int8_t *p;
733
734	if (sc->sc_state >PPPOE_STATE_PADI_SENT)
735		panic("pppoe_send_padi in state %d", sc->sc_state);
736
737	/* calculate length of frame (excluding ethernet header + pppoe header) */
738	len = 2+2+2+2+sizeof sc;	/* service name tag is required, host unique is send too */
739	if (sc->sc_service_name != NULL) {
740		l1 = strlen(sc->sc_service_name);
741		len += l1;
742	}
743	if (sc->sc_concentrator_name != NULL) {
744		l2 = strlen(sc->sc_concentrator_name);
745		len += 2+2+l2;
746	}
747
748	/* allocate a buffer */
749	m0 = pppoe_get_mbuf(len+PPPOE_HEADERLEN);	/* header len + payload len */
750	if (!m0) return ENOBUFS;
751
752	/* fill in pkt */
753	p = mtod(m0, u_int8_t*);
754	PPPOE_ADD_HEADER(p, PPPOE_CODE_PADI, 0, len);
755	PPPOE_ADD_16(p, PPPOE_TAG_SNAME);
756	if (sc->sc_service_name != NULL) {
757		PPPOE_ADD_16(p, l1);
758		memcpy(p, sc->sc_service_name, l1);
759		p += l1;
760	} else {
761		PPPOE_ADD_16(p, 0);
762	}
763	if (sc->sc_concentrator_name != NULL) {
764		PPPOE_ADD_16(p, PPPOE_TAG_ACNAME);
765		PPPOE_ADD_16(p, l2);
766		memcpy(p, sc->sc_concentrator_name, l2);
767		p += l2;
768	}
769	PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE);
770	PPPOE_ADD_16(p, sizeof(sc));
771	memcpy(p, &sc, sizeof sc);
772
773#ifdef PPPOE_DEBUG
774	p += sizeof sc;
775	if (p - mtod(m0, u_int8_t*) != len + PPPOE_HEADERLEN)
776		panic("pppoe_send_padi: garbled output len, should be %ld, is %ld",
777		    (long)(len + PPPOE_HEADERLEN), (long)(p - mtod(m0, u_int8_t*)));
778#endif
779
780	/* send pkt */
781	return pppoe_output(sc, m0);
782}
783
784static void
785pppoe_timeout(void *arg)
786{
787	int x, retry_wait;
788	struct pppoe_softc *sc = (struct pppoe_softc*)arg;
789
790#ifdef PPPOE_DEBUG
791	printf("%s: timeout\n", sc->sc_sppp.pp_if.if_xname);
792#endif
793
794	switch (sc->sc_state) {
795	case PPPOE_STATE_PADI_SENT:
796		/*
797		 * We have two basic ways of retrying:
798		 *  - Quick retry mode: try a few times in short sequence
799		 *  - Slow retry mode: we already had a connection successfully
800		 *    established and will try infinitely (without user
801		 *    intervention)
802		 * We only enter slow retry mode if IFF_LINK1 (aka autodial)
803		 * is not set and we already had a successfull connection.
804		 */
805
806		/* initialize for quick retry mode */
807		retry_wait = PPPOE_DISC_TIMEOUT*(1+sc->sc_padi_retried);
808
809		x = splnet();
810		sc->sc_padi_retried++;
811		if (sc->sc_padi_retried >= PPPOE_DISC_MAXPADI) {
812			if ((sc->sc_sppp.pp_if.if_flags & IFF_LINK1) == 0
813			   && sc->sc_sppp.pp_if.if_ibytes) {
814			    /* slow retry mode */
815			    retry_wait = PPPOE_SLOW_RETRY;
816			} else {
817			    pppoe_abort_connect(sc);
818			    splx(x);
819			    return;
820			}
821		}
822		if (pppoe_send_padi(sc) == 0)
823			callout_reset(&sc->sc_timeout, retry_wait, pppoe_timeout, sc);
824		else
825			pppoe_abort_connect(sc);
826		splx(x);
827		break;
828
829	case PPPOE_STATE_PADR_SENT:
830		x = splnet();
831		sc->sc_padr_retried++;
832		if (sc->sc_padr_retried >= PPPOE_DISC_MAXPADR) {
833			memcpy(&sc->sc_dest, etherbroadcastaddr, sizeof(sc->sc_dest));
834			sc->sc_state = PPPOE_STATE_PADI_SENT;
835			sc->sc_padr_retried = 0;
836			if (pppoe_send_padi(sc) == 0)
837				callout_reset(&sc->sc_timeout, PPPOE_DISC_TIMEOUT*(1+sc->sc_padi_retried), pppoe_timeout, sc);
838			else
839				pppoe_abort_connect(sc);
840			splx(x);
841			return;
842		}
843		if (pppoe_send_padr(sc) == 0)
844			callout_reset(&sc->sc_timeout, PPPOE_DISC_TIMEOUT*(1+sc->sc_padr_retried), pppoe_timeout, sc);
845		else
846			pppoe_abort_connect(sc);
847		splx(x);
848		break;
849	case PPPOE_STATE_CLOSING:
850		pppoe_disconnect(sc);
851		break;
852	default:
853		return;	/* all done, work in peace */
854	}
855}
856
857/* Start a connection (i.e. initiate discovery phase) */
858static int
859pppoe_connect(struct pppoe_softc *sc)
860{
861	int x, err;
862
863	if (sc->sc_state != PPPOE_STATE_INITIAL)
864		return EBUSY;
865
866	x = splnet();
867	sc->sc_state = PPPOE_STATE_PADI_SENT;
868	sc->sc_padr_retried = 0;
869	err = pppoe_send_padi(sc);
870	if (err == 0)
871		callout_reset(&sc->sc_timeout, PPPOE_DISC_TIMEOUT, pppoe_timeout, sc);
872	else
873		pppoe_abort_connect(sc);
874	splx(x);
875	return err;
876}
877
878/* disconnect */
879static int
880pppoe_disconnect(struct pppoe_softc *sc)
881{
882	int err, x;
883
884	x = splnet();
885
886	if (sc->sc_state < PPPOE_STATE_SESSION)
887		err = EBUSY;
888	else {
889		printf("%s: disconnecting\n", sc->sc_sppp.pp_if.if_xname);
890		err = pppoe_send_padt(sc);
891	}
892
893	/* cleanup softc */
894	sc->sc_state = PPPOE_STATE_INITIAL;
895	memcpy(&sc->sc_dest, etherbroadcastaddr, sizeof(sc->sc_dest));
896	if (sc->sc_ac_cookie) {
897		free(sc->sc_ac_cookie, M_MBUF);
898		sc->sc_ac_cookie = NULL;
899	}
900	sc->sc_ac_cookie_len = 0;
901	sc->sc_session = 0;
902
903	/* notify upper layer */
904	sc->sc_sppp.pp_down(&sc->sc_sppp);
905
906	splx(x);
907
908	return err;
909}
910
911/* Connection attempt aborted */
912static void
913pppoe_abort_connect(struct pppoe_softc *sc)
914{
915	printf("%s: could not establish connection\n",
916		sc->sc_sppp.pp_if.if_xname);
917	sc->sc_state = PPPOE_STATE_INITIAL;
918	memcpy(&sc->sc_dest, etherbroadcastaddr, sizeof(sc->sc_dest));
919
920	/* notify upper layer */
921	sc->sc_sppp.pp_down(&sc->sc_sppp);
922}
923
924/* Send a PADR packet */
925static int
926pppoe_send_padr(struct pppoe_softc *sc)
927{
928	struct mbuf *m0;
929	u_int8_t *p;
930	size_t len, l1;
931
932	if (sc->sc_state != PPPOE_STATE_PADR_SENT)
933		return EIO;
934
935	len = 2+2+2+2+sizeof(sc);			/* service name, host unique */
936	if (sc->sc_service_name != NULL) {		/* service name tag maybe empty */
937		l1 = strlen(sc->sc_service_name);
938		len += l1;
939	}
940	if (sc->sc_ac_cookie_len > 0)
941		len += 2+2+sc->sc_ac_cookie_len;	/* AC cookie */
942	m0 = pppoe_get_mbuf(len+PPPOE_HEADERLEN);
943	if (!m0) return ENOBUFS;
944	p = mtod(m0, u_int8_t*);
945	PPPOE_ADD_HEADER(p, PPPOE_CODE_PADR, 0, len);
946	PPPOE_ADD_16(p, PPPOE_TAG_SNAME);
947	if (sc->sc_service_name != NULL) {
948		PPPOE_ADD_16(p, l1);
949		memcpy(p, sc->sc_service_name, l1);
950		p += l1;
951	} else {
952		PPPOE_ADD_16(p, 0);
953	}
954	if (sc->sc_ac_cookie_len > 0) {
955		PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE);
956		PPPOE_ADD_16(p, sc->sc_ac_cookie_len);
957		memcpy(p, sc->sc_ac_cookie, sc->sc_ac_cookie_len);
958		p += sc->sc_ac_cookie_len;
959	}
960	PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE);
961	PPPOE_ADD_16(p, sizeof(sc));
962	memcpy(p, &sc, sizeof sc);
963
964#ifdef PPPOE_DEBUG
965	p += sizeof sc;
966	if (p - mtod(m0, u_int8_t*) != len + PPPOE_HEADERLEN)
967		panic("pppoe_send_padr: garbled output len, should be %ld, is %ld",
968			(long)(len + PPPOE_HEADERLEN), (long)(p - mtod(m0, u_int8_t*)));
969#endif
970
971	return pppoe_output(sc, m0);
972}
973
974/* send a PADT packet */
975static int
976pppoe_send_padt(struct pppoe_softc *sc)
977{
978	struct mbuf *m0;
979	u_int8_t *p;
980
981	if (sc->sc_state < PPPOE_STATE_SESSION)
982		return EIO;
983
984#ifdef PPPOE_DEBUG
985	printf("%s: sending PADT\n", sc->sc_sppp.pp_if.if_xname);
986#endif
987	m0 = pppoe_get_mbuf(PPPOE_HEADERLEN);
988	if (!m0) return ENOBUFS;
989	p = mtod(m0, u_int8_t*);
990	PPPOE_ADD_HEADER(p, PPPOE_CODE_PADT, sc->sc_session, 0);
991	return pppoe_output(sc, m0);
992}
993
994static void
995pppoe_tls(struct sppp *sp)
996{
997	struct pppoe_softc *sc = (void*)sp;
998	if (sc->sc_state != PPPOE_STATE_INITIAL)
999		return;
1000	pppoe_connect(sc);
1001}
1002
1003static void
1004pppoe_tlf(struct sppp *sp)
1005{
1006	struct pppoe_softc *sc = (void*)sp;
1007	if (sc->sc_state < PPPOE_STATE_SESSION)
1008		return;
1009	/*
1010	 * Do not call pppoe_disconnect here, the upper layer state
1011	 * machine gets confused by this. We must return from this
1012	 * function and defer disconnecting to the timeout handler.
1013	 */
1014	sc->sc_state = PPPOE_STATE_CLOSING;
1015	callout_reset(&sc->sc_timeout, hz/50, pppoe_timeout, sc);
1016}
1017
1018static void
1019pppoe_start(struct ifnet *ifp)
1020{
1021	struct pppoe_softc *sc = (void*)ifp;
1022	struct mbuf *m;
1023	u_int8_t *p;
1024	size_t len;
1025
1026	if (sppp_isempty(ifp))
1027		return;
1028
1029	/* are we read to proccess data yet? */
1030	if (sc->sc_state < PPPOE_STATE_SESSION) {
1031		sppp_flush(&sc->sc_sppp.pp_if);
1032		return;
1033	}
1034
1035	while ((m = sppp_dequeue(ifp)) != NULL) {
1036		len = m->m_pkthdr.len;
1037		M_PREPEND(m, PPPOE_HEADERLEN, M_DONTWAIT);
1038		if (m == NULL) {
1039			m_free(m);
1040			break;
1041		}
1042		p = mtod(m, u_int8_t*);
1043		PPPOE_ADD_HEADER(p, 0, sc->sc_session, len);
1044
1045#if NBPFILTER > 0
1046		if(sc->sc_sppp.pp_if.if_bpf)
1047			bpf_mtap(sc->sc_sppp.pp_if.if_bpf, m);
1048#endif
1049
1050		pppoe_output(sc, m);
1051	}
1052}
1053