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