home *** CD-ROM | disk | FTP | other *** search
- /*
- * lcp.c - PPP Link Control Protocol.
- *
- * Copyright (c) 1989 Carnegie Mellon University.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Carnegie Mellon University. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
- /*
- * TODO:
- * Keepalive.
- * Encryption.
- * Send NAKs for unsent CIs.
- * Keep separate MTU, MRU.
- * Option tracing.
- * Extra data on authtype option.
- * Test restart.
- */
-
- #include <stdio.h>
- #include <sys/ioctl.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/time.h>
-
- #include <net/if.h>
- #include <netinet/in.h>
-
- #include "ppp.h"
- #include "fsm.h"
- #include "lcp.h"
-
-
- void lcp_resetci(); /* Reset our Configuration Information */
- int lcp_cilen(); /* Return length of our CI */
- void lcp_addci(); /* Add our CIs */
- int lcp_ackci(); /* Ack some CIs */
- void lcp_nakci(); /* Nak some CIs */
- void lcp_rejci(); /* Reject some CIs */
- u_char lcp_reqci(); /* Check the requested CIs */
- void lcp_up(); /* We're UP */
- void lcp_down(); /* We're DOWN */
- void lcp_closed(); /* We're CLOSED */
-
-
- fsm lcp_fsm[NPPP]; /* LCP fsm structure */
-
- fsm_callbacks lcp_callbacks = { /* LCP callback routines */
- lcp_resetci, /* Reset our Configuration Information */
- lcp_cilen, /* Length of our Configuration Information */
- lcp_addci, /* Add our Configuration Information */
- lcp_ackci, /* ACK our Configuration Information */
- lcp_nakci, /* NAK our Configuration Information */
- lcp_rejci, /* Reject our Configuration Information */
- lcp_reqci, /* Request peer's Configuration Information */
- lcp_up, /* Called when fsm reaches OPEN state */
- lcp_down, /* Called when fsm leaves OPEN state */
- lcp_closed, /* Called when fsm reaches CLOSED state */
- NULL, /* Called when Protocol-Reject received */
- NULL /* Retransmission is necessary */
- };
-
-
- lcp_options lcp_wantoptions[NPPP]; /* Options that we want to request */
- lcp_options lcp_gotoptions[NPPP]; /* Options that peer ack'd */
- lcp_options lcp_allowoptions[NPPP]; /* Options that we allow peer to request */
- lcp_options lcp_hisoptions[NPPP]; /* Options that we ack'd */
-
-
- #define DEFWARNLOOPS 10 /* XXX Move to lcp.h */
- int lcp_warnloops = DEFWARNLOOPS; /* Warn about a loopback this often */
-
-
- /*
- * lcp_init - Initialize LCP.
- */
- void lcp_init(unit)
- int unit;
- {
- fsm *f = &lcp_fsm[unit];
- lcp_options *wo = &lcp_wantoptions[unit];
- lcp_options *ao = &lcp_allowoptions[unit];
-
- f->unit = unit;
- f->protocol = LCP;
- f->timeouttime = DEFTIMEOUT;
- f->maxtermtransmits = DEFMAXTERMTRANSMITS;
- f->maxnakloops = DEFMAXNAKLOOPS;
- f->callbacks = &lcp_callbacks;
-
- wo->passive = 0;
- wo->restart = 0; /* Set to 1 in kernels or multi-line
- implementations */
-
- wo->neg_mru = 1;
- wo->mru = DEFMRU;
- wo->neg_asyncmap = 1;
- wo->asyncmap = 0;
- wo->neg_upap = 0; /* Set to 1 on server */
- wo->neg_encrypttype = 0;
- wo->encrypttype = 0;
- wo->neg_magicnumber = 1;
- #if 0
- wo->neg_keepalive = 0;
- #endif
- wo->neg_pcompression = 1;
- wo->neg_accompression = 1;
-
- ao->neg_mru = 1;
- ao->neg_asyncmap = 1;
- ao->neg_upap = 0; /* Set to 1 on client */
- ao->neg_encrypttype = 0;
- ao->neg_magicnumber = 1;
- #if 0
- ao->neg_keepalive = 0;
- #endif
- ao->neg_pcompression = 1;
- ao->neg_accompression = 1;
-
- fsm_init(f);
- }
-
-
- /*
- * lcp_activeopen - Actively open LCP.
- */
- void lcp_activeopen(unit)
- int unit;
- {
- fsm_activeopen(&lcp_fsm[unit]);
- }
-
-
- /*
- * lcp_passiveopen - Passively open LCP.
- */
- void lcp_passiveopen(unit)
- int unit;
- {
- fsm_passiveopen(&lcp_fsm[unit]);
- }
-
-
- /*
- * lcp_close - Close LCP.
- */
- void lcp_close(unit)
- int unit;
- {
- fsm_close(&lcp_fsm[unit]);
- }
-
-
- /*
- * lcp_lowerup - The lower layer is up.
- */
- void lcp_lowerup(unit)
- int unit;
- {
- SIFDOWN(unit);
- SIFMTU(unit, MTU);
- SIFASYNCMAP(unit, 0xffffffff);
- CIFPCOMPRESSION(unit);
- CIFACCOMPRESSION(unit);
-
- fsm_lowerup(&lcp_fsm[unit]);
- }
-
-
- /*
- * lcp_lowerdown - The lower layer is down.
- */
- void lcp_lowerdown(unit)
- int unit;
- {
- fsm_lowerdown(&lcp_fsm[unit]);
- }
-
-
- /*
- * lcp_input - Input LCP packet.
- */
- void lcp_input(unit, p, len)
- int unit;
- PACKET *p;
- int len;
- {
- fsm_input(&lcp_fsm[unit], p, len);
- }
-
-
- /*
- * lcp_protrej - A Protocol-Reject was received.
- */
- void lcp_protrej(unit)
- int unit;
- {
- /*
- * Can't reject LCP!
- */
- FSMDEBUG((stderr,
- "ppp: lcp_protrej: Received Protocol-Reject for LCP!\n"));
- }
-
-
- /*
- * lcp_sprotrej - Send a Protocol-Reject for some protocol.
- */
- void lcp_sprotrej(unit, p, len)
- int unit;
- PACKET *p;
- int len;
- {
- fsm_sdata(&lcp_fsm[unit], PROTREJ, ++lcp_fsm[unit].id,
- PACKET_DATA(p), len);
- PACKET_FREE(p);
- }
-
-
- /*
- * lcp_resetci - Reset our CI.
- */
- void lcp_resetci(f)
- fsm *f;
- {
- lcp_wantoptions[f->unit].magicnumber = magic();
- lcp_wantoptions[f->unit].numloops = 0;
- lcp_gotoptions[f->unit] = lcp_wantoptions[f->unit];
- }
-
-
- /*
- * lcp_cilen - Return length of our CI.
- */
- int lcp_cilen(f)
- fsm *f;
- {
- lcp_options *go = &lcp_gotoptions[f->unit];
-
- #define LENCIVOID(neg) (neg ? 2 : 0)
- #define LENCISHORT(neg) (neg ? 4 : 0)
- #define LENCILONG(neg) (neg ? 6 : 0)
-
- return (LENCISHORT(go->neg_mru) +
- LENCILONG(go->neg_asyncmap) +
- LENCISHORT(go->neg_upap) +
- LENCISHORT(go->neg_encrypttype) +
- LENCILONG(go->neg_magicnumber) +
- #if 0
- LENCI(go->neg_keepalive) +
- #endif
- LENCIVOID(go->neg_pcompression) +
- LENCIVOID(go->neg_accompression));
- }
-
-
- /*
- * lcp_addci - Add our desired CIs to a packet.
- */
- void lcp_addci(f, ucp)
- fsm *f;
- u_char *ucp;
- {
- lcp_options *go = &lcp_gotoptions[f->unit];
-
- #define ADDCIVOID(opt, neg) \
- if (neg) { \
- PUTCHAR(opt, ucp); \
- PUTCHAR(2, ucp); \
- }
- #define ADDCISHORT(opt, neg, val) \
- if (neg) { \
- PUTCHAR(opt, ucp); \
- PUTCHAR(2 + sizeof (short), ucp); \
- PUTSHORT(val, ucp); \
- }
- #define ADDCILONG(opt, neg, val) \
- if (neg) { \
- PUTCHAR(opt, ucp); \
- PUTCHAR(2 + sizeof (long), ucp); \
- PUTLONG(val, ucp); \
- }
-
- ADDCISHORT(CI_MRU, go->neg_mru, go->mru)
- ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap, go->asyncmap)
- ADDCISHORT(CI_AUTHTYPE, go->neg_upap, UPAP)
- ADDCISHORT(CI_ENCRYPTTYPE, go->neg_encrypttype, go->encrypttype)
- ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber)
- #if 0
- ADDCI(CI_KEEPALIVE, go->neg_keepalive, go->keepalive)
- #endif
- ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression)
- ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression)
- }
-
-
- /*
- * lcp_ackci - Ack our CIs.
- *
- * Returns:
- * 0 - Ack was bad.
- * 1 - Ack was good.
- */
- int lcp_ackci(f, p, len)
- fsm *f;
- u_char *p;
- int len;
- {
- lcp_options *go = &lcp_gotoptions[f->unit];
- u_char cilen, citype;
- u_short cishort;
- u_long cilong;
-
- /*
- * CIs must be in exactly the same order that we sent.
- * Check packet length and CI length at each step.
- * If we find any deviations, then this packet is bad.
- */
- #define ACKCIVOID(opt, neg) \
- if (neg) { \
- if ((len -= 2) < 0) \
- goto bad; \
- GETCHAR(citype, p); \
- GETCHAR(cilen, p); \
- if (cilen != 2 || \
- citype != opt) \
- goto bad; \
- }
- #define ACKCISHORT(opt, neg, val) \
- if (neg) { \
- if ((len -= 2 + sizeof (short)) < 0) \
- goto bad; \
- GETCHAR(citype, p); \
- GETCHAR(cilen, p); \
- if (cilen != 2 + sizeof (short) || \
- citype != opt) \
- goto bad; \
- GETSHORT(cishort, p); \
- if (cishort != val) \
- goto bad; \
- }
- #define ACKCILONG(opt, neg, val) \
- if (neg) { \
- if ((len -= 2 + sizeof (long)) < 0) \
- goto bad; \
- GETCHAR(citype, p); \
- GETCHAR(cilen, p); \
- if (cilen != 2 + sizeof (long) || \
- citype != opt) \
- goto bad; \
- GETLONG(cilong, p); \
- if (cilong != val) \
- goto bad; \
- }
-
- ACKCISHORT(CI_MRU, go->neg_mru, go->mru)
- ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap, go->asyncmap)
- ACKCISHORT(CI_AUTHTYPE, go->neg_upap, UPAP)
- ACKCISHORT(CI_ENCRYPTTYPE, go->neg_encrypttype, go->encrypttype)
- ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber)
- #if 0
- ACKCI(CI_KEEPALIVE, go->neg_keepalive, go->keepalive)
- #endif
- ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression)
- ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression)
-
- /*
- * If there are any remaining CIs, then this packet is bad.
- */
- if (len != 0)
- goto bad;
- return (1);
- bad:
- LCPDEBUG((stderr, "ppp: lcp_acki: received bad Ack!\n"));
- return (0);
- }
-
-
- /*
- * lcp_nakci - NAK some of our CIs.
- */
- void lcp_nakci(f, p, len)
- fsm *f;
- u_char *p;
- int len;
- {
- lcp_options *go = &lcp_gotoptions[f->unit];
- lcp_options *wo = &lcp_wantoptions[f->unit];
- u_short cishort;
- u_long cilong;
-
- /*
- * Any Nak'd CIs must be in exactly the same order that we sent.
- * Check packet length and CI length at each step.
- * If we find any deviations, then this packet is bad.
- */
- #define NAKCIVOID(opt, neg, code) \
- if (neg && \
- len >= 2 && \
- p[1] == 2 && \
- p[0] == opt) { \
- len -= 2; \
- INCPTR(2, p); \
- code \
- }
- #define NAKCISHORT(opt, neg, code) \
- if (neg && \
- len >= 2 + sizeof (short) && \
- p[1] == 2 + sizeof (short) && \
- p[0] == opt) { \
- len -= 2 + sizeof (short); \
- INCPTR(2, p); \
- GETSHORT(cishort, p); \
- code \
- }
- #define NAKCILONG(opt, neg, code) \
- if (neg && \
- len >= 2 + sizeof (long) && \
- p[1] == 2 + sizeof (long) && \
- p[0] == opt) { \
- len -= 2 + sizeof (long); \
- INCPTR(2, p); \
- GETLONG(cilong, p); \
- code \
- }
-
- /*
- * We don't care if they want to send us smaller packets than
- * we want. Therefore, accept any MRU less than what we asked for,
- * but then ignore the new value when setting the MRU in the kernel.
- * If they send us a bigger MRU than what we asked, reject it and
- * let him decide to accept our value.
- */
- NAKCISHORT(CI_MRU, go->neg_mru,
- if (cishort <= wo->mru)
- go->mru = cishort;
- else
- goto bad;
- )
- NAKCILONG(CI_ASYNCMAP, go->neg_asyncmap,
- go->asyncmap |= cilong;
- )
- NAKCISHORT(CI_AUTHTYPE, go->neg_upap,
- fprintf(stderr, "ppp: Peer refuses to authenticate!\n");
- )
- NAKCISHORT(CI_ENCRYPTTYPE, go->neg_encrypttype,
- go->neg_encrypttype = 0;
- )
- NAKCILONG(CI_MAGICNUMBER, go->neg_magicnumber,
- go->magicnumber = magic();
- if (++go->numloops % lcp_warnloops == 0)
- fprintf(stderr, "ppp: The line appears to be looped back.\n");
- )
- #if 0
- NAKCI(CI_KEEPALIVE, go->neg_keepalive,
- )
- #endif
- NAKCIVOID(CI_PCOMPRESSION, go->neg_pcompression,
- go->neg_pcompression = 0;
- )
- NAKCIVOID(CI_ACCOMPRESSION, go->neg_accompression,
- go->neg_accompression = 0;
- )
-
- /*
- * If there are any remaining CIs, then this packet is bad.
- */
- if (len == 0)
- return;
- bad:
- LCPDEBUG((stderr, "ppp: lcp_nakci: received bad Nak!\n"));
- }
-
-
- /*
- * lcp_rejci - Reject some of our CIs.
- */
- void lcp_rejci(f, p, len)
- fsm *f;
- u_char *p;
- int len;
- {
- lcp_options *go = &lcp_gotoptions[f->unit];
- u_short cishort;
- u_long cilong;
-
- /*
- * Any Rejected CIs must be in exactly the same order that we sent.
- * Check packet length and CI length at each step.
- * If we find any deviations, then this packet is bad.
- */
- #define REJCIVOID(opt, neg) \
- if (neg && \
- len >= 2 && \
- p[1] == 2 && \
- p[0] == opt) { \
- len -= 2; \
- INCPTR(2, p); \
- neg = 0; \
- }
- #define REJCISHORT(opt, neg, val) \
- if (neg && \
- len >= 2 + sizeof (short) && \
- p[1] == 2 + sizeof (short) && \
- p[0] == opt) { \
- len -= 2 + sizeof (short); \
- INCPTR(2, p); \
- GETSHORT(cishort, p); \
- /* Check rejected value. */ \
- if (cishort != val) \
- goto bad; \
- neg = 0; \
- }
- #define REJCILONG(opt, neg, val) \
- if (neg && \
- len >= 2 + sizeof (long) && \
- p[1] == 2 + sizeof (long) && \
- p[0] == opt) { \
- len -= 2 + sizeof (long); \
- INCPTR(2, p); \
- GETLONG(cilong, p); \
- /* Check rejected value. */ \
- if (cilong != val) \
- goto bad; \
- neg = 0; \
- }
-
- REJCISHORT(CI_MRU, go->neg_mru, go->mru)
- REJCILONG(CI_ASYNCMAP, go->neg_asyncmap, go->asyncmap)
- REJCISHORT(CI_AUTHTYPE, go->neg_upap, UPAP)
- REJCISHORT(CI_ENCRYPTTYPE, go->neg_encrypttype, go->encrypttype)
- REJCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber)
- #if 0
- REJCI(CI_KEEPALIVE, go->neg_keepalive, go->keepalive)
- #endif
- REJCIVOID(CI_PCOMPRESSION, go->neg_pcompression)
- REJCIVOID(CI_ACCOMPRESSION, go->neg_accompression)
-
- /*
- * If there are any remaining CIs, then this packet is bad.
- */
- if (len == 0)
- return;
- bad:
- LCPDEBUG((stderr, "ppp: lcp_rejci: received bad Reject!\n"));
- }
-
-
- /*
- * lcp_reqci - Check the peer's requested CIs and send appropriate response.
- *
- * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
- * appropriately.
- */
- u_char lcp_reqci(f, inp, len)
- fsm *f;
- u_char *inp; /* Requested CIs */
- int *len; /* Length of requested CIs */
- {
- lcp_options *go = &lcp_gotoptions[f->unit];
- lcp_options *ho = &lcp_hisoptions[f->unit];
- lcp_options *ao = &lcp_allowoptions[f->unit];
- u_char *cip; /* Pointer to Current CI */
- u_char cilen, citype; /* Parsed len, type, char value */
- u_short cishort; /* Parsed short value */
- u_long cilong; /* Parse long value */
- int rc = CONFACK; /* Final packet return code */
- int orc; /* Individual option return code */
- u_char *p = inp; /* Pointer to next char to parse */
- u_char *ucp = inp; /* Pointer to current output char */
- int l = *len; /* Length left */
-
- /*
- * Reset all his options.
- */
- ho->neg_mru = 0;
- ho->neg_asyncmap = 0;
- ho->neg_upap = 0;
- ho->neg_encrypttype = 0;
- ho->neg_magicnumber = 0;
- #if 0
- ho->neg_keepalive = 0;
- #endif
- ho->neg_pcompression = 0;
- ho->neg_accompression = 0;
-
- /*
- * Process all his options.
- */
- while (l) {
- orc = CONFACK; /* Assume success */
- cip = p; /* Remember begining of CI */
- if (l < 2 || /* Not enough data for CI header or */
- p[1] < 2 || /* CI length too small or */
- p[1] > l) { /* CI length too big? */
- LCPDEBUG((stderr, "ppp: lcp_reqci: bad CI length!\n"));
- orc = CONFREJ; /* Reject bad CI */
- cilen = l; /* Reject till end of packet */
- l = 0; /* Don't loop again */
- goto endswitch;
- }
- GETCHAR(citype, p); /* Parse CI type */
- GETCHAR(cilen, p); /* Parse CI length */
- l -= cilen; /* Adjust remaining length */
- cilen -= 2; /* Adjust cilen to just data */
-
- switch (citype) { /* Check CI type */
- case CI_MRU:
- LCPDEBUG((stderr, "ppp: lcp_reqci: rcvd MRU"));
- if (!ao->neg_mru || /* Allow option? */
- cilen != sizeof (short)) { /* Check CI length */
- INCPTR(cilen, p); /* Skip rest of CI */
- orc = CONFREJ; /* Reject CI */
- break;
- }
- GETSHORT(cishort, p); /* Parse MRU */
- LCPDEBUG((stderr, "(%d)", cishort));
-
- /*
- * He must be able to receive at least our minimum.
- * No need to check a maximum. If he sends a large number,
- * we'll just ignore it.
- */
- if (cishort < MINMRU) {
- orc = CONFNAK; /* Nak CI */
- DECPTR(sizeof (short), p); /* Backup */
- PUTSHORT(MINMRU, p); /* Give him a hint */
- break;
- }
- ho->neg_mru = 1; /* Remember he sent and MRU */
- ho->mru = cishort; /* And remember value */
- break;
-
- case CI_ASYNCMAP:
- LCPDEBUG((stderr, "ppp: lcp_reqci: rcvd ASYNCMAP"));
- if (!ao->neg_asyncmap ||
- cilen != sizeof (long)) {
- INCPTR(cilen, p);
- orc = CONFREJ;
- break;
- }
- GETLONG(cilong, p);
- LCPDEBUG((stderr, "(%lx)", cilong));
-
- /* XXX Accept anything he says */
- #if 0
- /*
- * Asyncmap must be OR of two maps.
- */
- if ((lcp_wantoptions[f->unit].neg_asyncmap &&
- cilong != (lcp_wantoptions[f->unit].asyncmap | cilong)) ||
- (!lcp_wantoptions[f->unit].neg_asyncmap &&
- cilong != 0xffffffff)) {
- orc = CONFNAK;
- DECPTR(sizeof (long), p);
- PUTLONG(lcp_wantoptions[f->unit].neg_asyncmap ?
- lcp_wantoptions[f->unit].asyncmap | cilong :
- 0xffffffff, p);
- break;
- }
- #endif
- ho->neg_asyncmap = 1;
- ho->asyncmap = cilong;
- break;
-
- case CI_AUTHTYPE:
- LCPDEBUG((stderr, "ppp: lcp_reqci: rcvd AUTHTYPE"));
- if (!ao->neg_upap ||
- cilen < sizeof (short)) {
- INCPTR(cilen, p);
- orc = CONFREJ;
- break;
- }
- GETSHORT(cishort, p);
- LCPDEBUG((stderr, "(%x)", cishort));
-
- /*
- * Authtype must be UPAP.
- */
- if (cishort != UPAP) {
- DECPTR(sizeof (short), p);
- orc = CONFNAK;
- PUTSHORT(UPAP, p);
- INCPTR(cilen - sizeof (u_short), p);
- break;
- }
- INCPTR(cilen - sizeof (u_short), p);
- ho->neg_upap = 1;
- break;
-
- #if 0
- /* XXX */
- case CI_ENCRYPTTYPE:
- if (!ao->neg_encrypttype ||
- cilen != sizeof (short)) {
- INCPTR(cilen, p);
- orc = CONFREJ;
- break;
- }
- GETSHORT(cishort, p);
- LCPDEBUG((stderr, "(%d)", cishort));
-
- /*
- * Encrypttype must be XXX.
- */
- if (XXX) {
- DECPTR(sizeof (short), p);
- orc = CONFNAK;
- PUTSHORT(XXX, p);
- break;
- }
- ho->neg_encrypttype = 1;
- ho->encrypttype = cishort;
- break;
- #endif
-
- case CI_MAGICNUMBER:
- LCPDEBUG((stderr, "ppp: lcp_reqci: rcvd MAGICNUMBER"));
- if (!ao->neg_magicnumber ||
- cilen != sizeof (long)) {
- INCPTR(cilen, p);
- orc = CONFREJ;
- break;
- }
- GETLONG(cilong, p);
- LCPDEBUG((stderr, "(%lx)", cilong));
-
- /*
- * He must have a different magic number.
- */
- if (go->neg_magicnumber &&
- cilong == go->magicnumber) {
- orc = CONFNAK;
- DECPTR(sizeof (long), p);
- cilong = magic(); /* Don't put magic() inside macro! */
- PUTLONG(cilong, p);
- break;
- }
- ho->neg_magicnumber = 1;
- ho->magicnumber = cilong;
- break;
-
- #if 0
- case CI_KEEPALIVE:
- if (!ao->neg_keepalive ||
- cilen != )) {
- INCPTR(cilen, p);
- orc = CONFREJ;
- break;
- }
- GET(ci, p);
- LCPDEBUG((stderr, "(%d)", cishort));
-
- /*
- * He must XXX
- */
- if () {
- orc = CONFNAK;
- DECPTR(sizeof (), p);
- PUT(, p);
- break;
- }
- ho->neg_keepalive = 1;
- ho->keepalive = ;
- break;
- #endif
-
- case CI_PCOMPRESSION:
- LCPDEBUG((stderr, "ppp: lcp_reqci: rcvd PCOMPRESSION"));
- if (!ao->neg_pcompression ||
- cilen != 0) {
- INCPTR(cilen, p);
- orc = CONFREJ;
- break;
- }
- ho->neg_pcompression = 1;
- break;
-
- case CI_ACCOMPRESSION:
- LCPDEBUG((stderr, "ppp: lcp_reqci: rcvd ACCOMPRESSION"));
- if (!ao->neg_accompression ||
- cilen != 0) {
- INCPTR(cilen, p);
- orc = CONFREJ;
- break;
- }
- ho->neg_accompression = 1;
- break;
-
- default:
- LCPDEBUG((stderr, "ppp: lcp_reqci: rcvd unknown option %d",
- citype));
- INCPTR(cilen, p);
- orc = CONFREJ;
- break;
- }
- cilen += 2; /* Adjust cilen whole CI */
-
- endswitch:
- LCPDEBUG((stderr, " (%s)\n",
- orc == CONFACK ? "ACK" : (orc == CONFNAK ? "NAK" : "REJ")));
- if (orc == CONFACK && /* Good CI */
- rc != CONFACK) /* but prior CI wasnt? */
- continue; /* Don't send this one */
-
- if (orc == CONFNAK) { /* Nak this CI? */
- if (rc == CONFREJ) /* Rejecting prior CI? */
- continue; /* Don't send this one */
- if (rc == CONFACK) { /* Ack'd all prior CIs? */
- rc = CONFNAK; /* Not anymore... */
- ucp = inp; /* Backup */
- }
- }
- if (orc == CONFREJ && /* Reject this CI */
- rc != CONFREJ) { /* but no prior ones? */
- rc = CONFREJ;
- ucp = inp; /* Backup */
- }
- if (ucp != cip) /* Need to move CI? */
- BCOPY(cip, ucp, cilen); /* Move it */
- INCPTR(cilen, ucp); /* Update output pointer */
- }
-
- /*
- * XXX If we wanted to send additional NAKs (for unsent CIs), the
- * code would go here. This must be done with care since it might
- * require a longer packet than we received.
- */
-
- *len = ucp - inp; /* Compute output length */
- LCPDEBUG((stderr, "ppp: lcp_reqci: returning %s.\n",
- rc == CONFACK ? "CONFACK" :
- rc == CONFNAK ? "CONFNAK" : "CONFREJ"));
- return (rc); /* Return final code */
- }
-
-
- /*
- * lcp_up - LCP has come UP.
- *
- * Start UPAP, IPCP, etc.
- */
- void lcp_up(f)
- fsm *f;
- {
- lcp_options *ho = &lcp_hisoptions[f->unit];
- lcp_options *go = &lcp_gotoptions[f->unit];
- int auth = 0;
-
- if (ho->neg_mru)
- SIFMTU(f->unit, ho->mru);
- if (ho->neg_asyncmap)
- SIFASYNCMAP(f->unit, ho->asyncmap);
- if (ho->neg_pcompression)
- SIFPCOMPRESSION(f->unit);
- if (ho->neg_accompression)
- SIFACCOMPRESSION(f->unit);
- SIFUP(f->unit); /* Bring the interface up (set IFF_UP) */
- upap_lowerup(f->unit); /* Enable UPAP */
- ipcp_lowerup(f->unit); /* Enable IPCP */
- if (go->neg_upap) {
- upap_authpeer(f->unit);
- auth = 1;
- }
- if (ho->neg_upap) {
- upap_authwithpeer(f->unit);
- auth = 1;
- }
- if (!auth)
- ipcp_activeopen(f->unit);
- }
-
-
- /*
- * lcp_down - LCP has gone DOWN.
- *
- * Alert other protocols.
- */
- void lcp_down(f)
- fsm *f;
- {
- SIFDOWN(f->unit);
- SIFMTU(f->unit, MTU);
- SIFASYNCMAP(f->unit, 0xffffffff);
- CIFPCOMPRESSION(f->unit);
- CIFACCOMPRESSION(f->unit);
- upap_lowerdown(f->unit);
- ipcp_lowerdown(f->unit);
- }
-
-
- /*
- * lcp_closed - LCP has CLOSED.
- *
- * Alert other protocols.
- */
- void lcp_closed(f)
- fsm *f;
- {
- if (lcp_wantoptions[f->unit].restart) {
- if (lcp_wantoptions[f->unit].passive)
- lcp_passiveopen(f->unit); /* Start protocol in passive mode */
- else
- lcp_activeopen(f->unit); /* Start protocol in active mode */
- }
- else {
- EXIT(f->unit);
- }
- }
-