home *** CD-ROM | disk | FTP | other *** search
- /*
- * PPPLCP.C -- negotiate data link options
- *
- * REVISIONS:
- * 12-89 -- Katie Stevens (dkstevens@ucdavis.edu)
- * UC Davis, Computing Services
- * PPP.01 01-90 [ks] must echo requested magic# in REJ
- * PPP.08 05-90 [ks] improve PPP trace reporting
- * PPP.09 05-90 [ks] add auth type negotiation
- * PPP.10 07-90 [ks] make ppp open/close/reset work properly
- * PPP.14 08-90 [ks] change UPAP to PAP for consistency
- * with RFC1172
- * make LCP timeout configurable
- * PPP.15 09-90 [ks] update to KA9Q NOS v900828
- */
-
- #include <stdio.h>
- #include "global.h"
- #include "mbuf.h"
- #include "proc.h"
- #include "iface.h"
- #include "slip.h"
- #include "ppp.h"
-
- /* Counter for PPP id field */
- extern unsigned char Pppid;
-
- /* PPP tracing */
- extern int Ppptrace;
-
- static void lcp_open __ARGS((struct slip *sp));
-
- static int lcp_sendreq __ARGS((struct slip *sp));
- static struct mbuf *lcp_makereq __ARGS((struct lcpparm *localp));
-
- static void lcp_rcvack __ARGS((struct slip *sp, struct cnfhdr *rcnf,
- struct mbuf *data));
- static void lcp_rcvnak __ARGS((struct slip *sp, struct cnfhdr *rcnf,
- struct mbuf *data));
- static void lcp_rcvrej __ARGS((struct slip *sp, struct cnfhdr *rcnf,
- struct mbuf *data));
- static void lcp_rcvreq __ARGS((struct slip *sp, struct cnfhdr *rcnf,
- struct mbuf *data));
- static void lcp_rcvtermack __ARGS((struct slip *sp));
- static void lcp_rcvtermreq __ARGS((struct slip *sp, struct cnfhdr *rcnf));
-
- static int lcp_chkack __ARGS((struct slip *sp, struct cnfhdr *ackcnf,
- struct mbuf *data));
- static int lcp_chknak __ARGS((struct slip *sp, struct cnfhdr *nakcnf,
- struct mbuf *data));
- static int lcp_chkrej __ARGS((struct slip *sp, struct cnfhdr *rejcnf,
- struct mbuf *data));
- static void lcp_chkreq __ARGS((struct slip *sp, struct cnfhdr *reqcnf,
- struct mbuf *data));
-
- static void lcp_timeout __ARGS((void *vp));
- static void lcp_timer __ARGS((struct slip *sp));
-
- static int lcp_sendreply __ARGS((struct slip *sp, char code,
- unsigned char id, struct mbuf *data));
-
- /* Possible LCP states */
- char *LCPStates[] = {
- "Closed",
- "Listen",
- "Req Sent",
- "Ack Rcvd",
- "Ack Sent",
- "Open",
- "Terminate"
- };
-
- /* Possible LCP/IPCP packet types */
- char *LCPCodes[] = {
- NULLCHAR,
- "Config Req",
- "Config Ack",
- "Config Nak",
- "Config Rej",
- "Terminate Req",
- "Terminate Ack",
- "Code Rej",
- "Protocol Rej",
- "Echo Req",
- "Echo Reply",
- "Discard Req",
- };
-
- /* LCP default options, local */
- /* Attempt: 0=dont negotiate; 1=attempt negotiation */
- /* NOTE: this sructure is used to initialize the local parameter side */
- /* of PPP connections; options which will not be negotiated must be */
- /* initialized to default LCP values specified in the PPP RFC */
- static struct lcpparm attempt_parms = {
- 0, DEF_MRU,
- 0, DEF_CTL_MAP,
- 0, DEF_AUTH_TYPE,
- 0, DEF_ENCR_TYPE,
- 0, DEF_MAGIC_NUM,
- 0, DEF_LINK_QUAL,
- 0, DEF_PROT_COMPR,
- 0, DEF_AC_COMPR
- };
- /* LCP default options, remote */
- /* Accept: 0=reject negotiation; 1=negotiation okay */
- static struct lcpparm accept_parms = {
- 1, DEF_MRU,
- 1, DEF_CTL_MAP,
- 1, DEF_AUTH_TYPE,
- 0, DEF_ENCR_TYPE,
- 0, DEF_MAGIC_NUM,
- 0, DEF_LINK_QUAL,
- 1, DEF_PROT_COMPR,
- 1, DEF_AC_COMPR
- };
-
- /****************************************************************************/
-
- /* Convert LCP/IPCP header in host form to network form */
- struct mbuf *
- htoncnf(cnf, data)
- struct cnfhdr *cnf;
- struct mbuf *data;
- {
- struct mbuf *bp;
- register char *cp;
-
- /* Prepend bytes for LCP/IPCP header */
- if ((bp = pushdown(data, CNF_HDRLEN)) == NULLBUF)
- return NULLBUF;
-
- /* Load header with proper values */
- cp = bp->data;
- *cp++ = cnf->code;
- *cp++ = cnf->id;
- put16(cp, cnf->len);
-
- return bp;
- }
-
- /* Extract LCP/IPCP header from incoming packet */
- int
- ntohcnf(cnf, bpp)
- struct cnfhdr *cnf;
- struct mbuf **bpp;
- {
- cnf->code = pullchar(bpp);
- cnf->id = pullchar(bpp);
- cnf->len = pull16(bpp);
- return(CNF_HDRLEN);
- }
-
- /*******************************************/
-
- /* Convert LCP/IPCP configuration option header in host form to network mbuf */
- struct mbuf *
- htonopt(opt)
- struct opthdr *opt;
- {
- struct mbuf *bp;
- register char *cp;
-
- if((bp = alloc_mbuf(OPT_HDRLEN)) == NULLBUF)
- return NULLBUF;
-
- /* Load data into LCP/IPCP configuration option header */
- cp = bp->data;
- *cp++ = opt->type;
- *cp++ = opt->len;
-
- bp->cnt = cp - bp->data;
- return bp;
- }
- /* Extract LCP/IPCP configuration option header */
- int
- ntohopt(opt,bpp)
- struct opthdr *opt;
- struct mbuf **bpp;
- {
- if (opt== NULLOPTHDR || bpp == NULLBUFP)
- return -1;
- if (*bpp == NULLBUF)
- return -1;
-
- opt->type = pullchar(bpp);
- opt->len = pullchar(bpp);
- return 0;
- }
-
- /****************************************************************************/
-
- /* Initialize Link Control Protocol state machine for config exchange */
- int
- lcp_start(sp)
- struct slip *sp;
- {
- struct pppctl *pppiop;
- struct lcpctl *lcpiop;
-
- pppiop = sp->pppio;
- lcpiop = &(pppiop->lcpio);
-
- if (Ppptrace > 5)
- log(-1, "lcp_start()");
-
- /* Leave things alone if not strictly closed */
- if ((pppiop->state != PPP_CLOSED)&&(lcpiop->lcp_state != LCP_LISTEN)
- &&(lcpiop->lcp_state != LCP_CLOSED)) {
- return 0;
- }
-
- /* Prepare for Link Control negotiations */
- lcp_reset(pppiop);
-
- if (lcpiop->active == -1) {
- /* We have been strictly closed with 'ppp close' command */
- return 0;
- }
-
- /* Ready for Link Control negotiations */
- pppiop->state = PPP_LCP;
- if (lcpiop->active == 0) {
- /* Passive open; wait until remote host attempts connection */
- lcpiop->lcp_state = LCP_LISTEN;
- return 0;
- }
-
- /* Active open; begin LCP configuration negotiation */
- lcpiop->lcp_state = LCP_CLOSED;
- return(lcp_sendreq(sp));
- }
-
- /*******************************************/
-
- /* Close the PPP connection from local side */
- int
- lcp_close(sp)
- struct slip *sp;
- {
- struct pppctl *pppiop;
- struct lcpctl *lcpiop;
- struct ipcpctl *ipcpiop;
-
- if (Ppptrace > 5)
- log(-1,"lcp_close()");
-
- pppiop = sp->pppio;
- lcpiop = &(pppiop->lcpio);
- ipcpiop = &(pppiop->ipcpio);
- if ((lcpiop->lcp_state == LCP_CLOSED) ||
- (lcpiop->lcp_state == LCP_LISTEN)) {
- /* Already closed */
- return 0;
- }
-
- /* Need to shutdown PAP session if waiting for password */
- psignal(&(lcpiop->pap_user),0);
-
- /* Need to inform upper layers */
- if ((ipcpiop->ipcp_state != IPCP_CLOSED) &&
- (ipcpiop->ipcp_state != IPCP_LISTEN)) {
- /* Wait for the IP layer to close */
- ipcp_close(sp);
- pwait(ipcpiop);
- }
-
- /* Set a timer against our request to shutdown */
- lcp_timer(sp);
- /* Ask remote host to shutdown */
- lcpiop->lcp_state = LCP_TERMINATE;
- lcpiop->ack_retry = 0;
- if (lcp_sendreply(sp, TERMINATE_REQ, 0, NULLBUF) == 0)
- pwait(lcpiop);
-
- pppiop->state = PPP_CLOSED;
- return 0;
- }
-
- /* Initialize our LCP configuration options to compiled default options */
- void
- lcp_init(sp)
- struct slip *sp;
- {
- struct pppctl *pppiop;
- struct lcpctl *lcpiop;
- struct timer *t;
-
- if (Ppptrace > 5)
- log(-1, "lcp_init()");
-
- pppiop = sp->pppio;
- lcpiop = &(pppiop->lcpio);
- t = &(lcpiop->lcp_tm);
-
- /* One time initialization */
- lcpiop->lcp_state = LCP_CLOSED;
- lcpiop->active = 0;
- memcpy(&(lcpiop->initparm), &attempt_parms, sizeof(struct lcpparm));
- set_timer(t,LCP_TIMEOUT*1000L);
- lcp_timer(sp); /* Set timer strictly OFF */
- stop_timer(&(lcpiop->lcp_tm));
-
- /* Initialization for each LCP open/close */
- lcp_reset(pppiop);
- return;
- }
-
- /* Link Control configuration negotiation complete */
- static void
- lcp_open(sp)
- struct slip *sp;
- {
- struct pppctl *pppiop;
- struct lcpctl *lcpiop;
-
- pppiop = sp->pppio;
- lcpiop = &(pppiop->lcpio);
-
- /* Check on Auth Protocol */
- if (lcpiop->initparm.auth_type != 0x0000) {
- /* We require authentication from the remote host */
- if (lcpiop->lclparm.auth_type != lcpiop->initparm.auth_type) {
- /* Couldnt agree on auth, shut down the link */
- if (Ppptrace)
- log(-1,"%s: Couldn't negotiate Authenticate Protocol type",sp->iface->name);
- lcp_shutdown(sp);
- return;
- }
- }
-
- /* Mark LCP layer as open */
- if (Ppptrace)
- log(-1,"%s: PPP/LCP Connection Open",sp->iface->name);
- lcpiop->lcp_state = LCP_OPEN;
-
- /* Set flags in PPP control struct to reflect accepted LCP options */
- if (sp->iface->mtu > lcpiop->remparm.mru) {
- /* Set new Max Transmission Unit for outgoing packets */
- sp->iface->mtu = lcpiop->remparm.mru;
- if (Ppptrace > 1)
- log(-1," Set new MTU for outgoing packets: %d",
- sp->iface->mtu);
- }
-
- /* Update async control character map for outgoing packets */
- if (pppiop->ctlmap != lcpiop->remparm.ctl_map) {
- pppiop->ctlmap = lcpiop->remparm.ctl_map;
- if (Ppptrace > 1)
- log(-1," Set new control map for outgoing packets: 0x%08lx",
- pppiop->ctlmap);
- }
-
- /* Update for protocol compression for outgoing/incoming packets */
- if (lcpiop->remparm.prot_compress) {
- sp->escaped |= PPP_XMT_PRCOMP;
- if (Ppptrace > 1)
- log(-1," Begin protocol compression on outgoing packets");
- }
- if (lcpiop->lclparm.prot_compress) {
- sp->escaped |= PPP_RCV_PRCOMP;
- if (Ppptrace > 1)
- log(-1," Begin protocol compression on incoming packets");
- }
-
- /* Update for addr/ctl compression for outgoing/incoming packets */
- if (lcpiop->remparm.ac_compress) {
- sp->escaped |= PPP_XMT_ACCOMP;
- if (Ppptrace > 1)
- log(-1," Begin addr/ctl compression on outgoing packets");
- }
- if (lcpiop->lclparm.ac_compress) {
- sp->escaped |= PPP_RCV_ACCOMP;
- if (Ppptrace > 1)
- log(-1," Begin addr/ctl compression on incoming packets");
- }
-
- /* LCP is open; switch to next phase */
- if ((lcpiop->lclparm.auth_type == PAP_AUTH_TYPE) ||
- (lcpiop->remparm.auth_type == PAP_AUTH_TYPE)) {
- /* Startup PAP negotiations (do IPCP when done with PAP) */
- pap_start(sp);
- } else {
- /* Startup IPCP negotiations */
- ipcp_start(sp);
- }
- return;
- }
-
- /* Reset LCP configuration options for initial request */
- int
- lcp_reset(pppiop)
- struct pppctl *pppiop;
- {
- struct lcpctl *lcpiop;
-
- if (Ppptrace > 5)
- log(-1, "lcp_reset()");
-
- lcpiop = &(pppiop->lcpio);
- pppiop->ctlmap = DEF_CTL_MAP;
- if (lcpiop->active == 0)
- lcpiop->lcp_state = LCP_LISTEN;
- else
- lcpiop->lcp_state = LCP_CLOSED;
- lcpiop->ack_retry = 0;
-
- /* Reset our config request prarmeters to our preferred values */
- memcpy(&(lcpiop->lclparm),&(lcpiop->initparm),
- sizeof(struct lcpparm));
- memcpy(&(lcpiop->remparm),&accept_parms,
- sizeof(struct lcpparm));
-
- /* Need to shutdown PAP session if waiting for password */
- psignal(&(lcpiop->pap_user),0);
-
- return 0;
- }
-
- /****************************************************************************/
-
- /* Send our LCP configuration request */
- static int
- lcp_sendreq(sp)
- struct slip *sp;
- {
- struct pppctl *pppiop;
- struct lcpctl *lcpiop;
- struct mbuf *bp;
-
- if (Ppptrace > 5)
- log(-1,"lcp_sendreq()");
-
- pppiop = sp->pppio;
- lcpiop = &(pppiop->lcpio);
-
- /* Get a packet with our configuration request */
- bp = lcp_makereq(&(lcpiop->lclparm));
-
- /* Start timer against wait for reply to our config request */
- lcp_timer(sp);
-
- /* Send LCP configuration request to remote host */
- pppiop->state = PPP_LCP;
- if (lcpiop->lcp_state != LCP_ACK_SENT)
- lcpiop->lcp_state = LCP_REQ_SENT;
- return(lcp_sendreply(sp, CONFIG_REQ, 0, bp));
- }
-
- /*******************************************/
-
- static struct mbuf *
- lcp_makereq(localp)
- struct lcpparm *localp;
- {
- register char *cp;
- struct mbuf *bp;
- struct mbuf *req_bp = NULLBUF;
-
- if (Ppptrace > 5)
- log(-1," lcp_makereq()");
-
- /* Maximum Receive Unit */
- if (localp->neg_mru) {
- if (Ppptrace > 5)
- log(-1," asking for MRU: %d (0x%02x)",
- localp->mru,localp->mru);
-
- /* Attempt to negotiate Maximum Receive Unit */
- if ((bp = alloc_mbuf(4)) == NULLBUF)
- return NULLBUF;
- cp = bp->data;
- *cp++ = MAX_RCV_UNIT;
- *cp++ = 4;
- put16(cp, localp->mru);
- bp->cnt += 4;
- append(&req_bp, bp);
- }
- /* Async Control Map */
- if (localp->neg_ctl_map) {
- if (Ppptrace > 5)
- log(-1," asking for Async Control Map: 0x%08lx",
- localp->ctl_map);
-
- /* Attempt to negotiate Async Control Map */
- if ((bp = alloc_mbuf(6)) == NULLBUF)
- return NULLBUF;
- cp = bp->data;
- *cp++ = ASYNC_CTL_MAP;
- *cp++ = 6;
- put32(cp, localp->ctl_map);
- bp->cnt += 6;
- append(&req_bp, bp);
- }
- /* Authentication type */
- if ((localp->neg_auth_type)&&(localp->auth_type != 0x0000)) {
- if (Ppptrace > 5)
- log(-1," asking for Auth Protocol: 0x%04x",
- localp->auth_type);
- /* Attempt to negotiate Authentication Protocol */
- if ((bp = alloc_mbuf(4)) == NULLBUF)
- return NULLBUF;
- cp = bp->data;
- *cp++ = AUTH_TYPE;
- *cp++ = 4;
- put16(cp, localp->auth_type);
- bp->cnt += 4;
- append(&req_bp, bp);
- }
- /* Magic Number */
- if (localp->neg_magic_num) {
- if (Ppptrace > 5)
- log(-1," asking for Magic Number: %0x08lx",
- localp->magic_num);
-
- /* Attempt to negotiate Magic Number */
- if ((bp = alloc_mbuf(6)) == NULLBUF)
- return NULLBUF;
- cp = bp->data;
- *cp++ = MAGIC_NUMBER;
- *cp++ = 6;
- put32(cp, localp->magic_num);
- bp->cnt += 6;
- append(&req_bp, bp);
- }
- /* Protocol Field Compression */
- if (localp->neg_prot_compress) {
- if (Ppptrace > 5)
- log(-1," asking for Protcol compression");
-
- /* Attempt to negotiate protocol field compression */
- if ((bp = alloc_mbuf(2)) == NULLBUF)
- return NULLBUF;
- cp = bp->data;
- *cp++ = PROT_COMPRESS;
- *cp++ = 2;
- bp->cnt += 2;
- append(&req_bp, bp);
- }
- /* Address and Control Field Compression */
- if (localp->neg_ac_compress) {
- if (Ppptrace > 5)
- log(-1," asking for Addr/Ctl compression");
-
- /* Attempt to negotiate protocol field compression */
- if ((bp = alloc_mbuf(2)) == NULLBUF)
- return NULLBUF;
- cp = bp->data;
- *cp++ = AC_COMPRESS;
- *cp++ = 2;
- bp->cnt += 2;
- append(&req_bp, bp);
- }
- /* Encryption type not implemented */
- /* Link Quality Monitoring not implemented */
-
- return(req_bp);
- }
-
- /****************************************************************************/
-
- /* Remote host ACKed our configuration request */
- static void
- lcp_rcvack(sp, rcnf, data)
- struct slip *sp;
- struct cnfhdr *rcnf;
- struct mbuf *data;
- {
- struct pppctl *pppiop;
- struct lcpctl *lcpiop;
-
- if (Ppptrace > 5)
- log(-1, "lcp_rcvack()");
-
- pppiop = sp->pppio;
- lcpiop = &(pppiop->lcpio);
- stop_timer(&lcpiop->lcp_tm);
-
- switch(lcpiop->lcp_state) {
- case LCP_REQ_SENT:
- /* Make sure ACK is proper */
- if (lcp_chkack(sp, rcnf, data) != -1) {
- /* Remote host accepted our request */
- lcpiop->lcp_state = LCP_ACK_RCVD;
- }
-
- /* Still need to settle request from remote host */
- lcp_timer(sp);
- break;
-
- case LCP_ACK_SENT:
- /* Make sure ACK is proper */
- if (lcp_chkack(sp, rcnf, data) == -1) {
- /* Error in ACK from remote host */
- /* Wait for another ACK, then send another request */
- lcp_timer(sp);
- } else {
- /* LCP negotiation complete */
- lcp_open(sp);
- }
- break;
-
- case LCP_ACK_RCVD:
- case LCP_OPEN:
- /* Something went wrong; restart negotiations */
- free_p(data);
- lcp_reset(pppiop);
- lcp_sendreq(sp);
- break;
- case LCP_TERMINATE:
- /* We are attempting to close connection; wait */
- /* for timeout to resend a Terminate Request */
- free_p(data);
- break;
- case LCP_CLOSED:
- case LCP_LISTEN:
- default:
- /* Confusion; shutdown the connection */
- free_p(data);
- lcp_shutdown(sp);
- break;
- }
- return;
- }
-
- /* Remote host NAKed our configuration request */
- static void
- lcp_rcvnak(sp, rcnf, data)
- struct slip *sp;
- struct cnfhdr *rcnf;
- struct mbuf *data;
- {
- struct pppctl *pppiop;
- struct lcpctl *lcpiop;
-
- if (Ppptrace > 5)
- log(-1, "lcp_rcvnak()");
-
- pppiop = sp->pppio;
- lcpiop = &(pppiop->lcpio);
- stop_timer(&lcpiop->lcp_tm);
-
- switch(lcpiop->lcp_state) {
- case LCP_REQ_SENT:
- case LCP_ACK_SENT:
- /* Update our config request to reflect NAKed options */
- if (lcp_chknak(sp, rcnf, data) == -1) {
- /* Bad NAK packet */
- /* Wait for another; resend request on timeout */
- lcp_timer(sp);
- } else {
- /* Send updated config request */
- lcp_sendreq(sp);
- }
- break;
-
- case LCP_ACK_RCVD:
- case LCP_OPEN:
- /* Something went wrong; restart negotiations */
- free_p(data);
- lcp_reset(pppiop);
- lcp_sendreq(sp);
- break;
- case LCP_TERMINATE:
- /* We are attempting to close connection; wait */
- /* for timeout to resend a Terminate Request */
- free_p(data);
- break;
- case LCP_CLOSED:
- case LCP_LISTEN:
- default:
- /* Confusion; shutdown the connection */
- free_p(data);
- lcp_shutdown(sp);
- break;
- }
- return;
- }
-
- /* Remote host rejected our configuration request */
- static void
- lcp_rcvrej(sp, rcnf, data)
- struct slip *sp;
- struct cnfhdr *rcnf;
- struct mbuf *data;
- {
- struct pppctl *pppiop;
- struct lcpctl *lcpiop;
-
- if (Ppptrace > 5)
- log(-1, "lcp_rcvrej()");
-
- pppiop = sp->pppio;
- lcpiop = &(pppiop->lcpio);
- stop_timer(&lcpiop->lcp_tm);
-
- switch(lcpiop->lcp_state) {
- case LCP_REQ_SENT:
- case LCP_ACK_SENT:
- /* Update our config request to reflect rejected options */
- if (lcp_chkrej(sp, rcnf, data) == -1) {
- /* Bad reject packet */
- /* Wait for another; resend request on timeout */
- lcp_timer(sp);
- } else {
- /* Send updated config request */
- lcp_sendreq(sp);
- }
- break;
-
- case LCP_ACK_RCVD:
- case LCP_OPEN:
- /* Something went wrong; restart negotiations */
- free_p(data);
- lcp_reset(pppiop);
- lcp_sendreq(sp);
- break;
- case LCP_TERMINATE:
- /* We are attempting to close connection; wait */
- /* for timeout to resend a Terminate Request */
- free_p(data);
- break;
- case LCP_CLOSED:
- case LCP_LISTEN:
- default:
- /* Confusion; shutdown the connection */
- free_p(data);
- lcp_shutdown(sp);
- break;
- }
- return;
- }
-
- /* Process configuration request sent by remote host */
- static void
- lcp_rcvreq(sp, rcnf, data)
- struct slip *sp;
- struct cnfhdr *rcnf;
- struct mbuf *data;
- {
- struct pppctl *pppiop;
- struct lcpctl *lcpiop;
-
- if (Ppptrace > 5)
- log(-1, "lcp_rcvreq()");
-
- pppiop = sp->pppio;
- lcpiop = &(pppiop->lcpio);
-
- switch(lcpiop->lcp_state) {
- case LCP_LISTEN: /* Normal event */
- case LCP_ACK_SENT: /* Unexpected event */
- case LCP_OPEN: /* Unexpected event */
- /* Reset LCP state machine for configuration negotiation */
- lcp_reset(pppiop);
- /* Send our configuration request */
- lcp_sendreq(sp);
- /* Evaluate configuration request from remote host */
- lcp_chkreq(sp, rcnf, data);
- break;
-
- case LCP_ACK_RCVD:
- /* Stop timer against wait for config request */
- stop_timer(&(lcpiop->lcp_tm));
- case LCP_REQ_SENT:
- /* Evaluate configuration request from remote host */
- lcp_chkreq(sp, rcnf, data);
- break;
-
- case LCP_TERMINATE:
- /* We are attempting to close connection; wait */
- /* for timeout to resend a Terminate Request */
- free_p(data);
- break;
-
- case LCP_CLOSED:
- default:
- /* We are closed; dont accept any connections */
- free_p(data);
- lcp_shutdown(sp);
- break;
- }
- return;
- }
-
- /* Remote host closed connection */
- static void
- lcp_rcvtermack(sp)
- struct slip *sp;
- {
- struct pppctl *pppiop;
- struct lcpctl *lcpiop;
-
- if (Ppptrace > 5)
- log(-1,"lcp_rcvtermack()");
-
- pppiop = sp->pppio;
- lcpiop = &(pppiop->lcpio);
- stop_timer(&(lcpiop->lcp_tm));
-
- switch(lcpiop->lcp_state) {
- case LCP_OPEN:
- /* Remote host has abruptly closed connection */
- /* Need to inform upper levels */
- case LCP_TERMINATE:
- /* Remote host has responded to our terminate request */
- if (Ppptrace)
- log(-1,"%s: PPP/LCP Connection Closed",sp->iface->name);
- pppiop->state = PPP_CLOSED;
- if (lcpiop->active == 0)
- lcpiop->lcp_state = LCP_LISTEN;
- else
- lcpiop->lcp_state = LCP_CLOSED;
- /* Prepare for next open */
- lcp_reset(pppiop);
- psignal(lcpiop,0);
- break;
- case LCP_REQ_SENT:
- /* Wait for timeout to restart attempt */
- break;
- case LCP_ACK_SENT:
- case LCP_ACK_RCVD:
- /* Something went wrong; restart negotiations */
- lcp_reset(pppiop);
- lcp_sendreq(sp);
- break;
- case LCP_CLOSED:
- case LCP_LISTEN:
- default:
- /* Unexpected, but no action needed */
- break;
- }
-
- return;
- }
-
- /* Remote peer requested that we close the PPP connection */
- void
- lcp_rcvtermreq(sp, rcnf)
- struct slip *sp;
- struct cnfhdr *rcnf;
- {
- struct pppctl *pppiop;
- struct lcpctl *lcpiop;
-
- if (Ppptrace > 5)
- log(-1, "lcp_termreq()");
-
- pppiop = sp->pppio;
- lcpiop = &(pppiop->lcpio);
-
- if (Ppptrace)
- log(-1,"%s: PPP/LCP Peer requested close",sp->iface->name);
- lcpiop->active = 0;
- lcpiop->lcp_state = LCP_LISTEN;
- /* Need to inform upper layers */
-
- lcp_sendreply(sp, TERMINATE_ACK, rcnf->id, NULLBUF);
- lcp_reset(pppiop);
- pppiop->state = PPP_CLOSED;
- return;
- }
-
- /* Shutdown the LCP connection */
- void
- lcp_shutdown(sp)
- struct slip *sp;
- {
- struct pppctl *pppiop;
- struct lcpctl *lcpiop;
-
- if (Ppptrace > 5)
- log(-1, "lcp_shutdown()");
-
- pppiop = sp->pppio;
- lcpiop = &(pppiop->lcpio);
-
- if (Ppptrace)
- log(-1,"%s: PPP/LCP Connection Shutdown",sp->iface->name);
- if (lcpiop->active == 0)
- lcpiop->lcp_state = LCP_LISTEN;
- else
- lcpiop->lcp_state = LCP_CLOSED;
- /* Need to inform upper layers */
-
- lcp_sendreply(sp,TERMINATE_ACK,0,NULLBUF);
- lcp_reset(pppiop);
- pppiop->state = PPP_CLOSED;
- return;
- }
-
- /*******************************************/
-
- /* Process configuration ACK send by remote host */
- static int
- lcp_chkack(sp, ackcnf, data)
- struct slip *sp;
- struct cnfhdr *ackcnf;
- struct mbuf *data;
- {
- int ackerr = 0;
- struct pppctl *pppiop;
- struct lcpctl *lcpiop;
- struct mbuf *req_bp;
- struct opthdr reqopt;
- struct opthdr ackopt;
- int16 reqi16, acki16;
- int32 reqi32, acki32;
-
- if (Ppptrace > 5)
- log(-1,"lcp_chkack()");
-
- pppiop = sp->pppio;
- lcpiop = &(pppiop->lcpio);
-
- /* LCP ID field must match last request we sent */
- if (ackcnf->id != lcpiop->lastid) {
- if (Ppptrace > 1)
- log(-1,"improper LCP ACK; bad ID");
- free_p(data);
- return -1;
- }
-
- /* Get a copy of last request we sent */
- req_bp = lcp_makereq(&(lcpiop->lclparm));
-
- /* Overall buffer length should match */
- if (ackcnf->len != len_p(req_bp)) {
- ackerr = 1;
- }
-
- /* ACK must echo all options we requested in the order requested */
- while ((ntohopt(&reqopt, &req_bp) != -1) && (!ackerr)) {
- /* Get config option from ACK packet */
- if (ntohopt(&ackopt, &data) == -1) {
- /* Must have as many acked options as requested */
- ackerr = 1;
- break;
- }
-
- /* Config option headers must match */
- if ((ackopt.type != reqopt.type)
- ||(ackopt.len != reqopt.len)) {
- ackerr = 1;
- break;
- }
-
- /* Config option values must match */
- switch(reqopt.type) {
- case MAX_RCV_UNIT: /* Maximum Receive Unit */
- case AUTH_TYPE: /* Authentication Protocol Type */
- acki16 = pull16(&data);
- reqi16 = pull16(&req_bp);
- if (acki16 != reqi16) {
- ackerr = 1;
- }
- break;
- case MAGIC_NUMBER: /* Magic Number */
- case ASYNC_CTL_MAP: /* Async Control Map */
- acki32 = pull32(&data);
- reqi32 = pull32(&req_bp);
- if (acki32 != reqi32) {
- ackerr = 1;
- }
- break;
- case PROT_COMPRESS: /* Protocol Compression */
- case AC_COMPRESS: /* Addr/Control Compression */
- /* Option ON if requested */
- break;
-
- case ENCR_TYPE: /* Encryption type not implemented */
- case LINK_QUALITY: /* Link Qual Monitor not implemented */
- default: /* Shouldnt happen */
- ackerr = 1;
- break;
- }
- }
-
- free_p(req_bp);
- free_p(data);
-
- if (ackerr) {
- /* Error in configuration ACK */
- if (Ppptrace > 5)
- log(-1,"improper LCP ACK echo");
- return -1;
- }
-
- /* ACK matches last request we made */
- if (Ppptrace > 5)
- log(-1,"valid LCP ACK echo");
- return 0;
- }
-
- /* Process configuration NAK send by remote host */
- static int
- lcp_chknak(sp, nakcnf, data)
- struct slip *sp;
- struct cnfhdr *nakcnf;
- struct mbuf *data;
- {
- int nakerr = 0;
- struct pppctl *pppiop;
- struct lcpctl *lcpiop;
- struct lcpparm *localp;
- struct mbuf *req_bp;
- struct opthdr reqopt;
- struct opthdr nakopt;
- int16 naki16;
- int32 naki32;
-
- if (Ppptrace > 5)
- log(-1,"lcp_chknak()");
-
- pppiop = sp->pppio;
- lcpiop = &(pppiop->lcpio);
- localp = &(lcpiop->lclparm);
-
- /* LCP ID field must match last request we sent */
- if (nakcnf->id != lcpiop->lastid) {
- if (Ppptrace > 1)
- log(-1,"improper LCP NAK; bad ID");
- free_p(data);
- return -1;
- }
-
- /* Get a copy of last request we sent */
- req_bp = lcp_makereq(&(lcpiop->lclparm));
-
- /* Check overall buffer length */
- if (nakcnf->len > len_p(req_bp)) {
- /* Remote cant NAK more options than we requested */
- nakerr = 1;
- }
-
- /* NAKed options must be same order as our original request */
- while ((ntohopt(&nakopt, &data) != -1) && (!nakerr)) {
- /* Get config option from our request */
- if (ntohopt(&reqopt, &req_bp) == -1) {
- /* Must find match to each NAKed option */
- nakerr = 1;
- break;
- }
-
- /* Maybe not all options were NAKed; look */
- /* for matching option in our request */
- while (reqopt.type != nakopt.type) {
- /* This option not NAKed; eat rest */
- /* of option from the request packet */
- reqopt.len -= 2;
- while (reqopt.len--)
- pullchar(&req_bp);
-
- /* Get next config option from our request */
- if (ntohopt(&reqopt, &req_bp) == -1) {
- /* Must find match to each NAKed option */
- reqopt.type = 0;
- nakerr = 1;
- break;
- }
- }
-
- /* Config option headers must match */
- if ((nakopt.type != reqopt.type)
- ||(nakopt.len != reqopt.len)) {
- nakerr = 1;
- break;
- }
-
- /* Remote host replaced our request with new suggestion */
- switch(reqopt.type) {
- case MAX_RCV_UNIT: /* Maximum Receive Unit */
- /* Get suggested MRU */
- naki16 = pull16(&data);
- /* Eat MRU from our request packet */
- pull16(&req_bp);
-
- if ((naki16 < MIN_MRU)||(naki16 > DEF_MRU))
- naki16 = DEF_MRU;
-
- /* Save new request value */
- localp->mru = naki16;
- break;
- case ASYNC_CTL_MAP: /* Async Control Map */
- /* Get suggested control map */
- naki32 = pull32(&data);
- /* Eat control map from our request packet */
- pull32(&req_bp);
-
- /* Remote host may ask to escape more control */
- /* characters than we require, but must escape */
- /* at least the control chars that we require. */
- if (naki32 != (naki32 | lcpiop->initparm.ctl_map))
- naki32 = lcpiop->initparm.ctl_map;
-
- /* Save new request value */
- localp->ctl_map = naki32;
- break;
- case AUTH_TYPE: /* Authentication Protocol Type */
- /* Get suggested Auth Protocol */
- naki16 = pull16(&data);
- /* Eat auth type from our request packet */
- pull16(&req_bp);
-
- /* Can only accept auth protocols we know */
- if (naki16 != PAP_AUTH_TYPE) {
- /* Abandon request for auth type */
- /* Wont open LCP layer without auth protocol */
- naki16 = DEF_AUTH_TYPE;
- }
-
- /* Save new request value */
- localp->mru = naki16;
- break;
- case MAGIC_NUMBER: /* Magic Number */
- /* Get suggested magic number */
- naki32 = pull32(&data);
- /* Eat magic number from our request packet */
- pull32(&req_bp);
-
- /* Try to prevent matching magic numbers */
-
- /* Save new request value */
- localp->magic_num = naki32;
- break;
- case PROT_COMPRESS:
- /* Remote host says no protocol compression */
- localp->neg_prot_compress = 0;
- localp->prot_compress = DEF_PROT_COMPR;
- break;
- case AC_COMPRESS:
- /* Remote host says no addr/ctl compression */
- localp->neg_ac_compress = 0;
- localp->ac_compress = DEF_AC_COMPR;
- break;
-
- case ENCR_TYPE: /* Encryption type not implemented */
- case LINK_QUALITY: /* Link Qual Monitor not implemented */
- default: /* Shouldnt happen */
- nakerr = 1;
- break;
- }
- }
-
- free_p(req_bp);
- free_p(data);
-
- if (nakerr) {
- /* Error in configuration NAK */
- if (Ppptrace > 5)
- log(-1,"improper LCP NAK echo");
- return -1;
- }
-
- /* NAK matches last request we made */
- if (Ppptrace > 5)
- log(-1,"valid LCP NAK echo");
- return 0;
- }
-
- /* Process configuration reject send by remote host */
- static int
- lcp_chkrej(sp, rejcnf, data)
- struct slip *sp;
- struct cnfhdr *rejcnf;
- struct mbuf *data;
- {
- int rejerr = 0;
- struct pppctl *pppiop;
- struct lcpctl *lcpiop;
- struct lcpparm *localp;
- struct mbuf *req_bp;
- struct opthdr reqopt;
- struct opthdr rejopt;
-
- if (Ppptrace > 5)
- log(-1,"lcp_chkrej()");
-
- pppiop = sp->pppio;
- lcpiop = &(pppiop->lcpio);
- localp = &(lcpiop->lclparm);
-
- /* LCP ID field must match last request we sent */
- if (rejcnf->id != lcpiop->lastid) {
- if (Ppptrace > 1)
- log(-1,"improper LCP REJ; bad ID");
- free_p(data);
- return -1;
- }
-
- /* Get a copy of last request we sent */
- req_bp = lcp_makereq(&(lcpiop->lclparm));
-
- /* Check overall buffer length */
- if (rejcnf->len > len_p(req_bp)) {
- /* Remote cant NAK more options than we requested */
- rejerr = 1;
- }
-
- /* Rejected options must be same order as our original request */
- while ((ntohopt(&rejopt, &data) != -1) && (!rejerr)) {
- /* Get config option from our request */
- if (ntohopt(&reqopt, &req_bp) == -1) {
- /* Must find match to each NAKed option */
- rejerr = 1;
- break;
- }
-
- /* Maybe not all options were NAKed; look */
- /* for matching option in our request */
- while (reqopt.type != rejopt.type) {
- /* This option not NAKed; eat rest */
- /* of option from the request packet */
- reqopt.len -= 2;
- while (reqopt.len--)
- pullchar(&req_bp);
-
- /* Get next config option from our request */
- if (ntohopt(&reqopt, &req_bp) == -1) {
- /* Must find match to each NAKed option */
- reqopt.type = 0;
- rejerr = 1;
- break;
- }
- }
-
- /* Config option headers must match */
- if ((rejopt.type != reqopt.type)
- ||(rejopt.len != reqopt.len)) {
- rejerr = 1;
- break;
- }
-
- /* Remote host wont negotiate this option */
- switch(reqopt.type) {
- case MAX_RCV_UNIT: /* Maximum Receive Unit */
- /* Eat MRU value from config packets */
- pull16(&data);
- pull16(&req_bp);
-
- /* Dont attempt to negotiate MRU */
- localp->neg_mru = 0;
- localp->mru = DEF_MRU;
- break;
- case ASYNC_CTL_MAP: /* Async Control Map */
- /* Eat control map value from config packets */
- pull32(&data);
- pull32(&req_bp);
-
- /* Dont attempt to negotiate control map */
- localp->neg_ctl_map = 0;
- localp->ctl_map = DEF_CTL_MAP;
- break;
- case AUTH_TYPE: /* Authentication Protocol Type */
- /* Eat auth type value from config packets */
- pull16(&data);
- pull16(&req_bp);
-
- /* Dont attempt to negotiate auth type */
- /* Wont open LCP layer without auth protocol */
- localp->neg_auth_type = 0;
- localp->auth_type = DEF_AUTH_TYPE;
- break;
- case MAGIC_NUMBER: /* Magic Number */
- /* Eat magic number value from config packets */
- pull32(&data);
- pull32(&req_bp);
-
- /* Dont attempt to negotiate control map */
- localp->neg_magic_num = 0;
- localp->magic_num = DEF_MAGIC_NUM;
- break;
- case PROT_COMPRESS: /* Protocol Compression */
- /* Abandon attempt to use protocol compression */
- localp->neg_prot_compress = 0;
- localp->prot_compress = DEF_PROT_COMPR;
- break;
- case AC_COMPRESS: /* Addr/Ctl Compression */
- /* Abandon attempt to use addr/ctl compression */
- localp->neg_ac_compress = 0;
- localp->ac_compress = DEF_AC_COMPR;
- break;
-
- case ENCR_TYPE: /* Encryption type not implemented */
- case LINK_QUALITY: /* Link Qual Monitor not implemented */
- default: /* Shouldnt happen */
- rejerr = 1;
- break;
- }
- }
-
- free_p(req_bp);
- free_p(data);
-
- if (rejerr) {
- /* Error in configuration reject */
- if (Ppptrace > 5)
- log(-1,"improper LCP REJ echo");
- return -1;
- }
-
- /* Reject matches last request we made */
- if (Ppptrace > 5)
- log(-1,"valid LCP REJ echo");
- return 0;
- }
-
- /* Check Link Control options requested by the remote host */
- static void
- lcp_chkreq(sp, reqcnf, data)
- struct slip *sp;
- struct cnfhdr *reqcnf;
- struct mbuf *data;
- {
- struct pppctl *pppiop;
- struct lcpctl *lcpiop;
- int ilen;
- int16 i16;
- int32 i32;
- register char *cp;
- char cnf_accept = CONFIG_ACK; /* Overall reply to request */
- char opt_accept; /* Per option reply */
- struct opthdr reqopt; /* Per option header storage */
- struct opthdr replyopt; /* For building reply */
- struct lcpparm *remotep; /* Ptr to remote options */
- struct lcpparm *initp; /* Ptr to initial lcl opts */
- struct mbuf *bp; /* Ptr for building reply */
- struct mbuf *reply_bp = NULLBUF; /* Actual reply packet */
-
- if (Ppptrace > 5)
- log(-1, "lcp_chkreq()");
-
- pppiop = sp->pppio;
- lcpiop = &(pppiop->lcpio);
- remotep = &(lcpiop->remparm);
- initp = &(lcpiop->initparm);
-
- /* Make sure length in LCP config header is realistic */
- i16 = len_p(data);
- if (i16 < reqcnf->len)
- reqcnf->len = i16;
-
- /* Process options requested by remote host */
- while (reqcnf->len > 0) {
- /* Get header for next option */
- if (ntohopt(&reqopt, &data) == -1)
- break;
-
- reqcnf->len -= reqopt.len; /* Count bytes this option */
- reqopt.len -= 2; /* Get data len this option */
- opt_accept = CONFIG_ACK; /* Assume will accept option */
-
- switch(reqopt.type) {
- case MAX_RCV_UNIT:
- if (Ppptrace > 5)
- log(-1, "remote asking for MRU");
-
- /* Max Receive Unit is a 16bit field */
- ilen = 2;
- if (reqopt.len < ilen) {
- /* Short option data; reject packet */
- opt_accept = CONFIG_REJ;
- i16 = DEF_MRU;
- break;
- }
- /* Get proposed value from packet */
- i16 = pull16(&data);
- if ((remotep->neg_mru == 0) && (i16 != DEF_MRU)) {
- /* Not open for negotiation */
- opt_accept = CONFIG_REJ;
- break;
- }
- /* Check if new value is appropriate */
- if (i16 < MIN_MRU) {
- /* Too small, ask for minimum instead */
- opt_accept = CONFIG_NAK;
- i16 = MIN_MRU;
- } else if (i16 > DEF_MRU) {
- /* Too big, tell largest value we can use */
- opt_accept = CONFIG_NAK;
- i16 = DEF_MRU;
- } else {
- /* Value is acceptable */
- opt_accept = CONFIG_ACK;
- }
- remotep->mru = i16;
- break;
- case ASYNC_CTL_MAP: /* Async Control Map */
- if (Ppptrace > 5)
- log(-1, "remote asking for async control map");
- /* Async control map is a 32bit field */
- ilen = 4;
- if (reqopt.len < ilen) {
- /* Short option data; reject packet */
- opt_accept = CONFIG_REJ;
- i32 = DEF_CTL_MAP;
- break;
- }
- /* Get proposed value from packet */
- i32 = pull32(&data);
- if ((remotep->neg_ctl_map == 0)
- && (i32 != DEF_CTL_MAP)) {
- /* Not open for negotiation */
- opt_accept = CONFIG_REJ;
- break;
- }
-
- /* Record new async control character map */
- opt_accept = CONFIG_ACK;
- remotep->ctl_map = i32;
- break;
- case AUTH_TYPE:
- if (Ppptrace > 5)
- log(-1, "remote asking for Auth Protocol type");
-
- /* Auth Protocol Type is a 16bit field */
- ilen = 2;
- if (reqopt.len < ilen) {
- /* Short option data; reject packet */
- opt_accept = CONFIG_REJ;
- i16 = DEF_MRU;
- break;
- }
- /* Get proposed value from packet */
- i16 = pull16(&data);
- if ((initp->neg_auth_type == 1)
- && (initp->auth_type != DEF_AUTH_TYPE)) {
- /* We are requesting auth too; */
- /* we only know PAP auth protocol */
- /* PAP is a one-way authentication protocol */
- opt_accept = CONFIG_REJ;
- break;
- }
- if ((remotep->neg_auth_type == 0)
- && (i16 != DEF_AUTH_TYPE)) {
- /* Not open for negotiation */
- opt_accept = CONFIG_REJ;
- break;
- }
- /* Check if new value is appropriate */
- if (i16 == PAP_AUTH_TYPE) {
- /* Yes, we know Password Auth Protocol */
- opt_accept = CONFIG_ACK;
- } else {
- /* We dont know this protocol */
- opt_accept = CONFIG_NAK;
- i16 = PAP_AUTH_TYPE;
- }
- remotep->auth_type = i16;
- break;
- case MAGIC_NUMBER: /* Magic Number */
- if (Ppptrace > 5)
- log(-1, "remote asking for magic number");
- /* Magic number is a 32bit field */
- ilen = 4;
- if (reqopt.len < ilen) {
- /* Short option data; reject packet */
- opt_accept = CONFIG_REJ;
- i32 = 0L;
- break;
- }
- /* Get proposed value from packet */
- i32 = pull32(&data);
- if ((remotep->neg_magic_num == 0)
- || (i32 == 0L)) {
- /* Not open for negotiation */
- opt_accept = CONFIG_REJ;
- break;
- }
-
- /* Remote host cant use same magic number as us */
- if (i32 == lcpiop->lclparm.magic_num) {
- opt_accept = CONFIG_NAK;
- ++i32;
- break;
- }
-
- /* Record new async control character map */
- opt_accept = CONFIG_ACK;
- remotep->magic_num = i32;
- break;
- case PROT_COMPRESS:
- if (Ppptrace > 5)
- log(-1, "remote asking for protocol compression");
- /* Presence of option means do protcol compression */
- ilen = 0;
- if ((remotep->neg_prot_compress == 0)
- && (!DEF_PROT_COMPR)) {
- /* We wont do protocol compression */
- opt_accept = CONFIG_REJ;
- break;
- }
-
- /* Accept request for protocol compression */
- opt_accept = CONFIG_ACK;
- remotep->prot_compress = 1;
- break;
- case AC_COMPRESS:
- if (Ppptrace > 5)
- log(-1, "remote asking for addr/ctl compression");
- /* Presence of option means do addr/ctl compression */
- ilen = 0;
- if ((remotep->neg_ac_compress == 0)
- && (!DEF_AC_COMPR)) {
- /* We wont do addr/ctl compression */
- opt_accept = CONFIG_REJ;
- break;
- }
-
- /* Accept request for addr/ctl compression */
- opt_accept = CONFIG_ACK;
- remotep->ac_compress = 1;
- break;
-
- case ENCR_TYPE: /* Encryption type not implemented */
- case LINK_QUALITY: /* Link Qual Monitor not implemented */
- default: /* Unknown option */
- if (Ppptrace > 5)
- log(-1, "remote asking for unimplemented option: %x len: %d",
- reqopt.type, reqopt.len);
- opt_accept = CONFIG_REJ;
- ilen = reqopt.len;
- if (len_p(data) < ilen)
- ilen = len_p(data);
- /* Look for standard sizes */
- if (ilen == 2)
- i16 = pull16(&data);
- else if (ilen == 4) {
- i32 = pull32(&data);
- }
- /* Other lengths dequeued at echo time */
-
- break;
- }
- if ((opt_accept == CONFIG_ACK) &&
- (cnf_accept != CONFIG_ACK))
- /* This option was good, but a previous */
- /* option was not. Return only those options */
- /* which are being nacked/rejected. */
- continue;
-
- if (opt_accept == CONFIG_NAK) {
- if (cnf_accept == CONFIG_REJ)
- /* Return only those options */
- /* which are being rejected. */
- continue;
- if (cnf_accept == CONFIG_ACK) {
- /* Discard current list of good options */
- free_p(reply_bp);
- reply_bp = NULLBUF;
- /* Send a list of nacked options */
- cnf_accept = CONFIG_NAK;
- }
- }
-
- if (opt_accept == CONFIG_REJ) {
- if (cnf_accept != CONFIG_REJ) {
- /* Discard current list of good options */
- free_p(reply_bp);
- reply_bp = NULLBUF;
- /* Send a list of rejected options */
- cnf_accept = CONFIG_REJ;
- }
- }
-
- /* Add option response to the return list */
- replyopt.type = reqopt.type;
- replyopt.len = ilen + OPT_HDRLEN;
- if ((bp = htonopt(&replyopt)) == NULLBUF)
- break;
- append(&reply_bp,bp);
- if (ilen) {
- if ((bp = alloc_mbuf(ilen)) == NULLBUF)
- break;
- cp = bp->data;
- switch(ilen) {
- case 2:
- put16(cp,i16);
- bp->cnt += 2;
- break;
- case 4:
- put32(cp,i32);
- bp->cnt += 4;
- break;
- default:
- while (ilen--)
- bp->data[bp->cnt++] = pullchar(&data);
- }
- append(&reply_bp,bp);
- }
- }
-
- /* Send ACK/NAK/REJ to remote host */
- if (cnf_accept == CONFIG_ACK) {
- if (Ppptrace > 1)
- log(-1, "accept all options requested by remote peer");
-
- /* Accept configuration requested by remote host */
- lcp_sendreply(sp, CONFIG_ACK, reqcnf->id, reply_bp);
- if (lcpiop->lcp_state == LCP_REQ_SENT) {
- lcpiop->lcp_state = LCP_ACK_SENT;
- } else {
- /* LCP link now open */
- lcp_open(sp);
- }
- } else {
- if (Ppptrace > 1)
- log(-1,"options requested by remote peer not accepted: %s",
- ((cnf_accept==CONFIG_NAK) ? "NAK" : "REJ"));
-
- /* NAK/REJ config request made by remote host */
- lcp_sendreply(sp, cnf_accept, reqcnf->id, reply_bp);
-
- /* Start timer against wait for amended config request */
- if (lcpiop->lcp_state == LCP_ACK_RCVD)
- lcp_timer(sp);
- }
- free_p(data);
- return;
- }
-
- /****************************************************************************/
-
- /* Timeout while waiting for reply from remote host */
- static void
- lcp_timeout(vp)
- void *vp;
- {
- struct slip *sp;
- struct pppctl *pppiop;
- struct lcpctl *lcpiop;
-
- if (Ppptrace > 1)
- log(-1, "lcp_timeout()");
-
- /* Load pointers to interface that timed-out */
- sp = (struct slip *)vp;
- pppiop = sp->pppio;
- lcpiop = &(pppiop->lcpio);
-
- /* Attempt to get things going again */
- switch(lcpiop->lcp_state) {
- case LCP_ACK_SENT:
- /* Remote host isnt listening to our request */
- lcp_reset(pppiop);
- case LCP_REQ_SENT:
- case LCP_ACK_RCVD:
- if (lcpiop->active == 0) {
- /* If passive open, we got a CONFIG_REQ from remote */
- /* host but no ACK in response to our CONFIG_REQ */
- if (++lcpiop->ack_retry > LCP_RETRY_MAX) {
- /* Remote host doesnt seem to be listening */
- lcp_shutdown(sp);
- break;
- }
- }
- /* Timeout waiting for ACK to our request, */
- /* or timeout waiting for request from remote host */
- lcp_sendreq(sp);
- break;
-
- case LCP_TERMINATE:
- /* Timeout waiting for terminate ACK; send another request */
- if (++lcpiop->ack_retry > LCP_TERM_RETRY) {
- /* No response to our polite request; give it up */
-
- if (Ppptrace)
- log(-1,"%s: PPP/LCP Connection Closed without reply from remote peer",sp->iface->name);
- if (lcpiop->active == 0)
- lcpiop->lcp_state = LCP_LISTEN;
- else
- lcpiop->lcp_state = LCP_CLOSED;
-
- lcp_sendreply(sp,TERMINATE_ACK,0,NULLBUF);
- lcp_reset(pppiop);
- tprintf("Still no response; marking LCP layer as closed\n");
- pppiop->state = PPP_CLOSED;
- psignal(lcpiop,0);
- } else {
- /* Request remote host to close data link */
- tprintf("Timeout waiting for response to our LCP terminate request\n");
- lcp_timer(sp);
- lcp_sendreply(sp, TERMINATE_REQ, 0, NULLBUF);
- }
- break;
-
- case LCP_CLOSED:
- case LCP_LISTEN:
- case LCP_OPEN:
- default:
- /* Confusion; shutdown the connection */
- lcp_shutdown(sp);
- break;
- }
- return;
- }
-
- /* Set a timer in case an expected event does not occur */
- static void
- lcp_timer(sp)
- struct slip *sp;
- {
- struct pppctl *pppiop;
- struct lcpctl *lcpiop;
- struct timer *t;
-
- if (Ppptrace > 5)
- log(-1,"lcp_timer()");
-
- pppiop = sp->pppio;
- lcpiop = &(pppiop->lcpio);
- t = &(lcpiop->lcp_tm);
- t->func = (void (*)())lcp_timeout;
- t->arg = (void *)sp;
- start_timer(t);
- return;
- }
-
- /****************************************************************************/
-
- /* Send an LCP packet to the remote host */
- static int
- lcp_sendreply(sp,code,id,data)
- struct slip *sp;
- char code;
- unsigned char id;
- struct mbuf *data;
- {
- struct iface *iface;
- struct cnfhdr hdr;
-
- /* Load LCP header values */
- hdr.code = code;
- switch(code) {
- case CONFIG_REQ:
- case TERMINATE_REQ:
- case ECHO_REQ:
- /* Save ID field for match aginst replies from remote host */
- sp->pppio->lcpio.lastid = Pppid;
- case PROT_REJ:
- case DISCARD_REQ:
- /* Use a unique ID field value */
- hdr.id = Pppid++;
- break;
-
- case CONFIG_ACK:
- case CONFIG_NAK:
- case CONFIG_REJ:
- case TERMINATE_ACK:
- case CODE_REJ:
- case ECHO_REPLY:
- /* Use ID sent by remote host */
- hdr.id = id;
- break;
-
- default:
- /* Shouldnt happen */
- if (Ppptrace)
- log(-1, "bogus code: %x", code);
- return -1;
- }
- hdr.len = len_p(data) + CNF_HDRLEN;
- if (Ppptrace > 1) {
- log(-1, "%s: PPP/LCP Send: current state: %s LCP option: %s id: %d len: %d",
- sp->iface->name,
- LCPStates[sp->pppio->lcpio.lcp_state],
- LCPCodes[code],hdr.id,hdr.len);
- }
-
- /* Prepend LCP header to packet data */
- if ((data = htoncnf(&hdr,data)) == NULLBUF)
- return -1;
-
- /* Send LCP packet to remote host */
- sp->pppio->sndlcp++;
- iface = sp->iface;
- return( (*iface->output)
- (iface, NULLCHAR, NULLCHAR, PPP_LCP_TYPE, data) );
- }
-
- /* Process incoming LCP packet */
- void
- lcpproc(iface,bp)
- struct iface *iface;
- struct mbuf *bp;
- {
- struct slip *sp;
- struct cnfhdr hdr;
-
- sp = &Slip[iface->xdev];
-
- /* Extract LCP header */
- ntohcnf(&hdr, &bp);
- hdr.len -= CNF_HDRLEN; /* Length includes envelope */
- trim_mbuf(&bp, hdr.len); /* Trim off FCS bytes */
-
- if (Ppptrace > 1)
- log(-1, "%s: PPP/LCP Recv: current state: %s: LCP option: %s id: %d len: %d",
- iface->name,
- LCPStates[sp->pppio->lcpio.lcp_state],
- LCPCodes[hdr.code], hdr.id, hdr.len);
-
- /* Process LCP packet data */
- switch(hdr.code) {
- case CONFIG_REQ: /* Request of remote host */
- lcp_rcvreq(sp, &hdr, bp);
- break;
- case CONFIG_ACK: /* Remote accepted our req */
- lcp_rcvack(sp, &hdr, bp);
- break;
- case CONFIG_NAK: /* Remote adjusted our req */
- lcp_rcvnak(sp, &hdr, bp);
- break;
- case CONFIG_REJ: /* Remote rejected our req */
- lcp_rcvrej(sp, &hdr, bp);
- break;
- case TERMINATE_REQ: /* Remote request to close */
- lcp_rcvtermreq(sp, &hdr);
- break;
- case TERMINATE_ACK: /* Remote closed on request */
- lcp_rcvtermack(sp);
- break;
-
- case CODE_REJ:
- case PROT_REJ:
- case ECHO_REQ:
- case ECHO_REPLY:
- case DISCARD_REQ:
- if (Ppptrace)
- log(-1,"Unimplemented LCP packet type: %x; dropping packet",hdr.code);
- free_p(bp);
- break;
- default:
- if (Ppptrace)
- log(-1,"Unknown LCP packet type: %x; dropping packet",hdr.code);
- free_p(bp);
- break;
- }
- return;
- }
-