if_pppoe.c revision 1.21
1/* $NetBSD: if_pppoe.c,v 1.21 2002/02/10 15:13:43 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 <sys/cdefs.h> 30__KERNEL_RCSID(0, "$NetBSD: if_pppoe.c,v 1.21 2002/02/10 15:13:43 martin 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#include <machine/intr.h> 56 57#undef PPPOE_DEBUG /* XXX - remove this or make it an option */ 58/* #define PPPOE_DEBUG 1 */ 59 60#define PPPOE_HEADERLEN 6 61#define PPPOE_VERTYPE 0x11 /* VER=1, TYPE = 1 */ 62 63#define PPPOE_TAG_EOL 0x0000 /* end of list */ 64#define PPPOE_TAG_SNAME 0x0101 /* service name */ 65#define PPPOE_TAG_ACNAME 0x0102 /* access concentrator name */ 66#define PPPOE_TAG_HUNIQUE 0x0103 /* host unique */ 67#define PPPOE_TAG_ACCOOKIE 0x0104 /* AC cookie */ 68#define PPPOE_TAG_VENDOR 0x0105 /* vendor specific */ 69#define PPPOE_TAG_RELAYSID 0x0110 /* relay session id */ 70#define PPPOE_TAG_SNAME_ERR 0x0201 /* service name error */ 71#define PPPOE_TAG_ACSYS_ERR 0x0202 /* AC system error */ 72#define PPPOE_TAG_GENERIC_ERR 0x0203 /* gerneric error */ 73 74#define PPPOE_CODE_PADI 0x09 /* Active Discovery Initiation */ 75#define PPPOE_CODE_PADO 0x07 /* Active Discovery Offer */ 76#define PPPOE_CODE_PADR 0x19 /* Active Discovery Request */ 77#define PPPOE_CODE_PADS 0x65 /* Active Discovery Session confirmation */ 78#define PPPOE_CODE_PADT 0xA7 /* Active Discovery Terminate */ 79 80/* two byte PPP protocol discriminator, then IP data */ 81#define PPPOE_MAXMTU (ETHERMTU-PPPOE_HEADERLEN-2) 82 83/* Read a 16 bit unsigned value from a buffer */ 84#define PPPOE_READ_16(PTR, VAL) \ 85 (VAL) = ((PTR)[0] << 8) | (PTR)[1]; \ 86 (PTR)+=2 87 88/* Add a 16 bit unsigned value to a buffer pointed to by PTR */ 89#define PPPOE_ADD_16(PTR, VAL) \ 90 *(PTR)++ = (VAL) / 256; \ 91 *(PTR)++ = (VAL) % 256 92 93/* Add a complete PPPoE header to the buffer pointed to by PTR */ 94#define PPPOE_ADD_HEADER(PTR, CODE, SESS, LEN) \ 95 *(PTR)++ = PPPOE_VERTYPE; \ 96 *(PTR)++ = (CODE); \ 97 PPPOE_ADD_16(PTR, SESS); \ 98 PPPOE_ADD_16(PTR, LEN) 99 100#define PPPOE_DISC_TIMEOUT (hz*5) /* base for quick timeout calculation */ 101#define PPPOE_SLOW_RETRY (hz*60) /* persistent retry interval */ 102#define PPPOE_DISC_MAXPADI 4 /* retry PADI four times (quickly) */ 103#define PPPOE_DISC_MAXPADR 2 /* retry PADR twice */ 104 105struct pppoe_softc { 106 struct sppp sc_sppp; /* contains a struct ifnet as first element */ 107 LIST_ENTRY(pppoe_softc) sc_list; 108 struct ifnet *sc_eth_if; /* ethernet interface we are using */ 109 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 = PPPOE_MAXMTU; 205 sc->sc_sppp.pp_if.if_flags = IFF_SIMPLEX|IFF_POINTOPOINT|IFF_MULTICAST; 206 sc->sc_sppp.pp_if.if_type = IFT_PPP; 207 sc->sc_sppp.pp_if.if_hdrlen = sizeof(struct ether_header)+PPPOE_HEADERLEN; 208 sc->sc_sppp.pp_if.if_dlt = DLT_PPP_ETHER; 209 sc->sc_sppp.pp_flags |= PP_KEEPALIVE| /* use LCP keepalive */ 210 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 282 if (LIST_EMPTY(&pppoe_softc_list)) return NULL; 283 284 if (len != sizeof sc) return NULL; 285 memcpy(&t, token, len); 286 287 LIST_FOREACH(sc, &pppoe_softc_list, sc_list) 288 if (sc == t) break; 289 290 if (sc != t) { 291#ifdef PPPOE_DEBUG 292 printf("pppoe: alien host unique tag, no session found\n"); 293#endif 294 return NULL; 295 } 296 297 /* should be safe to access *sc now */ 298 if (sc->sc_state < PPPOE_STATE_PADI_SENT || sc->sc_state >= PPPOE_STATE_SESSION) { 299 printf("%s: host unique tag found, but it belongs to a connection in state %d\n", 300 sc->sc_sppp.pp_if.if_xname, sc->sc_state); 301 return NULL; 302 } 303 if (sc->sc_eth_if != rcvif) { 304 printf("%s: wrong interface, not accepting host unique\n", 305 sc->sc_sppp.pp_if.if_xname); 306 return NULL; 307 } 308 return sc; 309} 310 311#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS 312static void pppoe_softintr_handler(void *dummy) 313{ 314 /* called at splsoftnet() */ 315 pppoe_input(); 316} 317#else 318void pppoe_softintr_handler(void *dummy) 319{ 320 int s = splnet(); 321 pppoe_input(); 322 callout_deactivate(&pppoe_softintr); 323 splx(s); 324} 325#endif 326 327/* called at appropriate protection level */ 328static void 329pppoe_input() 330{ 331 struct mbuf *m; 332 int s, disc_done, data_done; 333 334 do { 335 disc_done = 0; 336 data_done = 0; 337 for (;;) { 338 s = splnet(); 339 IF_DEQUEUE(&ppoediscinq, m); 340 splx(s); 341 if (m == NULL) break; 342 disc_done = 1; 343 pppoe_disc_input(m); 344 } 345 346 for (;;) { 347 s = splnet(); 348 IF_DEQUEUE(&ppoeinq, m); 349 splx(s); 350 if (m == NULL) break; 351 data_done = 1; 352 pppoe_data_input(m); 353 } 354 } while (disc_done || data_done); 355} 356 357/* analyze and handle a single received packet while not in session state */ 358static void pppoe_dispatch_disc_pkt(u_int8_t *p, size_t size, struct ifnet *rcvif, struct ether_header *eh) 359{ 360 u_int16_t tag, len; 361 u_int8_t vertype, code; 362 u_int16_t session, plen; 363 struct pppoe_softc *sc; 364 const char *err_msg = NULL; 365 u_int8_t * ac_cookie; 366 size_t ac_cookie_len; 367 368 ac_cookie = NULL; 369 ac_cookie_len = 0; 370 session = 0; 371 if (size <= PPPOE_HEADERLEN) { 372 printf("pppoe: packet too short: %ld\n", (long)size); 373 return; 374 } 375 vertype = *p++; 376 if (vertype != PPPOE_VERTYPE) { 377 printf("pppoe: unknown version/type packet: 0x%x\n", vertype); 378 return; 379 } 380 code = *p++; 381 PPPOE_READ_16(p, session); 382 PPPOE_READ_16(p, plen); 383 size -= PPPOE_HEADERLEN; 384 385 if (plen > size) { 386 printf("pppoe: packet content does not fit: data available = %ld, packet size = %ld\n", 387 (long)size, (long)plen); 388 return; 389 } 390 size = plen; /* ignore trailing garbage */ 391 tag = 0; 392 len = 0; 393 sc = NULL; 394 while (size > 4) { 395 PPPOE_READ_16(p, tag); 396 PPPOE_READ_16(p, len); 397 if (len > size) { 398 printf("pppoe: tag 0x%x len 0x%x is too long\n", tag, len); 399 return; 400 } 401 switch (tag) { 402 case PPPOE_TAG_EOL: 403 size = 0; break; 404 case PPPOE_TAG_SNAME: 405 break; /* ignored */ 406 case PPPOE_TAG_ACNAME: 407 break; /* ignored */ 408 case PPPOE_TAG_HUNIQUE: 409 if (sc == NULL) 410 sc = pppoe_find_softc_by_hunique(p, len, rcvif); 411 break; 412 case PPPOE_TAG_ACCOOKIE: 413 if (ac_cookie == NULL) { 414 ac_cookie = p; 415 ac_cookie_len = len; 416 } 417 break; 418 case PPPOE_TAG_SNAME_ERR: 419 err_msg = "SERVICE NAME ERROR"; 420 break; 421 case PPPOE_TAG_ACSYS_ERR: 422 err_msg = "AC SYSTEM ERROR"; 423 break; 424 case PPPOE_TAG_GENERIC_ERR: 425 err_msg = "GENERIC ERROR"; 426 break; 427 } 428 if (err_msg) { 429 printf("%s: %s\n", sc? sc->sc_sppp.pp_if.if_xname : "pppoe", 430 err_msg); 431 return; 432 } 433 if (size >= 0) { 434 size -= 4 + len; 435 if (len > 0) 436 p += len; 437 } 438 } 439 switch (code) { 440 case PPPOE_CODE_PADI: 441 case PPPOE_CODE_PADR: 442 /* ignore, we are no access concentrator */ 443 return; 444 case PPPOE_CODE_PADO: 445 if (sc == NULL) { 446 printf("pppoe: received PADO but could not find request for it\n"); 447 return; 448 } 449 if (sc->sc_state != PPPOE_STATE_PADI_SENT) { 450 printf("%s: received unexpected PADO\n", sc->sc_sppp.pp_if.if_xname); 451 return; 452 } 453 if (ac_cookie) { 454 sc->sc_ac_cookie = malloc(ac_cookie_len, M_DEVBUF, M_DONTWAIT); 455 if (sc->sc_ac_cookie == NULL) 456 return; 457 sc->sc_ac_cookie_len = ac_cookie_len; 458 memcpy(sc->sc_ac_cookie, ac_cookie, ac_cookie_len); 459 } 460 memcpy(&sc->sc_dest, eh->ether_shost, sizeof sc->sc_dest); 461 callout_stop(&sc->sc_timeout); 462 sc->sc_padr_retried = 0; 463 sc->sc_state = PPPOE_STATE_PADR_SENT; 464 if (pppoe_send_padr(sc) == 0) 465 callout_reset(&sc->sc_timeout, PPPOE_DISC_TIMEOUT*(1+sc->sc_padr_retried), pppoe_timeout, sc); 466 else 467 pppoe_abort_connect(sc); 468 break; 469 case PPPOE_CODE_PADS: 470 if (sc == NULL) 471 return; 472 sc->sc_session = session; 473 callout_stop(&sc->sc_timeout); 474 if (sc->sc_sppp.pp_if.if_flags & IFF_DEBUG) 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 if (sc->sc_sppp.pp_if.if_flags & IFF_DEBUG) 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 /* signal upper layer */ 496 sc->sc_sppp.pp_down(&sc->sc_sppp); 497 break; 498 default: 499 printf("%s: unknown code (0x%04x) session = 0x%04x\n", 500 sc? sc->sc_sppp.pp_if.if_xname : "pppoe", 501 code, session); 502 break; 503 } 504} 505 506static void 507pppoe_disc_input(struct mbuf *m) 508{ 509 u_int8_t *p; 510 struct ether_header *eh; 511 512 eh = mtod(m, struct ether_header*); 513 m_adj(m, sizeof(struct ether_header)); 514 p = mtod(m, u_int8_t*); 515 KASSERT(m->m_flags & M_PKTHDR); 516 pppoe_dispatch_disc_pkt(p, m->m_len, m->m_pkthdr.rcvif, eh); 517 m_free(m); 518} 519 520static void 521pppoe_data_input(struct mbuf *m) 522{ 523 u_int8_t *p, vertype; 524 u_int16_t session, plen, code; 525 struct pppoe_softc *sc; 526 527 KASSERT(m->m_flags & M_PKTHDR); 528 529 m_adj(m, sizeof(struct ether_header)); 530 if (m->m_pkthdr.len <= PPPOE_HEADERLEN) { 531 printf("pppoe (data): dropping too short packet: %ld bytes\n", (long)m->m_pkthdr.len); 532 goto drop; 533 } 534 535 p = mtod(m, u_int8_t*); 536 537 vertype = *p++; 538 if (vertype != PPPOE_VERTYPE) { 539 printf("pppoe (data): unknown version/type packet: 0x%x\n", vertype); 540 goto drop; 541 } 542 543 code = *p++; 544 if (code != 0) 545 goto drop; 546 547 PPPOE_READ_16(p, session); 548 sc = pppoe_find_softc_by_session(session, m->m_pkthdr.rcvif); 549 if (sc == NULL) 550 goto drop; 551 552 PPPOE_READ_16(p, plen); 553 554#if NBPFILTER > 0 555 if(sc->sc_sppp.pp_if.if_bpf) 556 bpf_mtap(sc->sc_sppp.pp_if.if_bpf, m); 557#endif 558 559 m_adj(m, PPPOE_HEADERLEN); 560 561#ifdef PPPOE_DEBUG 562 { 563 struct mbuf *p; 564 565 printf("%s: pkthdr.len=%d, pppoe.len=%d", 566 sc->sc_sppp.pp_if.if_xname, 567 m->m_pkthdr.len, plen); 568 p = m; 569 while (p) { 570 printf(" l=%d", p->m_len); 571 p = p->m_next; 572 } 573 printf("\n"); 574 } 575#endif 576 577 if (m->m_pkthdr.len < plen) 578 goto drop; 579 580 /* fix incoming interface pointer (not the raw ethernet interface anymore) */ 581 m->m_pkthdr.rcvif = &sc->sc_sppp.pp_if; 582 583 /* pass packet up and account for it */ 584 sc->sc_sppp.pp_if.if_ipackets++; 585 sppp_input(&sc->sc_sppp.pp_if, m); 586 return; 587 588drop: 589 m_free(m); 590} 591 592static int 593pppoe_output(struct pppoe_softc *sc, struct mbuf *m) 594{ 595 struct sockaddr dst; 596 struct ether_header *eh; 597 u_int16_t etype; 598 599 if (sc->sc_eth_if == NULL) 600 return EIO; 601 602 memset(&dst, 0, sizeof dst); 603 dst.sa_family = AF_UNSPEC; 604 eh = (struct ether_header*)&dst.sa_data; 605 etype = sc->sc_state == PPPOE_STATE_SESSION? ETHERTYPE_PPPOE : ETHERTYPE_PPPOEDISC; 606 eh->ether_type = htons(etype); 607 memcpy(&eh->ether_dhost, &sc->sc_dest, sizeof sc->sc_dest); 608 609#ifdef PPPOE_DEBUG 610 printf("%s (%x) state=%d, session=0x%x output -> %s, len=%d\n", 611 sc->sc_sppp.pp_if.if_xname, etype, 612 sc->sc_state, sc->sc_session, 613 ether_sprintf((const unsigned char *)&sc->sc_dest), m->m_pkthdr.len); 614#endif 615 616 sc->sc_sppp.pp_if.if_opackets++; 617 return sc->sc_eth_if->if_output(sc->sc_eth_if, m, &dst, NULL); 618} 619 620static int 621pppoe_ioctl(struct ifnet *ifp, unsigned long cmd, caddr_t data) 622{ 623 struct proc *p = curproc; /* XXX */ 624 struct pppoe_softc *sc = (struct pppoe_softc*)ifp; 625 int error = 0; 626 627 switch (cmd) { 628 case PPPOESETPARMS: 629 { 630 struct pppoediscparms *parms = (struct pppoediscparms*)data; 631 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 632 return error; 633 if (parms->eth_ifname[0] != 0) { 634 sc->sc_eth_if = ifunit(parms->eth_ifname); 635 if (sc->sc_eth_if == NULL) 636 return ENXIO; 637 } 638 if (parms->ac_name) { 639 size_t s; 640 char * p = malloc(parms->ac_name_len + 1, M_DEVBUF, M_WAITOK); 641 copyinstr(parms->ac_name, p, parms->ac_name_len, &s); 642 if (sc->sc_concentrator_name) 643 free(sc->sc_concentrator_name, M_DEVBUF); 644 sc->sc_concentrator_name = p; 645 } 646 if (parms->service_name) { 647 size_t s; 648 char * p = malloc(parms->service_name_len + 1, M_DEVBUF, M_WAITOK); 649 copyinstr(parms->service_name, p, parms->service_name_len, &s); 650 if (sc->sc_service_name) 651 free(sc->sc_service_name, M_DEVBUF); 652 sc->sc_service_name = p; 653 } 654 return 0; 655 } 656 break; 657 case PPPOEGETPARMS: 658 { 659 struct pppoediscparms *parms = (struct pppoediscparms*)data; 660 memset(parms, 0, sizeof *parms); 661 if (sc->sc_eth_if) 662 strncpy(parms->ifname, sc->sc_eth_if->if_xname, IFNAMSIZ); 663 return 0; 664 } 665 break; 666 case PPPOEGETSESSION: 667 { 668 struct pppoeconnectionstate *state = (struct pppoeconnectionstate*)data; 669 state->state = sc->sc_state; 670 state->session_id = sc->sc_session; 671 state->padi_retry_no = sc->sc_padi_retried; 672 state->padr_retry_no = sc->sc_padr_retried; 673 return 0; 674 } 675 break; 676 case SIOCSIFFLAGS: 677 { 678 struct ifreq *ifr = (struct ifreq*) data; 679 /* 680 * Prevent running re-establishment timers overriding 681 * administrators choice. 682 */ 683 if ((ifr->ifr_flags & IFF_UP) == 0 684 && sc->sc_state >= PPPOE_STATE_PADI_SENT 685 && sc->sc_state < PPPOE_STATE_SESSION) { 686 callout_stop(&sc->sc_timeout); 687 sc->sc_state = PPPOE_STATE_INITIAL; 688 sc->sc_padi_retried = 0; 689 sc->sc_padr_retried = 0; 690 memcpy(&sc->sc_dest, etherbroadcastaddr, sizeof(sc->sc_dest)); 691 } 692 return sppp_ioctl(ifp, cmd, data); 693 } 694 case SIOCSIFMTU: 695 { 696 struct ifreq *ifr = (struct ifreq*) data; 697 698 if (ifr->ifr_mtu > PPPOE_MAXMTU) 699 return EINVAL; 700 return sppp_ioctl(ifp, cmd, data); 701 } 702 default: 703 return sppp_ioctl(ifp, cmd, data); 704 } 705 return 0; 706} 707 708/* 709 * Allocate a mbuf/cluster with space to store the given data length 710 * of payload, leaving space for prepending an ethernet header 711 * in front. 712 */ 713static struct mbuf * 714pppoe_get_mbuf(size_t len) 715{ 716 struct mbuf *m; 717 718 MGETHDR(m, M_DONTWAIT, MT_DATA); 719 if (m == NULL) 720 return NULL; 721 if (len+sizeof(struct ether_header) > MHLEN) { 722 MCLGET(m, M_DONTWAIT); 723 if ((m->m_flags & M_EXT) == 0) { 724 struct mbuf *n; 725 MFREE(m, n); 726 return 0; 727 } 728 } 729 m->m_data += sizeof(struct ether_header); 730 m->m_len = len; 731 m->m_pkthdr.len = len; 732 m->m_pkthdr.rcvif = NULL; 733 734 return m; 735} 736 737static int 738pppoe_send_padi(struct pppoe_softc *sc) 739{ 740 struct mbuf *m0; 741 int len, l1, l2; 742 u_int8_t *p; 743 744 if (sc->sc_state >PPPOE_STATE_PADI_SENT) 745 panic("pppoe_send_padi in state %d", sc->sc_state); 746 747 /* calculate length of frame (excluding ethernet header + pppoe header) */ 748 len = 2+2+2+2+sizeof sc; /* service name tag is required, host unique is send too */ 749 if (sc->sc_service_name != NULL) { 750 l1 = strlen(sc->sc_service_name); 751 len += l1; 752 } 753 if (sc->sc_concentrator_name != NULL) { 754 l2 = strlen(sc->sc_concentrator_name); 755 len += 2+2+l2; 756 } 757 758 /* allocate a buffer */ 759 m0 = pppoe_get_mbuf(len+PPPOE_HEADERLEN); /* header len + payload len */ 760 if (!m0) return ENOBUFS; 761 762 /* fill in pkt */ 763 p = mtod(m0, u_int8_t*); 764 PPPOE_ADD_HEADER(p, PPPOE_CODE_PADI, 0, len); 765 PPPOE_ADD_16(p, PPPOE_TAG_SNAME); 766 if (sc->sc_service_name != NULL) { 767 PPPOE_ADD_16(p, l1); 768 memcpy(p, sc->sc_service_name, l1); 769 p += l1; 770 } else { 771 PPPOE_ADD_16(p, 0); 772 } 773 if (sc->sc_concentrator_name != NULL) { 774 PPPOE_ADD_16(p, PPPOE_TAG_ACNAME); 775 PPPOE_ADD_16(p, l2); 776 memcpy(p, sc->sc_concentrator_name, l2); 777 p += l2; 778 } 779 PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); 780 PPPOE_ADD_16(p, sizeof(sc)); 781 memcpy(p, &sc, sizeof sc); 782 783#ifdef PPPOE_DEBUG 784 p += sizeof sc; 785 if (p - mtod(m0, u_int8_t*) != len + PPPOE_HEADERLEN) 786 panic("pppoe_send_padi: garbled output len, should be %ld, is %ld", 787 (long)(len + PPPOE_HEADERLEN), (long)(p - mtod(m0, u_int8_t*))); 788#endif 789 790 /* send pkt */ 791 return pppoe_output(sc, m0); 792} 793 794static void 795pppoe_timeout(void *arg) 796{ 797 int x, retry_wait; 798 struct pppoe_softc *sc = (struct pppoe_softc*)arg; 799 800#ifdef PPPOE_DEBUG 801 printf("%s: timeout\n", sc->sc_sppp.pp_if.if_xname); 802#endif 803 804 switch (sc->sc_state) { 805 case PPPOE_STATE_PADI_SENT: 806 /* 807 * We have two basic ways of retrying: 808 * - Quick retry mode: try a few times in short sequence 809 * - Slow retry mode: we already had a connection successfully 810 * established and will try infinitely (without user 811 * intervention) 812 * We only enter slow retry mode if IFF_LINK1 (aka autodial) 813 * is not set and we already had a successfull connection. 814 */ 815 816 /* initialize for quick retry mode */ 817 retry_wait = PPPOE_DISC_TIMEOUT*(1+sc->sc_padi_retried); 818 819 x = splnet(); 820 sc->sc_padi_retried++; 821 if (sc->sc_padi_retried >= PPPOE_DISC_MAXPADI) { 822 if ((sc->sc_sppp.pp_if.if_flags & IFF_LINK1) == 0 823 && sc->sc_sppp.pp_if.if_ibytes) { 824 /* slow retry mode */ 825 retry_wait = PPPOE_SLOW_RETRY; 826 } else { 827 pppoe_abort_connect(sc); 828 splx(x); 829 return; 830 } 831 } 832 if (pppoe_send_padi(sc) == 0) 833 callout_reset(&sc->sc_timeout, retry_wait, pppoe_timeout, sc); 834 else 835 pppoe_abort_connect(sc); 836 splx(x); 837 break; 838 839 case PPPOE_STATE_PADR_SENT: 840 x = splnet(); 841 sc->sc_padr_retried++; 842 if (sc->sc_padr_retried >= PPPOE_DISC_MAXPADR) { 843 memcpy(&sc->sc_dest, etherbroadcastaddr, sizeof(sc->sc_dest)); 844 sc->sc_state = PPPOE_STATE_PADI_SENT; 845 sc->sc_padr_retried = 0; 846 if (pppoe_send_padi(sc) == 0) 847 callout_reset(&sc->sc_timeout, PPPOE_DISC_TIMEOUT*(1+sc->sc_padi_retried), pppoe_timeout, sc); 848 else 849 pppoe_abort_connect(sc); 850 splx(x); 851 return; 852 } 853 if (pppoe_send_padr(sc) == 0) 854 callout_reset(&sc->sc_timeout, PPPOE_DISC_TIMEOUT*(1+sc->sc_padr_retried), pppoe_timeout, sc); 855 else 856 pppoe_abort_connect(sc); 857 splx(x); 858 break; 859 case PPPOE_STATE_CLOSING: 860 pppoe_disconnect(sc); 861 break; 862 default: 863 return; /* all done, work in peace */ 864 } 865} 866 867/* Start a connection (i.e. initiate discovery phase) */ 868static int 869pppoe_connect(struct pppoe_softc *sc) 870{ 871 int x, err; 872 873 if (sc->sc_state != PPPOE_STATE_INITIAL) 874 return EBUSY; 875 876 x = splnet(); 877 sc->sc_state = PPPOE_STATE_PADI_SENT; 878 sc->sc_padr_retried = 0; 879 err = pppoe_send_padi(sc); 880 if (err == 0) 881 callout_reset(&sc->sc_timeout, PPPOE_DISC_TIMEOUT, pppoe_timeout, sc); 882 else 883 pppoe_abort_connect(sc); 884 splx(x); 885 return err; 886} 887 888/* disconnect */ 889static int 890pppoe_disconnect(struct pppoe_softc *sc) 891{ 892 int err, x; 893 894 x = splnet(); 895 896 if (sc->sc_state < PPPOE_STATE_SESSION) 897 err = EBUSY; 898 else { 899 if (sc->sc_sppp.pp_if.if_flags & IFF_DEBUG) 900 printf("%s: disconnecting\n", sc->sc_sppp.pp_if.if_xname); 901 err = pppoe_send_padt(sc); 902 } 903 904 /* cleanup softc */ 905 sc->sc_state = PPPOE_STATE_INITIAL; 906 memcpy(&sc->sc_dest, etherbroadcastaddr, sizeof(sc->sc_dest)); 907 if (sc->sc_ac_cookie) { 908 free(sc->sc_ac_cookie, M_MBUF); 909 sc->sc_ac_cookie = NULL; 910 } 911 sc->sc_ac_cookie_len = 0; 912 sc->sc_session = 0; 913 914 /* notify upper layer */ 915 sc->sc_sppp.pp_down(&sc->sc_sppp); 916 917 splx(x); 918 919 return err; 920} 921 922/* Connection attempt aborted */ 923static void 924pppoe_abort_connect(struct pppoe_softc *sc) 925{ 926 printf("%s: could not establish connection\n", 927 sc->sc_sppp.pp_if.if_xname); 928 sc->sc_state = PPPOE_STATE_INITIAL; 929 memcpy(&sc->sc_dest, etherbroadcastaddr, sizeof(sc->sc_dest)); 930 931 /* notify upper layer */ 932 sc->sc_sppp.pp_down(&sc->sc_sppp); 933} 934 935/* Send a PADR packet */ 936static int 937pppoe_send_padr(struct pppoe_softc *sc) 938{ 939 struct mbuf *m0; 940 u_int8_t *p; 941 size_t len, l1; 942 943 if (sc->sc_state != PPPOE_STATE_PADR_SENT) 944 return EIO; 945 946 len = 2+2+2+2+sizeof(sc); /* service name, host unique */ 947 if (sc->sc_service_name != NULL) { /* service name tag maybe empty */ 948 l1 = strlen(sc->sc_service_name); 949 len += l1; 950 } 951 if (sc->sc_ac_cookie_len > 0) 952 len += 2+2+sc->sc_ac_cookie_len; /* AC cookie */ 953 m0 = pppoe_get_mbuf(len+PPPOE_HEADERLEN); 954 if (!m0) return ENOBUFS; 955 p = mtod(m0, u_int8_t*); 956 PPPOE_ADD_HEADER(p, PPPOE_CODE_PADR, 0, len); 957 PPPOE_ADD_16(p, PPPOE_TAG_SNAME); 958 if (sc->sc_service_name != NULL) { 959 PPPOE_ADD_16(p, l1); 960 memcpy(p, sc->sc_service_name, l1); 961 p += l1; 962 } else { 963 PPPOE_ADD_16(p, 0); 964 } 965 if (sc->sc_ac_cookie_len > 0) { 966 PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE); 967 PPPOE_ADD_16(p, sc->sc_ac_cookie_len); 968 memcpy(p, sc->sc_ac_cookie, sc->sc_ac_cookie_len); 969 p += sc->sc_ac_cookie_len; 970 } 971 PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); 972 PPPOE_ADD_16(p, sizeof(sc)); 973 memcpy(p, &sc, sizeof sc); 974 975#ifdef PPPOE_DEBUG 976 p += sizeof sc; 977 if (p - mtod(m0, u_int8_t*) != len + PPPOE_HEADERLEN) 978 panic("pppoe_send_padr: garbled output len, should be %ld, is %ld", 979 (long)(len + PPPOE_HEADERLEN), (long)(p - mtod(m0, u_int8_t*))); 980#endif 981 982 return pppoe_output(sc, m0); 983} 984 985/* send a PADT packet */ 986static int 987pppoe_send_padt(struct pppoe_softc *sc) 988{ 989 struct mbuf *m0; 990 u_int8_t *p; 991 992 if (sc->sc_state < PPPOE_STATE_SESSION) 993 return EIO; 994 995#ifdef PPPOE_DEBUG 996 printf("%s: sending PADT\n", sc->sc_sppp.pp_if.if_xname); 997#endif 998 m0 = pppoe_get_mbuf(PPPOE_HEADERLEN); 999 if (!m0) return ENOBUFS; 1000 p = mtod(m0, u_int8_t*); 1001 PPPOE_ADD_HEADER(p, PPPOE_CODE_PADT, sc->sc_session, 0); 1002 return pppoe_output(sc, m0); 1003} 1004 1005static void 1006pppoe_tls(struct sppp *sp) 1007{ 1008 struct pppoe_softc *sc = (void*)sp; 1009 if (sc->sc_state != PPPOE_STATE_INITIAL) 1010 return; 1011 pppoe_connect(sc); 1012} 1013 1014static void 1015pppoe_tlf(struct sppp *sp) 1016{ 1017 struct pppoe_softc *sc = (void*)sp; 1018 if (sc->sc_state < PPPOE_STATE_SESSION) 1019 return; 1020 /* 1021 * Do not call pppoe_disconnect here, the upper layer state 1022 * machine gets confused by this. We must return from this 1023 * function and defer disconnecting to the timeout handler. 1024 */ 1025 sc->sc_state = PPPOE_STATE_CLOSING; 1026 callout_reset(&sc->sc_timeout, hz/50, pppoe_timeout, sc); 1027} 1028 1029static void 1030pppoe_start(struct ifnet *ifp) 1031{ 1032 struct pppoe_softc *sc = (void*)ifp; 1033 struct mbuf *m; 1034 u_int8_t *p; 1035 size_t len; 1036 1037 if (sppp_isempty(ifp)) 1038 return; 1039 1040 /* are we ready to proccess data yet? */ 1041 if (sc->sc_state < PPPOE_STATE_SESSION) { 1042 sppp_flush(&sc->sc_sppp.pp_if); 1043 return; 1044 } 1045 1046 while ((m = sppp_dequeue(ifp)) != NULL) { 1047 len = m->m_pkthdr.len; 1048 M_PREPEND(m, PPPOE_HEADERLEN, M_DONTWAIT); 1049 if (m == NULL) { 1050 m_free(m); 1051 break; 1052 } 1053 p = mtod(m, u_int8_t*); 1054 PPPOE_ADD_HEADER(p, 0, sc->sc_session, len); 1055 1056#if NBPFILTER > 0 1057 if(sc->sc_sppp.pp_if.if_bpf) 1058 bpf_mtap(sc->sc_sppp.pp_if.if_bpf, m); 1059#endif 1060 1061 pppoe_output(sc, m); 1062 } 1063} 1064