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