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