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