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