This patch gets very brief PPPOE server implementation. Patch was originally written by Dinar Talypov <di...@yantel.ru> and sent to t...@openbsd.org in aug 2008. I just done some cosmetic operations and very brief critical view on it. Ok, it's ugly, but at least one can start from it.
Kernel must be compiled with 'option PPPOE_SERVER'. Works for me with this configuration: $ cat /etc/hostname.pppoe0 inet 192.168.1.1 255.255.255.255 NONE link0 \ pppoedev re0 peerproto chap \ pppoeac test \ pppoesvc test \ peername 'test' peerkey 'test' up dest 192.168.1.2 I'm not very brave with cvs/diff, sorry. Anyhow, here is the diff: Common subdirectories: /usr/aeriesrc2205/sys/net/CVS and /usr/src/sys/net/CVS diff -u /usr/aeriesrc2205/sys/net/if_pppoe.c /usr/src/sys/net/if_pppoe.c --- /usr/aeriesrc2205/sys/net/if_pppoe.c Fri Dec 26 23:51:52 2008 +++ /usr/src/sys/net/if_pppoe.c Sun May 24 22:45:07 2009 @@ -1378,6 +1378,14 @@ /* include hunique */ len += 2 + 2 + sc->sc_hunique_len; + if (sc->sc_concentrator_name != NULL){ + /* include ac_name */ + len += 2 + 2 + sizeof(sc->sc_concentrator_name); + if (sc->sc_service_name != NULL) + /* include service_name */ + len += 2 + 2 + sizeof(sc->sc_service_name); + } + m0 = pppoe_get_mbuf(len + PPPOE_HEADERLEN); if (m0 == NULL) return (ENOBUFS); @@ -1386,12 +1394,25 @@ PPPOE_ADD_HEADER(p, PPPOE_CODE_PADO, 0, len); PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE); PPPOE_ADD_16(p, sizeof(sc->sc_unique)); - memcpy(p, &sc, sizeof(sc->sc_unique)); + memcpy(p, &sc->sc_unique, sizeof(sc->sc_unique)); p += sizeof(sc->sc_unique); PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); PPPOE_ADD_16(p, sc->sc_hunique_len); memcpy(p, sc->sc_hunique, sc->sc_hunique_len); + if (sc->sc_concentrator_name != NULL){ + p += sc->sc_hunique_len; + PPPOE_ADD_16(p, PPPOE_TAG_ACNAME); + PPPOE_ADD_16(p, sizeof(sc->sc_concentrator_name)); + memcpy(p, sc->sc_concentrator_name, sizeof(sc->sc_concentrator_name)); + if (sc->sc_service_name != NULL){ + p += sizeof(sc->sc_concentrator_name); + PPPOE_ADD_16(p, PPPOE_TAG_SNAME); + PPPOE_ADD_16(p, sizeof(sc->sc_service_name)); + memcpy(p, sc->sc_service_name, sizeof(sc->sc_service_name)); + } + } + return (pppoe_output(sc, m0)); } @@ -1402,11 +1423,15 @@ struct mbuf *m0; size_t len, l1; u_int8_t *p; + struct timeval tv; if (sc->sc_state != PPPOE_STATE_PADO_SENT) return (EIO); - sc->sc_session = mono_time.tv_sec % 0xff + 1; + getmicrotime(&tv); + sc->sc_session = tv.tv_sec % 0xff + 1; + sc->sc_session_time.tv_sec = tv.tv_sec; + sc->sc_session_time.tv_usec = tv.tv_usec; /* calc length */ len = 0; @@ -1464,6 +1489,11 @@ * function and defer disconnecting to the timeout handler. */ sc->sc_state = PPPOE_STATE_CLOSING; +#ifdef PPPOE_SERVER + /* notify upper layer */ + if (sp->pp_if.if_flags & IFF_PASSIVE) + sc->sc_sppp.pp_down(&sc->sc_sppp); +#endif timeout_add(&sc->sc_timeout, hz / 50); } Only in /usr/src/sys/net: if_pppoe.c.ORIG diff -u /usr/aeriesrc2205/sys/net/if_spppsubr.c /usr/src/sys/net/if_spppsubr.c --- /usr/aeriesrc2205/sys/net/if_spppsubr.c Fri Dec 26 23:51:52 2008 +++ /usr/src/sys/net/if_spppsubr.c Sun May 24 22:57:28 2009 @@ -140,6 +140,7 @@ #define PPP_CHAP 0xc223 /* Challenge-Handshake Auth Protocol */ #define PPP_IPCP 0x8021 /* Internet Protocol Control Protocol */ #define PPP_IPV6CP 0x8057 /* IPv6 Control Protocol */ +#define PPP_CCP 0x80fd /* Compression Control Protocol */ #define CONF_REQ 1 /* PPP configure request */ #define CONF_ACK 2 /* PPP configure acknowledge */ @@ -474,7 +475,7 @@ }; - /* +/* * Exported functions, comprising our interface to the lower layer. */ @@ -559,6 +560,7 @@ goto drop; } switch (ntohs (h->protocol)) { + case PPP_CCP: default: if (sp->state[IDX_LCP] == STATE_OPENED) sppp_cp_send (sp, PPP_LCP, PROTO_REJ, @@ -1538,6 +1540,11 @@ log(LOG_DEBUG, SPP_FMT "%s send terminate-ack\n", SPP_ARGS(ifp), cp->name); sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); +#ifdef PPPOE_SERVER + sp->rst_counter[cp->protoidx] = 0; + sppp_cp_change_state(cp, sp, STATE_CLOSING); + (cp->tlf)(sp); +#endif /* PPPOE_SERVER */ break; case STATE_OPENED: sp->rst_counter[cp->protoidx] = 0; @@ -1817,6 +1824,12 @@ (cp->tls)(sp); break; case STATE_STARTING: +#ifdef PPPOE_SERVER + if (sp->pp_if.if_flags & IFF_PASSIVE){ + sppp_cp_change_state(cp, sp, STATE_STARTING); + (cp->tls)(sp); + } +#endif break; case STATE_CLOSED: sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; @@ -2116,6 +2129,11 @@ else sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); sp->pp_flags &= ~PP_NEEDAUTH; +#ifdef PPPOE_SERVER + if (sp->pp_if.if_flags & IFF_PASSIVE){ + sp->lcp.opts |= (1 << LCP_OPT_AUTH_PROTO); + } +#endif sppp_open_event(&lcp, sp); } @@ -2392,7 +2410,7 @@ break; } if (debug) - addlog("[access denied]\n"); + addlog("[access denied: No authentication]\n"); lcp.Close(sp); break; } @@ -2471,7 +2489,7 @@ * deny. */ if (debug) - addlog("[access denied]\n"); + addlog("[access denied: Auth method mismatch]\n"); lcp.Close(sp); break; } @@ -2616,7 +2634,14 @@ } if (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) { +#ifdef PPPOE_SERVER + if(sp->pp_if.if_flags & IFF_PASSIVE) + authproto = sp->myauth.proto = sp->hisauth.proto; + else + authproto = sp->hisauth.proto; +#else authproto = sp->hisauth.proto; +#endif opt[i++] = LCP_OPT_AUTH_PROTO; opt[i++] = authproto == PPP_CHAP? 5: 4; opt[i++] = authproto >> 8; @@ -3050,6 +3075,10 @@ sp->ipcp.flags |= IPCP_MYADDR_DYN; sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); } +#ifdef PPPOE_SERVER + if(sp->pp_if.if_flags & IFF_PASSIVE) + sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); +#endif if (hisaddr == 1) { /* * XXX - remove this hack! @@ -3843,6 +3872,7 @@ sppp_print_string(sp->hisauth.name, sppp_strnlen(sp->hisauth.name, AUTHNAMELEN)); addlog("\n"); + goto bad; } if (debug) { log(LOG_DEBUG, SPP_FMT "chap input(%s) " @@ -3879,7 +3909,7 @@ if (value_len != sizeof digest || bcmp(digest, value, value_len) != 0) { /* action scn, tld */ - sppp_auth_send(&chap, sp, CHAP_FAILURE, h->ident, +bad: sppp_auth_send(&chap, sp, CHAP_FAILURE, h->ident, sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 0); chap.tld(sp); Only in /usr/src/sys/net: if_spppsubr.c.ORIG -- antonvm