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