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