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