Deleted Added
full compact
5c5
< * Copyright (C) 1994 Cronyx Ltd.
---
> * Copyright (C) 1994-1996 Cronyx Engineering Ltd.
18c18
< * From: Version 1.9, Wed Oct 4 18:58:15 MSK 1995
---
> * From: Version 2.4, Thu Apr 30 17:17:21 MSD 1997
30a31
> #include <sys/md5.h>
35a37,38
> #include <machine/stdarg.h>
>
75a79,87
> *
> * Setting IFF_DEBUG will syslog the option negotiation and state
> * transitions at level kern.debug. Note: all logs consistently look
> * like
> *
> * <if-name><unit>: <proto-name> <additional info...>
> *
> * with <if-name><unit> being something like "bppp0", and <proto-name>
> * being one of "lcp", "ipcp", "cisco", "chap", "pap", etc.
81,88c93,102
< #define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */
< #define PPP_UI 0x03 /* Unnumbered Information */
< #define PPP_IP 0x0021 /* Internet Protocol */
< #define PPP_ISO 0x0023 /* ISO OSI Protocol */
< #define PPP_XNS 0x0025 /* Xerox NS Protocol */
< #define PPP_IPX 0x002b /* Novell IPX Protocol */
< #define PPP_LCP 0xc021 /* Link Control Protocol */
< #define PPP_IPCP 0x8021 /* Internet Protocol Control Protocol */
---
> #define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */
> #define PPP_UI 0x03 /* Unnumbered Information */
> #define PPP_IP 0x0021 /* Internet Protocol */
> #define PPP_ISO 0x0023 /* ISO OSI Protocol */
> #define PPP_XNS 0x0025 /* Xerox NS Protocol */
> #define PPP_IPX 0x002b /* Novell IPX Protocol */
> #define PPP_LCP 0xc021 /* Link Control Protocol */
> #define PPP_PAP 0xc023 /* Password Authentication Protocol */
> #define PPP_CHAP 0xc223 /* Challenge-Handshake Auth Protocol */
> #define PPP_IPCP 0x8021 /* Internet Protocol Control Protocol */
102,109c116,123
< #define LCP_OPT_MRU 1 /* maximum receive unit */
< #define LCP_OPT_ASYNC_MAP 2 /* async control character map */
< #define LCP_OPT_AUTH_PROTO 3 /* authentication protocol */
< #define LCP_OPT_QUAL_PROTO 4 /* quality protocol */
< #define LCP_OPT_MAGIC 5 /* magic number */
< #define LCP_OPT_RESERVED 6 /* reserved */
< #define LCP_OPT_PROTO_COMP 7 /* protocol field compression */
< #define LCP_OPT_ADDR_COMP 8 /* address/control field compression */
---
> #define LCP_OPT_MRU 1 /* maximum receive unit */
> #define LCP_OPT_ASYNC_MAP 2 /* async control character map */
> #define LCP_OPT_AUTH_PROTO 3 /* authentication protocol */
> #define LCP_OPT_QUAL_PROTO 4 /* quality protocol */
> #define LCP_OPT_MAGIC 5 /* magic number */
> #define LCP_OPT_RESERVED 6 /* reserved */
> #define LCP_OPT_PROTO_COMP 7 /* protocol field compression */
> #define LCP_OPT_ADDR_COMP 8 /* address/control field compression */
115,120c129,131
< #define CISCO_MULTICAST 0x8f /* Cisco multicast address */
< #define CISCO_UNICAST 0x0f /* Cisco unicast address */
< #define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */
< #define CISCO_ADDR_REQ 0 /* Cisco address request */
< #define CISCO_ADDR_REPLY 1 /* Cisco address reply */
< #define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */
---
> #define PAP_REQ 1 /* PAP name/password request */
> #define PAP_ACK 2 /* PAP acknowledge */
> #define PAP_NAK 3 /* PAP fail */
121a133,146
> #define CHAP_CHALLENGE 1 /* CHAP challenge request */
> #define CHAP_RESPONSE 2 /* CHAP challenge response */
> #define CHAP_SUCCESS 3 /* CHAP response ok */
> #define CHAP_FAILURE 4 /* CHAP response failed */
>
> #define CHAP_MD5 5 /* hash algorithm - MD5 */
>
> #define CISCO_MULTICAST 0x8f /* Cisco multicast address */
> #define CISCO_UNICAST 0x0f /* Cisco unicast address */
> #define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */
> #define CISCO_ADDR_REQ 0 /* Cisco address request */
> #define CISCO_ADDR_REPLY 1 /* Cisco address reply */
> #define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */
>
190a216
> static struct callout_handle keepalive_ch;
196a223,224
> *
> * XXX is this really still necessary? - joerg -
209c237
< static int sppp_output(struct ifnet *ifp, struct mbuf *m,
---
> static int sppp_output(struct ifnet *ifp, struct mbuf *m,
221a250,252
> static void sppp_auth_send(const struct cp *cp,
> struct sppp *sp, u_char type, u_char id,
> ...);
228a260,261
> static void sppp_null(struct sppp *sp);
>
243c276,277
< static void sppp_lcp_check(struct sppp *sp);
---
> static void sppp_lcp_check_and_close(struct sppp *sp);
> static int sppp_ncp_check(struct sppp *sp);
259a294,313
> static void sppp_pap_input(struct sppp *sp, struct mbuf *m);
> static void sppp_pap_init(struct sppp *sp);
> static void sppp_pap_open(struct sppp *sp);
> static void sppp_pap_close(struct sppp *sp);
> static void sppp_pap_TO(void *sp);
> static void sppp_pap_my_TO(void *sp);
> static void sppp_pap_tlu(struct sppp *sp);
> static void sppp_pap_tld(struct sppp *sp);
> static void sppp_pap_scr(struct sppp *sp);
>
> static void sppp_chap_input(struct sppp *sp, struct mbuf *m);
> static void sppp_chap_init(struct sppp *sp);
> static void sppp_chap_open(struct sppp *sp);
> static void sppp_chap_close(struct sppp *sp);
> static void sppp_chap_TO(void *sp);
> static void sppp_chap_tlu(struct sppp *sp);
> static void sppp_chap_tld(struct sppp *sp);
> static void sppp_chap_scr(struct sppp *sp);
>
> static const char *sppp_auth_type_name(u_short proto, u_char type);
261c315
< static const char *sppp_lcp_opt_name(u_char opt);
---
> static const char *sppp_dotted_quad(u_long addr);
263c317
< static const char *sppp_state_name(int state);
---
> static const char *sppp_lcp_opt_name(u_char opt);
266c320,324
<
---
> static const char *sppp_state_name(int state);
> static int sppp_params(struct sppp *sp, int cmd, void *data);
> static int sppp_strnlen(u_char *p, int max);
> static void sppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst,
> u_long *srcmask);
268c326,328
< static struct callout_handle keepalive_ch;
---
> static void sppp_phase_network(struct sppp *sp);
> static void sppp_print_bytes(const u_char *p, u_short len);
> static void sppp_print_string(const char *p, u_short len);
270,271d329
<
< static void sppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst);
274,275d331
< static void sppp_print_bytes(u_char *p, u_short len);
<
292a349,364
> const struct cp pap = {
> PPP_PAP, IDX_PAP, CP_AUTH, "pap",
> sppp_null, sppp_null, sppp_pap_open, sppp_pap_close,
> sppp_pap_TO, 0, 0, 0,
> sppp_pap_tlu, sppp_pap_tld, sppp_null, sppp_null,
> sppp_pap_scr
> };
>
> const struct cp chap = {
> PPP_CHAP, IDX_CHAP, CP_AUTH, "chap",
> sppp_null, sppp_null, sppp_chap_open, sppp_chap_close,
> sppp_chap_TO, 0, 0, 0,
> sppp_chap_tlu, sppp_chap_tld, sppp_null, sppp_null,
> sppp_chap_scr
> };
>
295a368,369
> &pap, /* IDX_PAP */
> &chap, /* IDX_CHAP */
364c438
< sppp_cp_input(&lcp, (struct sppp*)ifp, m);
---
> sppp_cp_input(&lcp, sp, m);
366a441,450
> case PPP_PAP:
> if (sp->pp_phase >= PHASE_AUTHENTICATE)
> sppp_pap_input(sp, m);
> m_freem (m);
> return;
> case PPP_CHAP:
> if (sp->pp_phase >= PHASE_AUTHENTICATE)
> sppp_chap_input(sp, m);
> m_freem (m);
> return;
370c454
< sppp_cp_input(&ipcp, (struct sppp*) ifp, m);
---
> sppp_cp_input(&ipcp, sp, m);
631c715
< keepalive_ch = timeout (sppp_keepalive, 0, hz * 10);
---
> keepalive_ch = timeout(sppp_keepalive, 0, hz * 10);
650a735,736
> sppp_pap_init(sp);
> sppp_chap_init(sp);
653c739
< void
---
> void
668c754
< untimeout (sppp_keepalive, 0, keepalive_ch);
---
> untimeout(sppp_keepalive, 0, keepalive_ch);
671a758
> untimeout(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch);
715,716c802,803
< * Process only the control protocol queue until we are in
< * network phase.
---
> * Process only the control protocol queue until we have at
> * least one NCP open.
718,725d804
< * XXX Network phase itself is still not a sufficient test, we
< * normally should keep a separate queue for each supported
< * protocol family, and only serve these queues as the
< * respective NCPs were opened. The simplistic logic used
< * here might cause some loss of network traffic while the
< * NCPs are being negotiated, in particular if the NCPs take a
< * long time to negotiate.
< *
730,731c809
< (sp->pp_phase == PHASE_NETWORK ||
< (sp->pp_flags & PP_CISCO) != 0)) {
---
> (sppp_ncp_check(sp) || (sp->pp_flags & PP_CISCO) != 0)) {
740a819,840
> * Pick the next packet, do not remove it from the queue.
> */
> struct mbuf *
> sppp_pick(struct ifnet *ifp)
> {
> struct sppp *sp = (struct sppp*)ifp;
> struct mbuf *m;
> int s;
>
> s= splimp ();
>
> m = sp->pp_cpq.ifq_head;
> if (m == NULL &&
> (sp->pp_phase == PHASE_NETWORK ||
> (sp->pp_flags & PP_CISCO) != 0))
> if ((m = sp->pp_fastq.ifq_head) == NULL)
> m = sp->pp_if.if_snd.ifq_head;
> splx (s);
> return (m);
> }
>
> /*
748c848
< int s, going_up, going_down, newmode;
---
> int s, rv, going_up, going_down, newmode;
750a851
> rv = 0;
816a918,922
> case SIOCGIFGENERIC:
> case SIOCSIFGENERIC:
> rv = sppp_params(sp, cmd, data);
> break;
>
818,819c924
< splx(s);
< return (ENOTTY);
---
> rv = ENOTTY;
822c927
< return (0);
---
> return rv;
833c938
< static void
---
> static void
838c943
< struct ifaddr *ifa;
---
> u_long me, mymask;
843c948
< "%s%d: invalid cisco packet length: %d bytes\n",
---
> "%s%d: cisco invalid packet length: %d bytes\n",
858c963
< addlog("%s%d: unknown cisco packet type: 0x%lx\n",
---
> addlog("%s%d: cisco unknown packet type: 0x%lx\n",
885c990
< sp->pp_loopcnt = 0;
---
> sp->pp_loopcnt = 0;
888c993
< ifp->if_flags |= IFF_UP;
---
> if_up(ifp);
893,905c998,1000
< for (ifa=ifp->if_addrhead.tqh_first; ifa;
< ifa=ifa->ifa_link.tqe_next)
< if (ifa->ifa_addr->sa_family == AF_INET)
< break;
< if (! ifa) {
< if (debug)
< addlog("%s%d: unknown address for cisco request\n",
< ifp->if_name, ifp->if_unit);
< return;
< }
< sppp_cisco_send (sp, CISCO_ADDR_REPLY,
< ntohl (((struct sockaddr_in*)ifa->ifa_addr)->sin_addr.s_addr),
< ntohl (((struct sockaddr_in*)ifa->ifa_netmask)->sin_addr.s_addr));
---
> sppp_get_ip_addrs(sp, &me, 0, &mymask);
> if (me != 0L)
> sppp_cisco_send(sp, CISCO_ADDR_REPLY, me, mymask);
1047a1143
> p = (u_char *)(h + 1);
1057a1154,1163
> /* handle states where RCR doesn't get a SCA/SCN */
> switch (sp->state[cp->protoidx]) {
> case STATE_CLOSING:
> case STATE_STOPPING:
> return;
> case STATE_CLOSED:
> sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident,
> 0, 0);
> return;
> }
1069,1071d1174
< case STATE_CLOSING:
< case STATE_STOPPING:
< break;
1078,1081d1180
< case STATE_CLOSED:
< sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident,
< 0, 0);
< break;
1133c1232
< addlog("%s%d: %s tlu\n",
---
> log(LOG_DEBUG, "%s%d: %s tlu\n",
1254a1354,1358
> log(LOG_INFO,
> "%s%d: %s: ignoring RXJ (%s) for proto 0x%x, "
> "danger will robinson\n",
> ifp->if_name, ifp->if_unit, cp->name,
> sppp_cp_type_name(h->type), ntohs(*((u_short *)p)));
1588,1589c1692
< callout_handle_init(&sp->ch[IDX_LCP]);
<
---
>
1600a1704
> callout_handle_init(&sp->ch[IDX_LCP]);
1609,1610c1713,1715
< * If this interface is passive or dial-on-demand, it means
< * we've got in incoming call. Activate the interface.
---
> * If this interface is passive or dial-on-demand, and we are
> * still in Initial state, it means we've got an incoming
> * call. Activate the interface.
1615,1616c1720
< "%s%d: Up event (incoming call)\n",
< ifp->if_name, ifp->if_unit);
---
> "%s%d: Up event", ifp->if_name, ifp->if_unit);
1618c1722,1728
< lcp.Open(sp);
---
> if (sp->state[IDX_LCP] == STATE_INITIAL) {
> if (debug)
> addlog("(incoming call)\n");
> sp->pp_flags |= PP_CALLIN;
> lcp.Open(sp);
> } else if (debug)
> addlog("\n");
1649c1759,1761
< lcp.Close(sp);
---
> sp->pp_flags &= ~PP_CALLIN;
> if (sp->state[IDX_LCP] != STATE_INITIAL)
> lcp.Close(sp);
1655a1768,1775
> /*
> * If we are authenticator, negotiate LCP_AUTH
> */
> if (sp->hisauth.proto != 0)
> sp->lcp.opts |= (1 << LCP_OPT_AUTH_PROTO);
> else
> sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO);
> sp->pp_flags &= ~PP_NEEDAUTH;
1683a1804
> u_short authproto;
1717a1839,1863
> case LCP_OPT_AUTH_PROTO:
> if (len < 4) {
> if (debug)
> addlog("[invalid] ");
> break;
> }
> authproto = (p[2] << 8) + p[3];
> if (authproto == PPP_CHAP && p[1] != 5) {
> if (debug)
> addlog("[invalid chap len] ");
> break;
> }
> if (sp->myauth.proto == 0) {
> /* we are not configured to do auth */
> if (debug)
> addlog("[not configured] ");
> break;
> }
> /*
> * Remote want us to authenticate, remember this,
> * so we stay in PHASE_AUTHENTICATE after LCP got
> * up.
> */
> sp->pp_flags |= PP_NEEDAUTH;
> continue;
1764c1910
< printf ("\n%s%d: loopback\n",
---
> printf ("%s%d: loopback\n",
1811a1958,1977
>
> case LCP_OPT_AUTH_PROTO:
> authproto = (p[2] << 8) + p[3];
> if (sp->myauth.proto != authproto) {
> /* not agreed, nak */
> if (debug)
> addlog("[mine %s != his %s] ",
> sppp_proto_name(sp->hisauth.proto),
> sppp_proto_name(authproto));
> p[2] = sp->myauth.proto >> 8;
> p[3] = sp->myauth.proto;
> break;
> }
> if (authproto == PPP_CHAP && p[4] != CHAP_MD5) {
> if (debug)
> addlog("[chap not MD5] ");
> p[4] == CHAP_MD5;
> break;
> }
> continue;
1880a2047,2064
> case LCP_OPT_AUTH_PROTO:
> /*
> * Peer doesn't want to authenticate himself,
> * deny unless this is a dialout call, and
> * AUTHFLAG_NOCALLOUT is set.
> */
> if ((sp->pp_flags & PP_CALLIN) == 0 &&
> (sp->hisauth.flags & AUTHFLAG_NOCALLOUT) != 0) {
> if (debug)
> addlog("[don't insist on auth "
> "for callout]");
> sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO);
> break;
> }
> if (debug)
> addlog("[access denied]\n");
> lcp.Close(sp);
> break;
1951a2136,2144
> case LCP_OPT_AUTH_PROTO:
> /*
> * Peer doesn't like our authentication method,
> * deny.
> */
> if (debug)
> addlog("[access denied]\n");
> lcp.Close(sp);
> break;
1979c2172,2173
< if (/* require authentication XXX */ 0)
---
> if ((sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0 ||
> (sp->pp_flags & PP_NEEDAUTH) != 0)
1987,1991c2181,2192
< if (sp->pp_phase == PHASE_AUTHENTICATE) {
< for (i = 0; i < IDX_COUNT; i++)
< if ((cps[i])->flags & CP_AUTH)
< (cps[i])->Open(sp);
< } else {
---
> /*
> * Open all authentication protocols. This is even required
> * if we already proceeded to network phase, since it might be
> * that remote wants us to authenticate, so we might have to
> * send a PAP request. Undesired authentication protocols
> * don't do anything when they get an Open event.
> */
> for (i = 0; i < IDX_COUNT; i++)
> if ((cps[i])->flags & CP_AUTH)
> (cps[i])->Open(sp);
>
> if (sp->pp_phase == PHASE_NETWORK) {
2005c2206
< sppp_lcp_check(sp);
---
> sppp_lcp_check_and_close(sp);
2065c2266
< char opt[6 /* magicnum */ + 4 /* mru */];
---
> char opt[6 /* magicnum */ + 4 /* mru */ + 5 /* chap */];
2066a2268
> u_short authproto;
2085a2288,2297
> if (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) {
> authproto = sp->hisauth.proto;
> opt[i++] = LCP_OPT_AUTH_PROTO;
> opt[i++] = authproto == PPP_CHAP? 5: 4;
> opt[i++] = authproto >> 8;
> opt[i++] = authproto;
> if (authproto == PPP_CHAP)
> opt[i++] = CHAP_MD5;
> }
>
2091,2092c2303
< * Re-check the open NCPs and see if we should terminate the link.
< * Called by the NCPs during their tlf action handling.
---
> * Check the open NCPs, return true if at least one NCP is open.
2094,2095c2305,2306
< static void
< sppp_lcp_check(struct sppp *sp)
---
> static int
> sppp_ncp_check(struct sppp *sp)
2101c2312,2330
< return;
---
> return 1;
> return 0;
> }
>
> /*
> * Re-check the open NCPs and see if we should terminate the link.
> * Called by the NCPs during their tlf action handling.
> */
> static void
> sppp_lcp_check_and_close(struct sppp *sp)
> {
>
> if (sp->pp_phase < PHASE_NETWORK)
> /* don't bother, we are already going down */
> return;
>
> if (sppp_ncp_check(sp))
> return;
>
2140c2369
< sppp_get_ip_addrs(sp, &myaddr, &hisaddr);
---
> sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0);
2254c2483
< sppp_get_ip_addrs(sp, 0, &hisaddr);
---
> sppp_get_ip_addrs(sp, 0, &hisaddr, 0);
2256c2485,2486
< addlog("%s%d: ipcp parse opt values: ", ifp->if_name, ifp->if_unit);
---
> log(LOG_DEBUG, "%s%d: ipcp parse opt values: ",
> ifp->if_name, ifp->if_unit);
2277c2507,2508
< addlog("0x%x [ack] ", hisaddr);
---
> addlog("%s [ack] ",
> sppp_dotted_quad(hisaddr));
2293,2294c2524,2525
< addlog("0x%x [not agreed] ",
< desiredaddr);
---
> addlog("%s [not agreed] ",
> sppp_dotted_quad(desiredaddr));
2428c2659,2660
< addlog("[wantaddr 0x%x] ", wantaddr);
---
> addlog("[wantaddr %s] ",
> sppp_dotted_quad(wantaddr));
2479c2711
< sppp_lcp_check(sp);
---
> sppp_lcp_check_and_close(sp);
2501c2733
< sppp_get_ip_addrs(sp, &ouraddr, 0);
---
> sppp_get_ip_addrs(sp, &ouraddr, 0, 0);
2515a2748,3539
> *--------------------------------------------------------------------------*
> * *
> * The CHAP implementation. *
> * *
> *--------------------------------------------------------------------------*
> */
>
> /*
> * The authentication protocols don't employ a full-fledged state machine as
> * the control protocols do, since they do have Open and Close events, but
> * not Up and Down, nor are they explicitly terminated. Also, use of the
> * authentication protocols may be different in both directions (this makes
> * sense, think of a machine that never accepts incoming calls but only
> * calls out, it doesn't require the called party to authenticate itself).
> *
> * Our state machine for the local authentication protocol (we are requesting
> * the peer to authenticate) looks like:
> *
> * RCA-
> * +--------------------------------------------+
> * V scn,tld|
> * +--------+ Close +---------+ RCA+
> * | |<----------------------------------| |------+
> * +--->| Closed | TO* | Opened | sca |
> * | | |-----+ +-------| |<-----+
> * | +--------+ irc | | +---------+
> * | ^ | | ^
> * | | | | |
> * | | | | |
> * | TO-| | | |
> * | |tld TO+ V | |
> * | | +------->+ | |
> * | | | | | |
> * | +--------+ V | |
> * | | |<----+<--------------------+ |
> * | | Req- | scr |
> * | | Sent | |
> * | | | |
> * | +--------+ |
> * | RCA- | | RCA+ |
> * +------+ +------------------------------------------+
> * scn,tld sca,irc,ict,tlu
> *
> *
> * with:
> *
> * Open: LCP reached authentication phase
> * Close: LCP reached terminate phase
> *
> * RCA+: received reply (pap-req, chap-response), acceptable
> * RCN: received reply (pap-req, chap-response), not acceptable
> * TO+: timeout with restart counter >= 0
> * TO-: timeout with restart counter < 0
> * TO*: reschedule timeout for CHAP
> *
> * scr: send request packet (none for PAP, chap-challenge)
> * sca: send ack packet (pap-ack, chap-success)
> * scn: send nak packet (pap-nak, chap-failure)
> * ict: initialize re-challenge timer (CHAP only)
> *
> * tlu: this-layer-up, LCP reaches network phase
> * tld: this-layer-down, LCP enters terminate phase
> *
> * Note that in CHAP mode, after sending a new challenge, while the state
> * automaton falls back into Req-Sent state, it doesn't signal a tld
> * event to LCP, so LCP remains in network phase. Only after not getting
> * any response (or after getting an unacceptable response), CHAP closes,
> * causing LCP to enter terminate phase.
> *
> * With PAP, there is no initial request that can be sent. The peer is
> * expected to send one based on the successful negotiation of PAP as
> * the authentication protocol during the LCP option negotiation.
> *
> * Incoming authentication protocol requests (remote requests
> * authentication, we are peer) don't employ a state machine at all,
> * they are simply answered. Some peers [Ascend P50 firmware rev
> * 4.50] react allergically when sending IPCP requests while they are
> * still in authentication phase (thereby violating the standard that
> * demands that these NCP packets are to be discarded), so we keep
> * track of the peer demanding us to authenticate, and only proceed to
> * phase network once we've seen a positive acknowledge for the
> * authentication.
> */
>
> /*
> * Handle incoming CHAP packets.
> */
> void
> sppp_chap_input(struct sppp *sp, struct mbuf *m)
> {
> STDDCL;
> struct lcp_header *h;
> int len, x;
> u_char *value, *name, digest[AUTHKEYLEN], dsize;
> int value_len, name_len;
> MD5_CTX ctx;
>
> len = m->m_pkthdr.len;
> if (len < 4) {
> if (debug)
> log(LOG_DEBUG,
> "%s%d: chap invalid packet length: %d bytes\n",
> ifp->if_name, ifp->if_unit, len);
> return;
> }
> h = mtod (m, struct lcp_header*);
> if (len > ntohs (h->len))
> len = ntohs (h->len);
>
> switch (h->type) {
> /* challenge, failure and success are his authproto */
> case CHAP_CHALLENGE:
> value = 1 + (u_char*)(h+1);
> value_len = value[-1];
> name = value + value_len;
> name_len = len - value_len - 5;
> if (name_len < 0) {
> if (debug) {
> log(LOG_DEBUG,
> "%s%d: chap corrupted challenge "
> "<%s id=0x%x len=%d",
> ifp->if_name, ifp->if_unit,
> sppp_auth_type_name(PPP_CHAP, h->type),
> h->ident, ntohs(h->len));
> if (len > 4)
> sppp_print_bytes((u_char*) (h+1), len-4);
> addlog(">\n");
> }
> break;
> }
> if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN)
> || bcmp(name, sp->hisauth.name, name_len) != 0) {
> log(LOG_INFO, "%s%d: chap challenge, his name ");
> sppp_print_string(name, name_len);
> addlog(" != expected ");
> sppp_print_string(sp->hisauth.name,
> sppp_strnlen(sp->hisauth.name, AUTHNAMELEN));
> addlog("\n");
> }
>
> if (debug) {
> log(LOG_DEBUG,
> "%s%d: chap input <%s id=0x%x len=%d name=",
> ifp->if_name, ifp->if_unit,
> sppp_auth_type_name(PPP_CHAP, h->type), h->ident,
> ntohs(h->len));
> sppp_print_string((char*) name, name_len);
> addlog(" value-size=%d value=", value_len);
> sppp_print_bytes(value, value_len);
> addlog(">\n");
> }
>
> /* Compute reply value. */
> MD5Init(&ctx);
> MD5Update(&ctx, &h->ident, 1);
> MD5Update(&ctx, sp->myauth.secret,
> sppp_strnlen(sp->myauth.secret, AUTHKEYLEN));
> MD5Update(&ctx, value, value_len);
> MD5Final(digest, &ctx);
> dsize = sizeof digest;
>
> sppp_auth_send(&chap, sp, CHAP_RESPONSE, h->ident,
> sizeof dsize, (const char *)&dsize,
> sizeof digest, digest,
> sppp_strnlen(sp->myauth.name, AUTHNAMELEN),
> sp->myauth.name,
> 0);
> break;
>
> case CHAP_SUCCESS:
> if (debug) {
> log(LOG_DEBUG, "%s%d: chap success",
> ifp->if_name, ifp->if_unit);
> if (len > 4) {
> addlog(": ");
> sppp_print_string((char*)(h + 1), len - 4);
> }
> addlog("\n");
> }
> x = splimp();
> sp->pp_flags &= ~PP_NEEDAUTH;
> if (sp->myauth.proto == PPP_CHAP &&
> (sp->lcp.protos & (1 << IDX_CHAP)) == 0) {
> /*
> * We are authenticator for CHAP but didn't
> * complete yet. Leave it to tlu to proceed
> * to network phase.
> */
> splx(x);
> break;
> }
> splx(x);
> sppp_phase_network(sp);
> break;
>
> case CHAP_FAILURE:
> if (debug) {
> log(LOG_INFO, "%s%d: chap failure",
> ifp->if_name, ifp->if_unit);
> if (len > 4) {
> addlog(": ");
> sppp_print_string((char*)(h + 1), len - 4);
> }
> addlog("\n");
> } else
> log(LOG_INFO, "%s%d: chap failure\n",
> ifp->if_name, ifp->if_unit);
> /* await LCP shutdown by authenticator */
> break;
>
> /* response is my authproto */
> case CHAP_RESPONSE:
> value = 1 + (u_char*)(h+1);
> value_len = value[-1];
> name = value + value_len;
> name_len = len - value_len - 5;
> if (name_len < 0) {
> if (debug) {
> log(LOG_DEBUG,
> "%s%d: chap corrupted response "
> "<%s id=0x%x len=%d",
> ifp->if_name, ifp->if_unit,
> sppp_auth_type_name(PPP_CHAP, h->type),
> h->ident, ntohs(h->len));
> if (len > 4)
> sppp_print_bytes((u_char*)(h+1), len-4);
> addlog(">\n");
> }
> break;
> }
> if (h->ident != sp->confid[IDX_CHAP]) {
> if (debug)
> log(LOG_DEBUG,
> "%s%d: chap dropping response for old ID "
> "(got %d, expected %d)\n",
> h->ident, sp->confid[IDX_CHAP]);
> break;
> }
> if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN)
> || bcmp(name, sp->hisauth.name, name_len) != 0) {
> log(LOG_INFO, "%s%d: chap response, his name ",
> ifp->if_name, ifp->if_unit);
> sppp_print_string(name, name_len);
> addlog(" != expected ");
> sppp_print_string(sp->hisauth.name,
> sppp_strnlen(sp->hisauth.name, AUTHNAMELEN));
> addlog("\n");
> }
> if (debug) {
> log(LOG_DEBUG, "%s%d: chap input(%s) "
> "<%s id=0x%x len=%d name=",
> ifp->if_name, ifp->if_unit,
> sppp_state_name(sp->state[IDX_CHAP]),
> sppp_auth_type_name(PPP_CHAP, h->type),
> h->ident, ntohs (h->len));
> sppp_print_string((char*)name, name_len);
> addlog(" value-size=%d value=", value_len);
> sppp_print_bytes(value, value_len);
> addlog(">\n");
> }
> if (value_len != AUTHKEYLEN) {
> if (debug)
> log(LOG_DEBUG,
> "%s%d: chap bad hash value length: "
> "%d bytes, should be %d\n",
> ifp->if_name, ifp->if_unit, value_len,
> AUTHKEYLEN);
> break;
> }
>
> MD5Init(&ctx);
> MD5Update(&ctx, &h->ident, 1);
> MD5Update(&ctx, sp->hisauth.secret,
> sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN));
> MD5Update(&ctx, sp->myauth.challenge, AUTHKEYLEN);
> MD5Final(digest, &ctx);
>
> #define FAILMSG "Failed..."
> #define SUCCMSG "Welcome!"
>
> if (value_len != sizeof digest ||
> bcmp(digest, value, value_len) != 0) {
> /* action scn, tld */
> sppp_auth_send(&chap, sp, CHAP_FAILURE, h->ident,
> sizeof(FAILMSG) - 1, (u_char *)FAILMSG,
> 0);
> chap.tld(sp);
> break;
> }
> /* action sca, perhaps tlu */
> if (sp->state[IDX_CHAP] == STATE_REQ_SENT ||
> sp->state[IDX_CHAP] == STATE_OPENED)
> sppp_auth_send(&chap, sp, CHAP_SUCCESS, h->ident,
> sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG,
> 0);
> if (sp->state[IDX_CHAP] == STATE_REQ_SENT) {
> sppp_cp_change_state(&chap, sp, STATE_OPENED);
> chap.tlu(sp);
> }
> break;
>
> default:
> /* Unknown CHAP packet type -- ignore. */
> if (debug) {
> log(LOG_DEBUG, "%s%d: chap unknown input(%s) "
> "<0x%x id=0x%xh len=%d",
> ifp->if_name, ifp->if_unit,
> sppp_state_name(sp->state[IDX_CHAP]),
> h->type, h->ident, ntohs(h->len));
> if (len > 4)
> sppp_print_bytes((u_char*)(h+1), len-4);
> addlog(">\n");
> }
> break;
>
> }
> }
>
> static void
> sppp_chap_init(struct sppp *sp)
> {
> /* Chap doesn't have STATE_INITIAL at all. */
> sp->state[IDX_CHAP] = STATE_CLOSED;
> sp->fail_counter[IDX_CHAP] = 0;
> callout_handle_init(&sp->ch[IDX_CHAP]);
> }
>
> static void
> sppp_chap_open(struct sppp *sp)
> {
> if (sp->myauth.proto == PPP_CHAP &&
> (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) {
> /* we are authenticator for CHAP, start it */
> chap.scr(sp);
> sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure;
> sppp_cp_change_state(&chap, sp, STATE_REQ_SENT);
> }
> /* nothing to be done if we are peer, await a challenge */
> }
>
> static void
> sppp_chap_close(struct sppp *sp)
> {
> if (sp->state[IDX_CHAP] != STATE_CLOSED)
> sppp_cp_change_state(&chap, sp, STATE_CLOSED);
> }
>
> static void
> sppp_chap_TO(void *cookie)
> {
> struct sppp *sp = (struct sppp *)cookie;
> STDDCL;
> int s;
>
> s = splimp();
> if (debug)
> log(LOG_DEBUG, "%s%d: chap TO(%s) rst_counter = %d\n",
> ifp->if_name, ifp->if_unit,
> sppp_state_name(sp->state[IDX_CHAP]),
> sp->rst_counter[IDX_CHAP]);
>
> if (--sp->rst_counter[IDX_CHAP] < 0)
> /* TO- event */
> switch (sp->state[IDX_CHAP]) {
> case STATE_REQ_SENT:
> chap.tld(sp);
> sppp_cp_change_state(&chap, sp, STATE_CLOSED);
> break;
> }
> else
> /* TO+ (or TO*) event */
> switch (sp->state[IDX_CHAP]) {
> case STATE_OPENED:
> /* TO* event */
> sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure;
> /* fall through */
> case STATE_REQ_SENT:
> chap.scr(sp);
> /* sppp_cp_change_state() will restart the timer */
> sppp_cp_change_state(&chap, sp, STATE_REQ_SENT);
> break;
> }
>
> splx(s);
> }
>
> static void
> sppp_chap_tlu(struct sppp *sp)
> {
> STDDCL;
> int i, x;
>
> sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure;
>
> /*
> * Some broken CHAP implementations (Conware CoNet, firmware
> * 4.0.?) don't want to re-authenticate their CHAP once the
> * initial challenge-response exchange has taken place.
> * Provide for an option to avoid rechallenges.
> */
> if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) {
> /*
> * Compute the re-challenge timeout. This will yield
> * a number between 300 and 810 seconds.
> */
> i = 300 + ((unsigned)(random() & 0xff00) >> 7);
>
> sp->ch[IDX_CHAP] = timeout(chap.TO, (void *)sp, i * hz);
> }
>
> if (debug) {
> log(LOG_DEBUG,
> "%s%d: chap %s, ",
> ifp->if_name, ifp->if_unit,
> sp->pp_phase == PHASE_NETWORK? "reconfirmed": "tlu");
> if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0)
> addlog("next re-challenge in %d seconds\n", i);
> else
> addlog("re-challenging supressed\n");
> }
>
> x = splimp();
> /* indicate to LCP that we need to be closed down */
> sp->lcp.protos |= (1 << IDX_CHAP);
>
> if (sp->pp_flags & PP_NEEDAUTH) {
> /*
> * Remote is authenticator, but his auth proto didn't
> * complete yet. Defer the transition to network
> * phase.
> */
> splx(x);
> return;
> }
> splx(x);
>
> /*
> * If we are already in phase network, we are done here. This
> * is the case if this is a dummy tlu event after a re-challenge.
> */
> if (sp->pp_phase != PHASE_NETWORK)
> sppp_phase_network(sp);
> }
>
> static void
> sppp_chap_tld(struct sppp *sp)
> {
> STDDCL;
>
> if (debug)
> log(LOG_DEBUG, "%s%d: chap tld\n", ifp->if_name, ifp->if_unit);
> untimeout(chap.TO, (void *)sp, sp->ch[IDX_CHAP]);
> sp->lcp.protos &= ~(1 << IDX_CHAP);
>
> lcp.Close(sp);
> }
>
> static void
> sppp_chap_scr(struct sppp *sp)
> {
> struct timeval tv;
> u_long *ch, seed;
> u_char clen;
>
> /* Compute random challenge. */
> ch = (u_long *)sp->myauth.challenge;
> microtime(&tv);
> seed = tv.tv_sec ^ tv.tv_usec;
> ch[0] = seed ^ random();
> ch[1] = seed ^ random();
> ch[2] = seed ^ random();
> ch[3] = seed ^ random();
> clen = AUTHKEYLEN;
>
> sp->confid[IDX_CHAP] = ++sp->pp_seq;
>
> sppp_auth_send(&chap, sp, CHAP_CHALLENGE, sp->confid[IDX_CHAP],
> sizeof clen, (const char *)&clen,
> AUTHKEYLEN, sp->myauth.challenge,
> sppp_strnlen(sp->myauth.name, AUTHNAMELEN),
> sp->myauth.name,
> 0);
> }
> /*
> *--------------------------------------------------------------------------*
> * *
> * The PAP implementation. *
> * *
> *--------------------------------------------------------------------------*
> */
> /*
> * For PAP, we need to keep a little state also if we are the peer, not the
> * authenticator. This is since we don't get a request to authenticate, but
> * have to repeatedly authenticate ourself until we got a response (or the
> * retry counter is expired).
> */
>
> /*
> * Handle incoming PAP packets. */
> static void
> sppp_pap_input(struct sppp *sp, struct mbuf *m)
> {
> STDDCL;
> struct lcp_header *h;
> int len, x;
> u_char *name, *passwd, mlen;
> int name_len, passwd_len;
>
> len = m->m_pkthdr.len;
> if (len < 5) {
> if (debug)
> log(LOG_DEBUG,
> "%s%d: pap invalid packet length: %d bytes\n",
> ifp->if_name, ifp->if_unit, len);
> return;
> }
> h = mtod (m, struct lcp_header*);
> if (len > ntohs (h->len))
> len = ntohs (h->len);
> switch (h->type) {
> /* PAP request is my authproto */
> case PAP_REQ:
> name = 1 + (u_char*)(h+1);
> name_len = name[-1];
> passwd = name + name_len + 1;
> if (name_len > len - 6 ||
> (passwd_len = passwd[-1]) > len - 6 - name_len) {
> if (debug) {
> log(LOG_DEBUG, "%s%d: pap corrupted input "
> "<%s id=0x%x len=%d",
> ifp->if_name, ifp->if_unit,
> sppp_auth_type_name(PPP_PAP, h->type),
> h->ident, ntohs(h->len));
> if (len > 4)
> sppp_print_bytes((u_char*)(h+1), len-4);
> addlog(">\n");
> }
> break;
> }
> if (debug) {
> log(LOG_DEBUG, "%s%d: pap input(%s) "
> "<%s id=0x%x len=%d name=",
> ifp->if_name, ifp->if_unit,
> sppp_state_name(sp->state[IDX_PAP]),
> sppp_auth_type_name(PPP_PAP, h->type),
> h->ident, ntohs(h->len));
> sppp_print_string((char*)name, name_len);
> addlog(" passwd=");
> sppp_print_string((char*)passwd, passwd_len);
> addlog(">\n");
> }
> if (name_len > AUTHNAMELEN ||
> passwd_len > AUTHKEYLEN ||
> bcmp(name, sp->hisauth.name, name_len) != 0 ||
> bcmp(passwd, sp->hisauth.secret, passwd_len) != 0) {
> /* action scn, tld */
> mlen = sizeof(FAILMSG) - 1;
> sppp_auth_send(&pap, sp, PAP_NAK, h->ident,
> sizeof mlen, (const char *)&mlen,
> sizeof(FAILMSG) - 1, (u_char *)FAILMSG,
> 0);
> pap.tld(sp);
> break;
> }
> /* action sca, perhaps tlu */
> if (sp->state[IDX_PAP] == STATE_REQ_SENT ||
> sp->state[IDX_PAP] == STATE_OPENED) {
> mlen = sizeof(SUCCMSG) - 1;
> sppp_auth_send(&pap, sp, PAP_ACK, h->ident,
> sizeof mlen, (const char *)&mlen,
> sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG,
> 0);
> }
> if (sp->state[IDX_PAP] == STATE_REQ_SENT) {
> sppp_cp_change_state(&pap, sp, STATE_OPENED);
> pap.tlu(sp);
> }
> break;
>
> /* ack and nak are his authproto */
> case PAP_ACK:
> untimeout(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch);
> if (debug) {
> log(LOG_DEBUG, "%s%d: pap success",
> ifp->if_name, ifp->if_unit);
> name_len = *((char *)h);
> if (len > 5 && name_len) {
> addlog(": ");
> sppp_print_string((char*)(h+1), name_len);
> }
> addlog("\n");
> }
> x = splimp();
> sp->pp_flags &= ~PP_NEEDAUTH;
> if (sp->myauth.proto == PPP_PAP &&
> (sp->lcp.protos & (1 << IDX_PAP)) == 0) {
> /*
> * We are authenticator for PAP but didn't
> * complete yet. Leave it to tlu to proceed
> * to network phase.
> */
> splx(x);
> break;
> }
> splx(x);
> sppp_phase_network(sp);
> break;
>
> case PAP_NAK:
> untimeout(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch);
> if (debug) {
> log(LOG_INFO, "%s%d: pap failure",
> ifp->if_name, ifp->if_unit);
> name_len = *((char *)h);
> if (len > 5 && name_len) {
> addlog(": ");
> sppp_print_string((char*)(h+1), name_len);
> }
> addlog("\n");
> } else
> log(LOG_INFO, "%s%d: pap failure\n",
> ifp->if_name, ifp->if_unit);
> /* await LCP shutdown by authenticator */
> break;
>
> default:
> /* Unknown PAP packet type -- ignore. */
> if (debug) {
> log(LOG_DEBUG, "%s%d: pap corrupted input "
> "<0x%x id=0x%x len=%d",
> ifp->if_name, ifp->if_unit,
> h->type, h->ident, ntohs(h->len));
> if (len > 4)
> sppp_print_bytes((u_char*)(h+1), len-4);
> addlog(">\n");
> }
> break;
>
> }
> }
>
> static void
> sppp_pap_init(struct sppp *sp)
> {
> /* PAP doesn't have STATE_INITIAL at all. */
> sp->state[IDX_PAP] = STATE_CLOSED;
> sp->fail_counter[IDX_PAP] = 0;
> callout_handle_init(&sp->ch[IDX_PAP]);
> callout_handle_init(&sp->pap_my_to_ch);
> }
>
> static void
> sppp_pap_open(struct sppp *sp)
> {
> if (sp->hisauth.proto == PPP_PAP &&
> (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) {
> /* we are authenticator for PAP, start our timer */
> sp->rst_counter[IDX_PAP] = sp->lcp.max_configure;
> sppp_cp_change_state(&pap, sp, STATE_REQ_SENT);
> }
> if (sp->myauth.proto == PPP_PAP) {
> /* we are peer, send a request, and start a timer */
> pap.scr(sp);
> sp->pap_my_to_ch = timeout(sppp_pap_my_TO, (void *)sp,
> sp->lcp.timeout);
> }
> }
>
> static void
> sppp_pap_close(struct sppp *sp)
> {
> if (sp->state[IDX_PAP] != STATE_CLOSED)
> sppp_cp_change_state(&pap, sp, STATE_CLOSED);
> }
>
> /*
> * That's the timeout routine if we are authenticator. Since the
> * authenticator is basically passive in PAP, we can't do much here.
> */
> static void
> sppp_pap_TO(void *cookie)
> {
> struct sppp *sp = (struct sppp *)cookie;
> STDDCL;
> int s;
>
> s = splimp();
> if (debug)
> log(LOG_DEBUG, "%s%d: pap TO(%s) rst_counter = %d\n",
> ifp->if_name, ifp->if_unit,
> sppp_state_name(sp->state[IDX_PAP]),
> sp->rst_counter[IDX_PAP]);
>
> if (--sp->rst_counter[IDX_PAP] < 0)
> /* TO- event */
> switch (sp->state[IDX_PAP]) {
> case STATE_REQ_SENT:
> pap.tld(sp);
> sppp_cp_change_state(&pap, sp, STATE_CLOSED);
> break;
> }
> else
> /* TO+ event, not very much we could do */
> switch (sp->state[IDX_PAP]) {
> case STATE_REQ_SENT:
> /* sppp_cp_change_state() will restart the timer */
> sppp_cp_change_state(&pap, sp, STATE_REQ_SENT);
> break;
> }
>
> splx(s);
> }
>
> /*
> * That's the timeout handler if we are peer. Since the peer is active,
> * we need to retransmit our PAP request since it is apparently lost.
> * XXX We should impose a max counter.
> */
> static void
> sppp_pap_my_TO(void *cookie)
> {
> struct sppp *sp = (struct sppp *)cookie;
> STDDCL;
>
> if (debug)
> log(LOG_DEBUG, "%s%d: pap peer TO\n",
> ifp->if_name, ifp->if_unit);
>
> pap.scr(sp);
> }
>
> static void
> sppp_pap_tlu(struct sppp *sp)
> {
> STDDCL;
> int x;
>
> sp->rst_counter[IDX_PAP] = sp->lcp.max_configure;
>
> if (debug)
> log(LOG_DEBUG, "%s%d: %s tlu\n",
> ifp->if_name, ifp->if_unit, pap.name);
>
> x = splimp();
> /* indicate to LCP that we need to be closed down */
> sp->lcp.protos |= (1 << IDX_PAP);
>
> if (sp->pp_flags & PP_NEEDAUTH) {
> /*
> * Remote is authenticator, but his auth proto didn't
> * complete yet. Defer the transition to network
> * phase.
> */
> splx(x);
> return;
> }
> splx(x);
> sppp_phase_network(sp);
> }
>
> static void
> sppp_pap_tld(struct sppp *sp)
> {
> STDDCL;
>
> if (debug)
> log(LOG_DEBUG, "%s%d: pap tld\n", ifp->if_name, ifp->if_unit);
> untimeout(pap.TO, (void *)sp, sp->ch[IDX_PAP]);
> untimeout(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch);
> sp->lcp.protos &= ~(1 << IDX_PAP);
>
> lcp.Close(sp);
> }
>
> static void
> sppp_pap_scr(struct sppp *sp)
> {
> STDDCL;
> u_char idlen, pwdlen;
>
> sp->confid[IDX_PAP] = ++sp->pp_seq;
> pwdlen = sppp_strnlen(sp->myauth.secret, AUTHKEYLEN);
> idlen = sppp_strnlen(sp->myauth.name, AUTHNAMELEN);
>
> sppp_auth_send(&pap, sp, PAP_REQ, sp->confid[IDX_PAP],
> sizeof idlen, (const char *)&idlen,
> (unsigned)idlen, sp->myauth.name,
> sizeof pwdlen, (const char *)&pwdlen,
> (unsigned)pwdlen, sp->myauth.secret,
> 0);
> }
> /*
2519a3544,3621
> * Send a PAP or CHAP proto packet.
> *
> * Varadic function, each of the elements for the ellipsis is of type
> * ``unsigned mlen, const u_char *msg''. Processing will stop iff
> * mlen == 0.
> */
>
> static void
> sppp_auth_send(const struct cp *cp, struct sppp *sp, u_char type, u_char id,
> ...)
> {
> STDDCL;
> struct ppp_header *h;
> struct lcp_header *lh;
> struct mbuf *m;
> u_char *p;
> int len;
> unsigned mlen;
> const char *msg;
> va_list ap;
>
> MGETHDR (m, M_DONTWAIT, MT_DATA);
> if (! m)
> return;
> m->m_pkthdr.rcvif = 0;
>
> h = mtod (m, struct ppp_header*);
> h->address = PPP_ALLSTATIONS; /* broadcast address */
> h->control = PPP_UI; /* Unnumbered Info */
> h->protocol = htons(cp->proto);
>
> lh = (struct lcp_header*)(h + 1);
> lh->type = type;
> lh->ident = id;
> p = (u_char*) (lh+1);
>
> va_start(ap, id);
> len = 0;
>
> while ((mlen = va_arg(ap, unsigned)) != 0) {
> msg = va_arg(ap, const char *);
> len += mlen;
> if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) {
> va_end(ap);
> m_freem(m);
> return;
> }
>
> bcopy(msg, p, mlen);
> p += mlen;
> }
> va_end(ap);
>
> m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len;
> lh->len = htons (LCP_HEADER_LEN + len);
>
> if (debug) {
> log(LOG_DEBUG, "%s%d: %s output <%s id=0x%x len=%d",
> ifp->if_name, ifp->if_unit, cp->name,
> sppp_auth_type_name(cp->proto, lh->type),
> lh->ident, ntohs(lh->len));
> if (len)
> sppp_print_bytes((u_char*) (lh+1), len);
> addlog(">\n");
> }
> if (IF_QFULL (&sp->pp_cpq)) {
> IF_DROP (&sp->pp_fastq);
> IF_DROP (&ifp->if_snd);
> m_freem (m);
> ++ifp->if_oerrors;
> } else
> IF_ENQUEUE (&sp->pp_cpq, m);
> if (! (ifp->if_flags & IFF_OACTIVE))
> (*ifp->if_start) (ifp);
> ifp->if_obytes += m->m_pkthdr.len + 3;
> }
>
> /*
2593c3695
< sppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst)
---
> sppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, u_long *srcmask)
2597c3699
< struct sockaddr_in *si;
---
> struct sockaddr_in *si, *sm;
2606c3708
< ifa;
---
> ifa;
2609a3712
> sm = (struct sockaddr_in *)ifa->ifa_netmask;
2614c3717
< if (si && si->sin_addr.s_addr)
---
> if (si && si->sin_addr.s_addr) {
2615a3719,3721
> if (srcmask)
> *srcmask = ntohl(sm->sin_addr.s_addr);
> }
2642c3748
< ifa;
---
> ifa;
2652a3759,3889
> static int
> sppp_params(struct sppp *sp, int cmd, void *data)
> {
> int subcmd;
> struct ifreq *ifr = (struct ifreq *)data;
> struct spppreq spr;
>
> /*
> * ifr->ifr_data is supposed to point to a struct spppreq.
> * Check the cmd word first before attempting to fetch all the
> * data.
> */
> if ((subcmd = fuword(ifr->ifr_data)) == -1)
> return EFAULT;
>
> if (copyin((caddr_t)ifr->ifr_data, &spr, sizeof spr) != 0)
> return EFAULT;
>
> switch (subcmd) {
> case SPPPIOGDEFS:
> if (cmd != SIOCGIFGENERIC)
> return EINVAL;
> /*
> * We copy over the entire current state, but clean
> * out some of the stuff we don't wanna pass up.
> * Remember, SIOCGIFGENERIC is unprotected, and can be
> * called by any user. No need to ever get PAP or
> * CHAP secrets back to userland anyway.
> */
> bcopy(sp, &spr.defs, sizeof(struct sppp));
> bzero(spr.defs.myauth.secret, AUTHKEYLEN);
> bzero(spr.defs.myauth.challenge, AUTHKEYLEN);
> bzero(spr.defs.hisauth.secret, AUTHKEYLEN);
> bzero(spr.defs.hisauth.challenge, AUTHKEYLEN);
> return copyout(&spr, (caddr_t)ifr->ifr_data, sizeof spr);
>
> case SPPPIOSDEFS:
> if (cmd != SIOCSIFGENERIC)
> return EINVAL;
> /*
> * We have a very specific idea of which fields we allow
> * being passed back from userland, so to not clobber our
> * current state. For one, we only allow setting
> * anything if LCP is in dead phase. Once the LCP
> * negotiations started, the authentication settings must
> * not be changed again. (The administrator can force an
> * ifconfig down in order to get LCP back into dead
> * phase.)
> *
> * Also, we only allow for authentication parameters to be
> * specified.
> *
> * XXX Should allow to set or clear pp_flags.
> *
> * Finally, if the respective authentication protocol to
> * be used is set differently than 0, but the secret is
> * passed as all zeros, we don't trash the existing secret.
> * This allows an administrator to change the system name
> * only without clobbering the secret (which he didn't get
> * back in a previous SPPPIOGDEFS call). However, the
> * secrets are cleared if the authentication protocol is
> * reset to 0.
> */
> if (sp->pp_phase != PHASE_DEAD)
> return EBUSY;
>
> if ((spr.defs.myauth.proto != 0 && spr.defs.myauth.proto != PPP_PAP &&
> spr.defs.myauth.proto != PPP_CHAP) ||
> (spr.defs.hisauth.proto != 0 && spr.defs.hisauth.proto != PPP_PAP &&
> spr.defs.hisauth.proto != PPP_CHAP))
> return EINVAL;
>
> if (spr.defs.myauth.proto == 0)
> /* resetting myauth */
> bzero(&sp->myauth, sizeof sp->myauth);
> else {
> /* setting/changing myauth */
> sp->myauth.proto = spr.defs.myauth.proto;
> bcopy(spr.defs.myauth.name, sp->myauth.name, AUTHNAMELEN);
> if (spr.defs.myauth.secret[0] != '\0')
> bcopy(spr.defs.myauth.secret, sp->myauth.secret,
> AUTHKEYLEN);
> }
> if (spr.defs.hisauth.proto == 0)
> /* resetting hisauth */
> bzero(&sp->hisauth, sizeof sp->hisauth);
> else {
> /* setting/changing hisauth */
> sp->hisauth.proto = spr.defs.hisauth.proto;
> sp->hisauth.flags = spr.defs.hisauth.flags;
> bcopy(spr.defs.hisauth.name, sp->hisauth.name, AUTHNAMELEN);
> if (spr.defs.hisauth.secret[0] != '\0')
> bcopy(spr.defs.hisauth.secret, sp->hisauth.secret,
> AUTHKEYLEN);
> }
> break;
>
> default:
> return EINVAL;
> }
>
> return 0;
> }
>
> static void
> sppp_phase_network(struct sppp *sp)
> {
> struct ifnet *ifp = &sp->pp_if;
> int i;
> u_long mask;
>
> sp->pp_phase = PHASE_NETWORK;
>
> log(LOG_INFO, "%s%d: phase %s\n", ifp->if_name, ifp->if_unit,
> sppp_phase_name(sp->pp_phase));
>
> /* Notify NCPs now. */
> for (i = 0; i < IDX_COUNT; i++)
> if ((cps[i])->flags & CP_NCP)
> (cps[i])->Open(sp);
>
> /* Send Up events to all NCPs. */
> for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1)
> if (sp->lcp.protos & mask && ((cps[i])->flags & CP_NCP))
> (cps[i])->Up(sp);
>
> /* if no NCP is starting, all this was in vain, close down */
> sppp_lcp_check_and_close(sp);
> }
>
>
2656c3893
< static char buf [12];
---
> static char buf[12];
2658,2668c3895,3905
< case CONF_REQ: return ("conf-req");
< case CONF_ACK: return ("conf-ack");
< case CONF_NAK: return ("conf-nak");
< case CONF_REJ: return ("conf-rej");
< case TERM_REQ: return ("term-req");
< case TERM_ACK: return ("term-ack");
< case CODE_REJ: return ("code-rej");
< case PROTO_REJ: return ("proto-rej");
< case ECHO_REQ: return ("echo-req");
< case ECHO_REPLY: return ("echo-reply");
< case DISC_REQ: return ("discard-req");
---
> case CONF_REQ: return "conf-req";
> case CONF_ACK: return "conf-ack";
> case CONF_NAK: return "conf-nak";
> case CONF_REJ: return "conf-rej";
> case TERM_REQ: return "term-req";
> case TERM_ACK: return "term-ack";
> case CODE_REJ: return "code-rej";
> case PROTO_REJ: return "proto-rej";
> case ECHO_REQ: return "echo-req";
> case ECHO_REPLY: return "echo-reply";
> case DISC_REQ: return "discard-req";
2671c3908
< return (buf);
---
> return buf;
2674a3912,3934
> sppp_auth_type_name(u_short proto, u_char type)
> {
> static char buf[12];
> switch (proto) {
> case PPP_CHAP:
> switch (type) {
> case CHAP_CHALLENGE: return "challenge";
> case CHAP_RESPONSE: return "response";
> case CHAP_SUCCESS: return "success";
> case CHAP_FAILURE: return "failure";
> }
> case PPP_PAP:
> switch (type) {
> case PAP_REQ: return "req";
> case PAP_ACK: return "ack";
> case PAP_NAK: return "nak";
> }
> }
> sprintf (buf, "0x%x", type);
> return buf;
> }
>
> static const char *
2677c3937
< static char buf [12];
---
> static char buf[12];
2679,2685c3939,3945
< case LCP_OPT_MRU: return ("mru");
< case LCP_OPT_ASYNC_MAP: return ("async-map");
< case LCP_OPT_AUTH_PROTO: return ("auth-proto");
< case LCP_OPT_QUAL_PROTO: return ("qual-proto");
< case LCP_OPT_MAGIC: return ("magic");
< case LCP_OPT_PROTO_COMP: return ("proto-comp");
< case LCP_OPT_ADDR_COMP: return ("addr-comp");
---
> case LCP_OPT_MRU: return "mru";
> case LCP_OPT_ASYNC_MAP: return "async-map";
> case LCP_OPT_AUTH_PROTO: return "auth-proto";
> case LCP_OPT_QUAL_PROTO: return "qual-proto";
> case LCP_OPT_MAGIC: return "magic";
> case LCP_OPT_PROTO_COMP: return "proto-comp";
> case LCP_OPT_ADDR_COMP: return "addr-comp";
2688c3948
< return (buf);
---
> return buf;
2694c3954
< static char buf [12];
---
> static char buf[12];
2696,2698c3956,3958
< case IPCP_OPT_ADDRESSES: return ("addresses");
< case IPCP_OPT_COMPRESSION: return ("compression");
< case IPCP_OPT_ADDRESS: return ("address");
---
> case IPCP_OPT_ADDRESSES: return "addresses";
> case IPCP_OPT_COMPRESSION: return "compression";
> case IPCP_OPT_ADDRESS: return "address";
2701c3961
< return (buf);
---
> return buf;
2741a4002,4003
> case PPP_PAP: return "pap";
> case PPP_CHAP: return "chap";
2748c4010
< sppp_print_bytes(u_char *p, u_short len)
---
> sppp_print_bytes(const u_char *p, u_short len)
2754a4017,4061
> static void
> sppp_print_string(const char *p, u_short len)
> {
> u_char c;
>
> while (len-- > 0) {
> c = *p++;
> /*
> * Print only ASCII chars directly. RFC 1994 recommends
> * using only them, but we don't rely on it. */
> if (c < ' ' || c > '~')
> addlog("\\x%x", c);
> else
> addlog("%c", c);
> }
> }
>
> static const char *
> sppp_dotted_quad(u_long addr)
> {
> static char s[16];
> sprintf(s, "%d.%d.%d.%d",
> (addr >> 24) & 0xff,
> (addr >> 16) & 0xff,
> (addr >> 8) & 0xff,
> addr & 0xff);
> return s;
> }
>
> static int
> sppp_strnlen(u_char *p, int max)
> {
> int len;
>
> for (len = 0; len < max && *p; ++p)
> ++len;
> return len;
> }
>
> /* a dummy, used to drop uninteresting events */
> static void
> sppp_null(struct sppp *unused)
> {
> /* do just nothing */
> }
2759c4066
< * hilit-auto-highlight-maxout: 100000
---
> * hilit-auto-highlight-maxout: 120000