home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 1 / HamRadio.cdr / misc / src0131 / ppplcp.c < prev    next >
C/C++ Source or Header  |  1990-12-09  |  46KB  |  1,840 lines

  1. /*
  2.  *  PPPLCP.C    -- negotiate data link options
  3.  *
  4.  *    REVISIONS:
  5.  *    12-89    -- Katie Stevens (dkstevens@ucdavis.edu)
  6.  *           UC Davis, Computing Services
  7.  *    PPP.01    01-90    [ks] must echo requested magic# in REJ
  8.  *    PPP.08    05-90    [ks] improve PPP trace reporting
  9.  *    PPP.09    05-90    [ks] add auth type negotiation
  10.  *    PPP.10    07-90    [ks] make ppp open/close/reset work properly
  11.  *    PPP.14    08-90    [ks] change UPAP to PAP for consistency
  12.  *                 with RFC1172
  13.  *                 make LCP timeout configurable
  14.  *    PPP.15    09-90    [ks] update to KA9Q NOS v900828
  15.  */
  16.  
  17. #include <stdio.h>
  18. #include "global.h"
  19. #include "mbuf.h"
  20. #include "proc.h"
  21. #include "iface.h"
  22. #include "slip.h"
  23. #include "ppp.h"
  24.  
  25. /* Counter for PPP id field */
  26. extern unsigned char Pppid;
  27.  
  28. /* PPP tracing */
  29. extern int Ppptrace;
  30.  
  31. static void lcp_open __ARGS((struct slip *sp));
  32.  
  33. static int lcp_sendreq __ARGS((struct slip *sp));
  34. static struct mbuf *lcp_makereq __ARGS((struct lcpparm *localp));
  35.  
  36. static void lcp_rcvack __ARGS((struct slip *sp, struct cnfhdr *rcnf,
  37.             struct mbuf *data));
  38. static void lcp_rcvnak __ARGS((struct slip *sp, struct cnfhdr *rcnf,
  39.             struct mbuf *data));
  40. static void lcp_rcvrej __ARGS((struct slip *sp, struct cnfhdr *rcnf,
  41.             struct mbuf *data));
  42. static void lcp_rcvreq __ARGS((struct slip *sp, struct cnfhdr *rcnf,
  43.             struct mbuf *data));
  44. static void lcp_rcvtermack __ARGS((struct slip *sp));
  45. static void lcp_rcvtermreq __ARGS((struct slip *sp, struct cnfhdr *rcnf));
  46.  
  47. static int lcp_chkack __ARGS((struct slip *sp, struct cnfhdr *ackcnf,
  48.             struct mbuf *data));
  49. static int lcp_chknak __ARGS((struct slip *sp, struct cnfhdr *nakcnf,
  50.             struct mbuf *data));
  51. static int lcp_chkrej __ARGS((struct slip *sp, struct cnfhdr *rejcnf,
  52.             struct mbuf *data));
  53. static void lcp_chkreq __ARGS((struct slip *sp, struct cnfhdr *reqcnf,
  54.             struct mbuf *data));
  55.  
  56. static void lcp_timeout __ARGS((void *vp));
  57. static void lcp_timer __ARGS((struct slip *sp));
  58.  
  59. static int lcp_sendreply __ARGS((struct slip *sp, char code,
  60.             unsigned char id, struct mbuf *data));
  61.  
  62. /* Possible LCP states */
  63. char *LCPStates[] = {
  64.     "Closed",
  65.     "Listen",
  66.     "Req Sent",
  67.     "Ack Rcvd",
  68.     "Ack Sent",
  69.     "Open",
  70.     "Terminate"
  71. };
  72.  
  73. /* Possible LCP/IPCP packet types */
  74. char *LCPCodes[] = {
  75.     NULLCHAR,
  76.     "Config Req",
  77.     "Config Ack",
  78.     "Config Nak",
  79.     "Config Rej",
  80.     "Terminate Req",
  81.     "Terminate Ack",
  82.     "Code Rej",
  83.     "Protocol Rej",
  84.     "Echo Req",
  85.     "Echo Reply",
  86.     "Discard Req",
  87. };
  88.  
  89. /* LCP default options, local */
  90. /* Attempt: 0=dont negotiate; 1=attempt negotiation */
  91. /* NOTE: this sructure is used to initialize the local parameter side */
  92. /* of PPP connections; options which will not be negotiated must be   */
  93. /* initialized to default LCP values specified in the PPP RFC         */
  94. static struct lcpparm attempt_parms = {
  95.     0, DEF_MRU,
  96.     0, DEF_CTL_MAP,
  97.     0, DEF_AUTH_TYPE,
  98.     0, DEF_ENCR_TYPE,
  99.     0, DEF_MAGIC_NUM,
  100.     0, DEF_LINK_QUAL,
  101.     0, DEF_PROT_COMPR,
  102.     0, DEF_AC_COMPR
  103. };
  104. /* LCP default options, remote */
  105. /* Accept: 0=reject negotiation; 1=negotiation okay */
  106. static struct lcpparm accept_parms = {
  107.     1, DEF_MRU,
  108.     1, DEF_CTL_MAP,
  109.     1, DEF_AUTH_TYPE,
  110.     0, DEF_ENCR_TYPE,
  111.     0, DEF_MAGIC_NUM,
  112.     0, DEF_LINK_QUAL,
  113.     1, DEF_PROT_COMPR,
  114.     1, DEF_AC_COMPR
  115. };
  116.  
  117. /****************************************************************************/
  118.  
  119. /* Convert LCP/IPCP header in host form to network form */
  120. struct mbuf *
  121. htoncnf(cnf, data)
  122. struct cnfhdr *cnf;
  123. struct mbuf *data;
  124. {
  125.     struct mbuf *bp;
  126.     register char *cp;
  127.  
  128.     /* Prepend bytes for LCP/IPCP header */
  129.     if ((bp = pushdown(data, CNF_HDRLEN)) == NULLBUF)
  130.     return NULLBUF;
  131.  
  132.     /* Load header with proper values */
  133.     cp = bp->data;
  134.     *cp++ = cnf->code;
  135.     *cp++ = cnf->id;
  136.     put16(cp, cnf->len);
  137.  
  138.     return bp;
  139. }
  140.  
  141. /* Extract LCP/IPCP header from incoming packet */
  142. int
  143. ntohcnf(cnf, bpp)
  144. struct cnfhdr *cnf;
  145. struct mbuf **bpp;
  146. {
  147.     cnf->code = pullchar(bpp);
  148.     cnf->id = pullchar(bpp);
  149.     cnf->len = pull16(bpp);
  150.     return(CNF_HDRLEN);
  151. }
  152.  
  153. /*******************************************/
  154.  
  155. /* Convert LCP/IPCP configuration option header in host form to network mbuf */
  156. struct mbuf *
  157. htonopt(opt)
  158. struct opthdr *opt;
  159. {
  160.     struct mbuf *bp;
  161.     register char *cp;
  162.  
  163.     if((bp = alloc_mbuf(OPT_HDRLEN)) == NULLBUF)
  164.         return NULLBUF;
  165.  
  166.     /* Load data into LCP/IPCP configuration option header */
  167.     cp = bp->data;
  168.     *cp++ = opt->type;
  169.     *cp++ = opt->len;
  170.  
  171.     bp->cnt = cp - bp->data;
  172.     return bp;
  173. }
  174. /* Extract LCP/IPCP configuration option header */
  175. int
  176. ntohopt(opt,bpp)
  177. struct opthdr *opt;
  178. struct mbuf **bpp;
  179. {
  180.     if (opt== NULLOPTHDR || bpp == NULLBUFP)
  181.         return -1;
  182.     if (*bpp == NULLBUF)
  183.         return -1;
  184.  
  185.     opt->type = pullchar(bpp);
  186.     opt->len = pullchar(bpp);
  187.     return 0;
  188. }
  189.  
  190. /****************************************************************************/
  191.  
  192. /* Initialize Link Control Protocol state machine for config exchange */
  193. int
  194. lcp_start(sp)
  195. struct slip *sp;
  196. {
  197.     struct pppctl *pppiop;
  198.     struct lcpctl *lcpiop;
  199.  
  200.     pppiop = sp->pppio;
  201.     lcpiop = &(pppiop->lcpio);
  202.  
  203.     if (Ppptrace > 5)
  204.         log(-1, "lcp_start()");
  205.  
  206.     /* Leave things alone if not strictly closed */
  207.     if ((pppiop->state != PPP_CLOSED)&&(lcpiop->lcp_state != LCP_LISTEN)
  208.                      &&(lcpiop->lcp_state != LCP_CLOSED)) {
  209.         return 0;
  210.     }
  211.  
  212.     /* Prepare for Link Control negotiations */
  213.     lcp_reset(pppiop);
  214.  
  215.     if (lcpiop->active == -1) {
  216.         /* We have been strictly closed with 'ppp close' command */
  217.         return 0;
  218.     }
  219.  
  220.     /* Ready for Link Control negotiations */
  221.     pppiop->state = PPP_LCP;
  222.     if (lcpiop->active == 0) {
  223.         /* Passive open; wait until remote host attempts connection */
  224.         lcpiop->lcp_state = LCP_LISTEN;
  225.         return 0;
  226.     }
  227.  
  228.     /* Active open; begin LCP configuration negotiation */
  229.     lcpiop->lcp_state = LCP_CLOSED;    
  230.     return(lcp_sendreq(sp));
  231. }
  232.  
  233. /*******************************************/
  234.  
  235. /* Close the PPP connection from local side */
  236. int
  237. lcp_close(sp)
  238. struct slip *sp;
  239. {
  240.     struct pppctl *pppiop;
  241.     struct lcpctl *lcpiop;
  242.     struct ipcpctl *ipcpiop;
  243.  
  244.     if (Ppptrace > 5)
  245.         log(-1,"lcp_close()");
  246.  
  247.     pppiop = sp->pppio;
  248.     lcpiop = &(pppiop->lcpio);
  249.     ipcpiop = &(pppiop->ipcpio);
  250.     if ((lcpiop->lcp_state == LCP_CLOSED) ||
  251.         (lcpiop->lcp_state == LCP_LISTEN))   {
  252.         /* Already closed */
  253.         return 0;
  254.     }
  255.  
  256.     /* Need to shutdown PAP session if waiting for password */
  257.     psignal(&(lcpiop->pap_user),0);
  258.  
  259.     /* Need to inform upper layers */
  260.     if ((ipcpiop->ipcp_state != IPCP_CLOSED) &&
  261.         (ipcpiop->ipcp_state != IPCP_LISTEN))   {
  262.         /* Wait for the IP layer to close */
  263.         ipcp_close(sp);
  264.         pwait(ipcpiop);
  265.     }
  266.  
  267.     /* Set a timer against our request to shutdown */
  268.     lcp_timer(sp);
  269.     /* Ask remote host to shutdown */
  270.     lcpiop->lcp_state = LCP_TERMINATE;
  271.     lcpiop->ack_retry = 0;
  272.     if (lcp_sendreply(sp, TERMINATE_REQ, 0, NULLBUF) == 0)
  273.         pwait(lcpiop);
  274.  
  275.     pppiop->state = PPP_CLOSED;
  276.     return 0;
  277. }
  278.  
  279. /* Initialize our LCP configuration options to compiled default options */
  280. void
  281. lcp_init(sp)
  282. struct slip *sp;
  283. {
  284.     struct pppctl *pppiop;
  285.     struct lcpctl *lcpiop;
  286.     struct timer *t;
  287.  
  288.     if (Ppptrace > 5)
  289.         log(-1, "lcp_init()");
  290.  
  291.     pppiop = sp->pppio;
  292.     lcpiop = &(pppiop->lcpio);
  293.     t = &(lcpiop->lcp_tm);
  294.  
  295.     /* One time initialization */
  296.     lcpiop->lcp_state = LCP_CLOSED;
  297.     lcpiop->active = 0;
  298.     memcpy(&(lcpiop->initparm), &attempt_parms, sizeof(struct lcpparm));
  299.     set_timer(t,LCP_TIMEOUT*1000L);
  300.     lcp_timer(sp);            /* Set timer strictly OFF */
  301.     stop_timer(&(lcpiop->lcp_tm));
  302.  
  303.     /* Initialization for each LCP open/close */
  304.     lcp_reset(pppiop);
  305.     return;
  306. }
  307.  
  308. /* Link Control configuration negotiation complete */
  309. static void
  310. lcp_open(sp)
  311. struct slip *sp;
  312. {
  313.     struct pppctl *pppiop;
  314.     struct lcpctl *lcpiop;
  315.  
  316.     pppiop = sp->pppio;
  317.     lcpiop = &(pppiop->lcpio);
  318.  
  319.     /* Check on Auth Protocol */
  320.     if (lcpiop->initparm.auth_type != 0x0000) {
  321.         /* We require authentication from the remote host */
  322.         if (lcpiop->lclparm.auth_type != lcpiop->initparm.auth_type) {
  323.             /* Couldnt agree on auth, shut down the link */
  324.             if (Ppptrace)
  325.                 log(-1,"%s: Couldn't negotiate Authenticate Protocol type",sp->iface->name);
  326.             lcp_shutdown(sp);
  327.             return;
  328.         }
  329.     }
  330.  
  331.     /* Mark LCP layer as open */
  332.     if (Ppptrace)
  333.         log(-1,"%s: PPP/LCP Connection Open",sp->iface->name);
  334.     lcpiop->lcp_state = LCP_OPEN;
  335.  
  336.     /* Set flags in PPP control struct to reflect accepted LCP options */
  337.     if (sp->iface->mtu > lcpiop->remparm.mru) {
  338.         /* Set new Max Transmission Unit for outgoing packets */
  339.         sp->iface->mtu = lcpiop->remparm.mru;
  340.         if (Ppptrace > 1)
  341.             log(-1,"    Set new MTU for outgoing packets: %d",
  342.                 sp->iface->mtu);
  343.     }
  344.  
  345.     /* Update async control character map for outgoing packets */
  346.     if (pppiop->ctlmap != lcpiop->remparm.ctl_map) {
  347.         pppiop->ctlmap = lcpiop->remparm.ctl_map;
  348.         if (Ppptrace > 1)
  349.             log(-1,"    Set new control map for outgoing packets: 0x%08lx",
  350.                 pppiop->ctlmap);
  351.     }
  352.  
  353.     /* Update for protocol compression for outgoing/incoming packets */
  354.     if (lcpiop->remparm.prot_compress) {
  355.         sp->escaped |= PPP_XMT_PRCOMP;
  356.         if (Ppptrace > 1)
  357.             log(-1,"    Begin protocol compression on outgoing packets");
  358.     }
  359.     if (lcpiop->lclparm.prot_compress) {
  360.         sp->escaped |= PPP_RCV_PRCOMP;
  361.         if (Ppptrace > 1)
  362.             log(-1,"    Begin protocol compression on incoming packets");
  363.     }
  364.  
  365.     /* Update for addr/ctl compression for outgoing/incoming packets */
  366.     if (lcpiop->remparm.ac_compress) {
  367.         sp->escaped |= PPP_XMT_ACCOMP;
  368.         if (Ppptrace > 1)
  369.             log(-1,"    Begin addr/ctl compression on outgoing packets");
  370.     }
  371.     if (lcpiop->lclparm.ac_compress) {
  372.         sp->escaped |= PPP_RCV_ACCOMP;
  373.         if (Ppptrace > 1)
  374.             log(-1,"    Begin addr/ctl compression on incoming packets");
  375.     }
  376.  
  377.     /* LCP is open; switch to next phase */
  378.     if ((lcpiop->lclparm.auth_type == PAP_AUTH_TYPE) ||
  379.         (lcpiop->remparm.auth_type == PAP_AUTH_TYPE))  {
  380.         /* Startup PAP negotiations (do IPCP when done with PAP) */
  381.         pap_start(sp);
  382.     } else {
  383.         /* Startup IPCP negotiations */
  384.         ipcp_start(sp);
  385.     }
  386.     return;
  387. }
  388.  
  389. /* Reset LCP configuration options for initial request */
  390. int
  391. lcp_reset(pppiop)
  392. struct pppctl *pppiop;
  393. {
  394.     struct lcpctl *lcpiop;
  395.  
  396.     if (Ppptrace > 5)
  397.         log(-1, "lcp_reset()");
  398.  
  399.     lcpiop = &(pppiop->lcpio);
  400.     pppiop->ctlmap = DEF_CTL_MAP;
  401.     if (lcpiop->active == 0)
  402.         lcpiop->lcp_state = LCP_LISTEN;
  403.     else
  404.         lcpiop->lcp_state = LCP_CLOSED;
  405.     lcpiop->ack_retry = 0;
  406.  
  407.     /* Reset our config request prarmeters to our preferred values */
  408.     memcpy(&(lcpiop->lclparm),&(lcpiop->initparm),
  409.                 sizeof(struct lcpparm));
  410.     memcpy(&(lcpiop->remparm),&accept_parms,
  411.                 sizeof(struct lcpparm));
  412.  
  413.     /* Need to shutdown PAP session if waiting for password */
  414.     psignal(&(lcpiop->pap_user),0);
  415.  
  416.     return 0;
  417. }
  418.  
  419. /****************************************************************************/
  420.  
  421. /* Send our LCP configuration request */
  422. static int
  423. lcp_sendreq(sp)
  424. struct slip *sp;
  425. {
  426.     struct pppctl *pppiop;
  427.     struct lcpctl *lcpiop;
  428.     struct mbuf *bp;
  429.  
  430.     if (Ppptrace > 5)
  431.         log(-1,"lcp_sendreq()");
  432.  
  433.     pppiop = sp->pppio;
  434.     lcpiop = &(pppiop->lcpio);
  435.  
  436.     /* Get a packet with our configuration request */
  437.     bp = lcp_makereq(&(lcpiop->lclparm));
  438.  
  439.     /* Start timer against wait for reply to our config request */
  440.     lcp_timer(sp);
  441.  
  442.     /* Send LCP configuration request to remote host */
  443.     pppiop->state = PPP_LCP;
  444.     if (lcpiop->lcp_state != LCP_ACK_SENT)
  445.         lcpiop->lcp_state = LCP_REQ_SENT;
  446.     return(lcp_sendreply(sp, CONFIG_REQ, 0, bp));
  447. }
  448.  
  449. /*******************************************/
  450.  
  451. static struct mbuf *
  452. lcp_makereq(localp)
  453. struct lcpparm *localp;
  454. {
  455.     register char *cp;
  456.     struct mbuf *bp;
  457.     struct mbuf *req_bp = NULLBUF;
  458.  
  459.     if (Ppptrace > 5)
  460.         log(-1,"    lcp_makereq()");
  461.  
  462.     /* Maximum Receive Unit */
  463.     if (localp->neg_mru) {
  464.         if (Ppptrace > 5)
  465.             log(-1,"    asking for MRU: %d (0x%02x)",
  466.                 localp->mru,localp->mru);
  467.  
  468.         /* Attempt to negotiate Maximum Receive Unit */
  469.         if ((bp = alloc_mbuf(4)) == NULLBUF)
  470.             return NULLBUF;
  471.         cp = bp->data;
  472.         *cp++ = MAX_RCV_UNIT;
  473.         *cp++ = 4;
  474.         put16(cp, localp->mru);
  475.         bp->cnt += 4;
  476.         append(&req_bp, bp);
  477.     }
  478.     /* Async Control Map */
  479.     if (localp->neg_ctl_map) {
  480.         if (Ppptrace > 5)
  481.             log(-1,"    asking for Async Control Map: 0x%08lx",
  482.                 localp->ctl_map);
  483.  
  484.         /* Attempt to negotiate Async Control Map */
  485.         if ((bp = alloc_mbuf(6)) == NULLBUF)
  486.             return NULLBUF;
  487.         cp = bp->data;
  488.         *cp++ = ASYNC_CTL_MAP;
  489.         *cp++ = 6;
  490.         put32(cp, localp->ctl_map);
  491.         bp->cnt += 6;
  492.         append(&req_bp, bp);
  493.     }
  494.     /* Authentication type */
  495.     if ((localp->neg_auth_type)&&(localp->auth_type != 0x0000)) {
  496.         if (Ppptrace > 5)
  497.             log(-1,"    asking for Auth Protocol: 0x%04x",
  498.                 localp->auth_type);
  499.         /* Attempt to negotiate Authentication Protocol */
  500.         if ((bp = alloc_mbuf(4)) == NULLBUF)
  501.             return NULLBUF;
  502.         cp = bp->data;
  503.         *cp++ = AUTH_TYPE;
  504.         *cp++ = 4;
  505.         put16(cp, localp->auth_type);
  506.         bp->cnt += 4;
  507.         append(&req_bp, bp);
  508.     }
  509.     /* Magic Number */
  510.     if (localp->neg_magic_num) {
  511.         if (Ppptrace > 5)
  512.             log(-1,"    asking for Magic Number: %0x08lx",
  513.                 localp->magic_num);
  514.  
  515.         /* Attempt to negotiate Magic Number */
  516.         if ((bp = alloc_mbuf(6)) == NULLBUF)
  517.             return NULLBUF;
  518.         cp = bp->data;
  519.         *cp++ = MAGIC_NUMBER;
  520.         *cp++ = 6;
  521.         put32(cp, localp->magic_num);
  522.         bp->cnt += 6;
  523.         append(&req_bp, bp);
  524.     }
  525.     /* Protocol Field Compression */
  526.     if (localp->neg_prot_compress) {
  527.         if (Ppptrace > 5)
  528.             log(-1,"    asking for Protcol compression");
  529.  
  530.         /* Attempt to negotiate protocol field compression */
  531.         if ((bp = alloc_mbuf(2)) == NULLBUF)
  532.             return NULLBUF;
  533.         cp = bp->data;
  534.         *cp++ = PROT_COMPRESS;
  535.         *cp++ = 2;
  536.         bp->cnt += 2;
  537.         append(&req_bp, bp);
  538.     }
  539.     /* Address and Control Field Compression */
  540.     if (localp->neg_ac_compress) {
  541.         if (Ppptrace > 5)
  542.             log(-1,"    asking for Addr/Ctl compression");
  543.  
  544.         /* Attempt to negotiate protocol field compression */
  545.         if ((bp = alloc_mbuf(2)) == NULLBUF)
  546.             return NULLBUF;
  547.         cp = bp->data;
  548.         *cp++ = AC_COMPRESS;
  549.         *cp++ = 2;
  550.         bp->cnt += 2;
  551.         append(&req_bp, bp);
  552.     }
  553.     /* Encryption type not implemented */
  554.     /* Link Quality Monitoring not implemented */
  555.  
  556.     return(req_bp);
  557. }
  558.  
  559. /****************************************************************************/
  560.  
  561. /* Remote host ACKed our configuration request */
  562. static void
  563. lcp_rcvack(sp, rcnf, data)
  564. struct slip *sp;
  565. struct cnfhdr *rcnf;
  566. struct mbuf *data;
  567. {
  568.     struct pppctl *pppiop;
  569.     struct lcpctl *lcpiop;
  570.  
  571.     if (Ppptrace > 5)
  572.         log(-1, "lcp_rcvack()");
  573.  
  574.     pppiop = sp->pppio;
  575.     lcpiop = &(pppiop->lcpio);
  576.     stop_timer(&lcpiop->lcp_tm);
  577.  
  578.     switch(lcpiop->lcp_state) {
  579.     case LCP_REQ_SENT:
  580.         /* Make sure ACK is proper */
  581.         if (lcp_chkack(sp, rcnf, data) != -1) {
  582.             /* Remote host accepted our request */
  583.             lcpiop->lcp_state = LCP_ACK_RCVD;
  584.         }
  585.  
  586.         /* Still need to settle request from remote host */
  587.         lcp_timer(sp);
  588.         break;
  589.  
  590.     case LCP_ACK_SENT:
  591.         /* Make sure ACK is proper */
  592.         if (lcp_chkack(sp, rcnf, data) == -1) {
  593.             /* Error in ACK from remote host */
  594.             /* Wait for another ACK, then send another request */
  595.             lcp_timer(sp);
  596.         } else {
  597.             /* LCP negotiation complete */
  598.             lcp_open(sp);
  599.         }
  600.         break;
  601.  
  602.     case LCP_ACK_RCVD:
  603.     case LCP_OPEN:
  604.         /* Something went wrong; restart negotiations */
  605.         free_p(data);    
  606.         lcp_reset(pppiop);
  607.         lcp_sendreq(sp);
  608.         break;
  609.     case LCP_TERMINATE:
  610.         /* We are attempting to close connection; wait */
  611.         /* for timeout to resend a Terminate Request */
  612.         free_p(data);
  613.         break;
  614.     case LCP_CLOSED:
  615.     case LCP_LISTEN:
  616.     default:
  617.         /* Confusion; shutdown the connection */
  618.         free_p(data);
  619.         lcp_shutdown(sp);
  620.         break;
  621.     }
  622.     return;
  623. }
  624.  
  625. /* Remote host NAKed our configuration request */
  626. static void
  627. lcp_rcvnak(sp, rcnf, data)
  628. struct slip *sp;
  629. struct cnfhdr *rcnf;
  630. struct mbuf *data;
  631. {
  632.     struct pppctl *pppiop;
  633.     struct lcpctl *lcpiop;
  634.  
  635.     if (Ppptrace > 5)
  636.         log(-1, "lcp_rcvnak()");
  637.  
  638.     pppiop = sp->pppio;
  639.     lcpiop = &(pppiop->lcpio);
  640.     stop_timer(&lcpiop->lcp_tm);
  641.  
  642.     switch(lcpiop->lcp_state) {
  643.     case LCP_REQ_SENT:
  644.     case LCP_ACK_SENT:
  645.         /* Update our config request to reflect NAKed options */
  646.         if (lcp_chknak(sp, rcnf, data) == -1) {
  647.             /* Bad NAK packet */
  648.             /* Wait for another; resend request on timeout */
  649.             lcp_timer(sp);
  650.         } else {
  651.             /* Send updated config request */
  652.             lcp_sendreq(sp);
  653.         }
  654.         break;
  655.  
  656.     case LCP_ACK_RCVD:
  657.     case LCP_OPEN:
  658.         /* Something went wrong; restart negotiations */
  659.         free_p(data);    
  660.         lcp_reset(pppiop);
  661.         lcp_sendreq(sp);
  662.         break;
  663.     case LCP_TERMINATE:
  664.         /* We are attempting to close connection; wait */
  665.         /* for timeout to resend a Terminate Request */
  666.         free_p(data);
  667.         break;
  668.     case LCP_CLOSED:
  669.     case LCP_LISTEN:
  670.     default:
  671.         /* Confusion; shutdown the connection */
  672.         free_p(data);
  673.         lcp_shutdown(sp);
  674.         break;
  675.     }
  676.     return;
  677. }
  678.  
  679. /* Remote host rejected our configuration request */
  680. static void
  681. lcp_rcvrej(sp, rcnf, data)
  682. struct slip *sp;
  683. struct cnfhdr *rcnf;
  684. struct mbuf *data;
  685. {
  686.     struct pppctl *pppiop;
  687.     struct lcpctl *lcpiop;
  688.  
  689.     if (Ppptrace > 5)
  690.         log(-1, "lcp_rcvrej()");
  691.  
  692.     pppiop = sp->pppio;
  693.     lcpiop = &(pppiop->lcpio);
  694.     stop_timer(&lcpiop->lcp_tm);
  695.  
  696.     switch(lcpiop->lcp_state) {
  697.     case LCP_REQ_SENT:
  698.     case LCP_ACK_SENT:
  699.         /* Update our config request to reflect rejected options */
  700.         if (lcp_chkrej(sp, rcnf, data) == -1) {
  701.             /* Bad reject packet */
  702.             /* Wait for another; resend request on timeout */
  703.             lcp_timer(sp);
  704.         } else {
  705.             /* Send updated config request */
  706.             lcp_sendreq(sp);
  707.         }
  708.         break;
  709.  
  710.     case LCP_ACK_RCVD:
  711.     case LCP_OPEN:
  712.         /* Something went wrong; restart negotiations */
  713.         free_p(data);    
  714.         lcp_reset(pppiop);
  715.         lcp_sendreq(sp);
  716.         break;
  717.     case LCP_TERMINATE:
  718.         /* We are attempting to close connection; wait */
  719.         /* for timeout to resend a Terminate Request */
  720.         free_p(data);
  721.         break;
  722.     case LCP_CLOSED:
  723.     case LCP_LISTEN:
  724.     default:
  725.         /* Confusion; shutdown the connection */
  726.         free_p(data);
  727.         lcp_shutdown(sp);
  728.         break;
  729.     }
  730.     return;
  731. }
  732.  
  733. /* Process configuration request sent by remote host */
  734. static void
  735. lcp_rcvreq(sp, rcnf, data)
  736. struct slip *sp;
  737. struct cnfhdr *rcnf;
  738. struct mbuf *data;
  739. {
  740.     struct pppctl *pppiop;
  741.     struct lcpctl *lcpiop;
  742.  
  743.     if (Ppptrace > 5)
  744.         log(-1, "lcp_rcvreq()");
  745.  
  746.     pppiop = sp->pppio;
  747.     lcpiop = &(pppiop->lcpio);
  748.  
  749.     switch(lcpiop->lcp_state) {
  750.     case LCP_LISTEN:    /* Normal event */
  751.     case LCP_ACK_SENT:    /* Unexpected event */
  752.     case LCP_OPEN:        /* Unexpected event */
  753.         /* Reset LCP state machine for configuration negotiation */
  754.         lcp_reset(pppiop);
  755.         /* Send our configuration request */    
  756.         lcp_sendreq(sp);
  757.         /* Evaluate configuration request from remote host */
  758.         lcp_chkreq(sp, rcnf, data);
  759.         break;
  760.  
  761.     case LCP_ACK_RCVD:
  762.         /* Stop timer against wait for config request */
  763.         stop_timer(&(lcpiop->lcp_tm));
  764.     case LCP_REQ_SENT:
  765.         /* Evaluate configuration request from remote host */
  766.         lcp_chkreq(sp, rcnf, data);
  767.         break;
  768.  
  769.     case LCP_TERMINATE:
  770.         /* We are attempting to close connection; wait */
  771.         /* for timeout to resend a Terminate Request   */
  772.         free_p(data);
  773.         break;
  774.  
  775.     case LCP_CLOSED:
  776.     default:
  777.         /* We are closed; dont accept any connections */
  778.         free_p(data);
  779.         lcp_shutdown(sp);
  780.         break;
  781.     }
  782.     return;
  783. }
  784.  
  785. /* Remote host closed connection */
  786. static void
  787. lcp_rcvtermack(sp)
  788. struct slip *sp;
  789. {
  790.     struct pppctl *pppiop;
  791.     struct lcpctl *lcpiop;
  792.  
  793.     if (Ppptrace > 5)
  794.         log(-1,"lcp_rcvtermack()");
  795.  
  796.     pppiop = sp->pppio;
  797.     lcpiop = &(pppiop->lcpio);
  798.     stop_timer(&(lcpiop->lcp_tm));
  799.  
  800.     switch(lcpiop->lcp_state) {
  801.     case LCP_OPEN:
  802.         /* Remote host has abruptly closed connection */
  803. /* Need to inform upper levels */
  804.     case LCP_TERMINATE:
  805.         /* Remote host has responded to our terminate request */
  806.         if (Ppptrace)
  807.             log(-1,"%s: PPP/LCP Connection Closed",sp->iface->name);
  808.         pppiop->state = PPP_CLOSED;
  809.         if (lcpiop->active == 0)
  810.             lcpiop->lcp_state = LCP_LISTEN;
  811.         else
  812.             lcpiop->lcp_state = LCP_CLOSED;
  813.         /* Prepare for next open */
  814.         lcp_reset(pppiop);
  815.         psignal(lcpiop,0);
  816.         break;
  817.     case LCP_REQ_SENT:
  818.         /* Wait for timeout to restart attempt */
  819.         break;
  820.     case LCP_ACK_SENT:
  821.     case LCP_ACK_RCVD:
  822.         /* Something went wrong; restart negotiations */
  823.         lcp_reset(pppiop);
  824.         lcp_sendreq(sp);
  825.         break;
  826.     case LCP_CLOSED:
  827.     case LCP_LISTEN:
  828.     default:
  829.         /* Unexpected, but no action needed */
  830.         break;
  831.     }
  832.  
  833.     return;
  834. }
  835.  
  836. /* Remote peer requested that we close the PPP connection */
  837. void
  838. lcp_rcvtermreq(sp, rcnf)
  839. struct slip *sp;
  840. struct cnfhdr *rcnf;
  841. {
  842.     struct pppctl *pppiop;
  843.     struct lcpctl *lcpiop;
  844.  
  845.     if (Ppptrace > 5)
  846.         log(-1, "lcp_termreq()");
  847.  
  848.     pppiop = sp->pppio;
  849.     lcpiop = &(pppiop->lcpio);
  850.  
  851.     if (Ppptrace)
  852.         log(-1,"%s: PPP/LCP Peer requested close",sp->iface->name);
  853.     lcpiop->active = 0;
  854.     lcpiop->lcp_state = LCP_LISTEN;
  855. /* Need to inform upper layers */
  856.  
  857.     lcp_sendreply(sp, TERMINATE_ACK, rcnf->id, NULLBUF);
  858.     lcp_reset(pppiop);
  859.     pppiop->state = PPP_CLOSED;
  860.     return;
  861. }
  862.  
  863. /* Shutdown the LCP connection */
  864. void
  865. lcp_shutdown(sp)
  866. struct slip *sp;
  867. {
  868.     struct pppctl *pppiop;
  869.     struct lcpctl *lcpiop;
  870.  
  871.     if (Ppptrace > 5)
  872.         log(-1, "lcp_shutdown()");
  873.  
  874.     pppiop = sp->pppio;
  875.     lcpiop = &(pppiop->lcpio);
  876.  
  877.     if (Ppptrace)
  878.         log(-1,"%s: PPP/LCP Connection Shutdown",sp->iface->name);
  879.     if (lcpiop->active == 0)
  880.         lcpiop->lcp_state = LCP_LISTEN;
  881.     else
  882.         lcpiop->lcp_state = LCP_CLOSED;
  883. /* Need to inform upper layers */
  884.  
  885.     lcp_sendreply(sp,TERMINATE_ACK,0,NULLBUF);
  886.     lcp_reset(pppiop);
  887.     pppiop->state = PPP_CLOSED;
  888.     return;
  889. }
  890.  
  891. /*******************************************/
  892.  
  893. /* Process configuration ACK send by remote host */
  894. static int
  895. lcp_chkack(sp, ackcnf, data)
  896. struct slip *sp;
  897. struct cnfhdr *ackcnf;
  898. struct mbuf *data;
  899. {
  900.     int ackerr = 0;
  901.     struct pppctl *pppiop;
  902.     struct lcpctl *lcpiop;
  903.     struct mbuf *req_bp;
  904.     struct opthdr reqopt;
  905.     struct opthdr ackopt;
  906.     int16 reqi16, acki16;
  907.     int32 reqi32, acki32;
  908.  
  909.     if (Ppptrace > 5)
  910.         log(-1,"lcp_chkack()");
  911.  
  912.     pppiop = sp->pppio;
  913.     lcpiop = &(pppiop->lcpio);
  914.  
  915.     /* LCP ID field must match last request we sent */
  916.     if (ackcnf->id != lcpiop->lastid) {
  917.         if (Ppptrace > 1)
  918.             log(-1,"improper LCP ACK; bad ID");
  919.         free_p(data);
  920.         return -1;
  921.     }
  922.  
  923.     /* Get a copy of last request we sent */
  924.     req_bp = lcp_makereq(&(lcpiop->lclparm));
  925.  
  926.     /* Overall buffer length should match */
  927.     if (ackcnf->len != len_p(req_bp)) {
  928.         ackerr = 1;
  929.     }
  930.  
  931.     /* ACK must echo all options we requested in the order requested */
  932.     while ((ntohopt(&reqopt, &req_bp) != -1) && (!ackerr)) {
  933.         /* Get config option from ACK packet */
  934.         if (ntohopt(&ackopt, &data) == -1) {
  935.             /* Must have as many acked options as requested */
  936.             ackerr = 1;
  937.             break;
  938.         }
  939.  
  940.         /* Config option headers must match */
  941.         if ((ackopt.type != reqopt.type)
  942.            ||(ackopt.len != reqopt.len)) {
  943.             ackerr = 1;
  944.             break;
  945.         }
  946.  
  947.         /* Config option values must match */
  948.         switch(reqopt.type) {
  949.         case MAX_RCV_UNIT:    /* Maximum Receive Unit */
  950.         case AUTH_TYPE:        /* Authentication Protocol Type */
  951.             acki16 = pull16(&data);
  952.             reqi16 = pull16(&req_bp);
  953.             if (acki16 != reqi16) {
  954.                 ackerr = 1;
  955.             }
  956.             break;
  957.         case MAGIC_NUMBER:    /* Magic Number */
  958.         case ASYNC_CTL_MAP:    /* Async Control Map */
  959.             acki32 = pull32(&data);
  960.             reqi32 = pull32(&req_bp);
  961.             if (acki32 != reqi32) {
  962.                 ackerr = 1;
  963.             }
  964.             break;
  965.         case PROT_COMPRESS:    /* Protocol Compression */
  966.         case AC_COMPRESS:    /* Addr/Control Compression */
  967.             /* Option ON if requested */
  968.             break;
  969.  
  970.         case ENCR_TYPE:        /* Encryption type not implemented */
  971.         case LINK_QUALITY:    /* Link Qual Monitor not implemented */
  972.         default:        /* Shouldnt happen */
  973.             ackerr = 1;
  974.             break;
  975.         }
  976.     }
  977.  
  978.     free_p(req_bp);
  979.     free_p(data);
  980.  
  981.     if (ackerr) {
  982.         /* Error in configuration ACK */
  983.         if (Ppptrace > 5)
  984.             log(-1,"improper LCP ACK echo");
  985.         return -1;
  986.     }
  987.  
  988.     /* ACK matches last request we made */
  989.     if (Ppptrace > 5)
  990.         log(-1,"valid LCP ACK echo");
  991.     return 0;
  992. }
  993.  
  994. /* Process configuration NAK send by remote host */
  995. static int
  996. lcp_chknak(sp, nakcnf, data)
  997. struct slip *sp;
  998. struct cnfhdr *nakcnf;
  999. struct mbuf *data;
  1000. {
  1001.     int nakerr = 0;
  1002.     struct pppctl *pppiop;
  1003.     struct lcpctl *lcpiop;
  1004.     struct lcpparm *localp;
  1005.     struct mbuf *req_bp;
  1006.     struct opthdr reqopt;
  1007.     struct opthdr nakopt;
  1008.     int16 naki16;
  1009.     int32 naki32;
  1010.  
  1011.     if (Ppptrace > 5)
  1012.         log(-1,"lcp_chknak()");
  1013.  
  1014.     pppiop = sp->pppio;
  1015.     lcpiop = &(pppiop->lcpio);
  1016.     localp = &(lcpiop->lclparm);
  1017.  
  1018.     /* LCP ID field must match last request we sent */
  1019.     if (nakcnf->id != lcpiop->lastid) {
  1020.         if (Ppptrace > 1)
  1021.             log(-1,"improper LCP NAK; bad ID");
  1022.         free_p(data);
  1023.         return -1;
  1024.     }
  1025.  
  1026.     /* Get a copy of last request we sent */
  1027.     req_bp = lcp_makereq(&(lcpiop->lclparm));
  1028.  
  1029.     /* Check overall buffer length */
  1030.     if (nakcnf->len > len_p(req_bp)) {
  1031.         /* Remote cant NAK more options than we requested */
  1032.         nakerr = 1;
  1033.     }
  1034.  
  1035.     /* NAKed options must be same order as our original request */
  1036.     while ((ntohopt(&nakopt, &data) != -1) && (!nakerr)) {
  1037.         /* Get config option from our request */
  1038.         if (ntohopt(&reqopt, &req_bp) == -1) {
  1039.             /* Must find match to each NAKed option */
  1040.             nakerr = 1;
  1041.             break;
  1042.         }
  1043.  
  1044.         /* Maybe not all options were NAKed; look */
  1045.         /* for matching option in our request     */
  1046.         while (reqopt.type != nakopt.type) {
  1047.             /* This option not NAKed; eat rest   */
  1048.             /* of option from the request packet */
  1049.             reqopt.len -= 2;
  1050.             while (reqopt.len--)
  1051.                 pullchar(&req_bp);
  1052.  
  1053.             /* Get next config option from our request */
  1054.             if (ntohopt(&reqopt, &req_bp) == -1) {
  1055.                 /* Must find match to each NAKed option */
  1056.                 reqopt.type = 0;
  1057.                 nakerr = 1;
  1058.                 break;
  1059.             }
  1060.         }
  1061.  
  1062.         /* Config option headers must match */
  1063.         if ((nakopt.type != reqopt.type)
  1064.            ||(nakopt.len != reqopt.len)) {
  1065.             nakerr = 1;
  1066.             break;
  1067.         }
  1068.  
  1069.         /* Remote host replaced our request with new suggestion */
  1070.         switch(reqopt.type) {
  1071.         case MAX_RCV_UNIT:    /* Maximum Receive Unit */
  1072.             /* Get suggested MRU */
  1073.             naki16 = pull16(&data);
  1074.             /* Eat MRU from our request packet */
  1075.             pull16(&req_bp);
  1076.  
  1077.             if ((naki16 < MIN_MRU)||(naki16 > DEF_MRU))
  1078.                 naki16 = DEF_MRU;
  1079.  
  1080.             /* Save new request value */
  1081.             localp->mru = naki16;
  1082.             break;
  1083.         case ASYNC_CTL_MAP:    /* Async Control Map */
  1084.             /* Get suggested control map */
  1085.             naki32 = pull32(&data);
  1086.             /* Eat control map from our request packet */
  1087.             pull32(&req_bp);
  1088.  
  1089.             /* Remote host may ask to escape more control  */
  1090.             /* characters than we require, but must escape */
  1091.             /* at least the control chars that we require. */
  1092.             if (naki32 != (naki32 | lcpiop->initparm.ctl_map))
  1093.                 naki32 = lcpiop->initparm.ctl_map;
  1094.  
  1095.             /* Save new request value */
  1096.             localp->ctl_map = naki32;
  1097.             break;
  1098.         case AUTH_TYPE:        /* Authentication Protocol Type */
  1099.             /* Get suggested Auth Protocol */
  1100.             naki16 = pull16(&data);
  1101.             /* Eat auth type from our request packet */
  1102.             pull16(&req_bp);
  1103.  
  1104.             /* Can only accept auth protocols we know */
  1105.             if (naki16 != PAP_AUTH_TYPE) {
  1106.                 /* Abandon request for auth type */
  1107.                 /* Wont open LCP layer without auth protocol */
  1108.                 naki16 = DEF_AUTH_TYPE;
  1109.             }
  1110.  
  1111.             /* Save new request value */
  1112.             localp->mru = naki16;
  1113.             break;
  1114.         case MAGIC_NUMBER:    /* Magic Number */
  1115.             /* Get suggested magic number */
  1116.             naki32 = pull32(&data);
  1117.             /* Eat magic number from our request packet */
  1118.             pull32(&req_bp);
  1119.  
  1120. /* Try to prevent matching magic numbers */
  1121.  
  1122.             /* Save new request value */
  1123.             localp->magic_num = naki32;
  1124.             break;
  1125.         case PROT_COMPRESS:
  1126.             /* Remote host says no protocol compression */
  1127.             localp->neg_prot_compress = 0;
  1128.             localp->prot_compress = DEF_PROT_COMPR;
  1129.             break;
  1130.         case AC_COMPRESS:
  1131.             /* Remote host says no addr/ctl compression */
  1132.             localp->neg_ac_compress = 0;
  1133.             localp->ac_compress = DEF_AC_COMPR;
  1134.             break;
  1135.  
  1136.         case ENCR_TYPE:        /* Encryption type not implemented */
  1137.         case LINK_QUALITY:    /* Link Qual Monitor not implemented */
  1138.         default:        /* Shouldnt happen */
  1139.             nakerr = 1;
  1140.             break;
  1141.         }
  1142.     }
  1143.  
  1144.     free_p(req_bp);
  1145.     free_p(data);
  1146.  
  1147.     if (nakerr) {
  1148.         /* Error in configuration NAK */
  1149.         if (Ppptrace > 5)
  1150.             log(-1,"improper LCP NAK echo");
  1151.         return -1;
  1152.     }
  1153.  
  1154.     /* NAK matches last request we made */
  1155.     if (Ppptrace > 5)
  1156.         log(-1,"valid LCP NAK echo");
  1157.     return 0;
  1158. }
  1159.  
  1160. /* Process configuration reject send by remote host */
  1161. static int
  1162. lcp_chkrej(sp, rejcnf, data)
  1163. struct slip *sp;
  1164. struct cnfhdr *rejcnf;
  1165. struct mbuf *data;
  1166. {
  1167.     int rejerr = 0;
  1168.     struct pppctl *pppiop;
  1169.     struct lcpctl *lcpiop;
  1170.     struct lcpparm *localp;
  1171.     struct mbuf *req_bp;
  1172.     struct opthdr reqopt;
  1173.     struct opthdr rejopt;
  1174.  
  1175.     if (Ppptrace > 5)
  1176.         log(-1,"lcp_chkrej()");
  1177.  
  1178.     pppiop = sp->pppio;
  1179.     lcpiop = &(pppiop->lcpio);
  1180.     localp = &(lcpiop->lclparm);
  1181.  
  1182.     /* LCP ID field must match last request we sent */
  1183.     if (rejcnf->id != lcpiop->lastid) {
  1184.         if (Ppptrace > 1)
  1185.             log(-1,"improper LCP REJ; bad ID");
  1186.         free_p(data);
  1187.         return -1;
  1188.     }
  1189.  
  1190.     /* Get a copy of last request we sent */
  1191.     req_bp = lcp_makereq(&(lcpiop->lclparm));
  1192.  
  1193.     /* Check overall buffer length */
  1194.     if (rejcnf->len > len_p(req_bp)) {
  1195.         /* Remote cant NAK more options than we requested */
  1196.         rejerr = 1;
  1197.     }
  1198.  
  1199.     /* Rejected options must be same order as our original request */
  1200.     while ((ntohopt(&rejopt, &data) != -1) && (!rejerr)) {
  1201.         /* Get config option from our request */
  1202.         if (ntohopt(&reqopt, &req_bp) == -1) {
  1203.             /* Must find match to each NAKed option */
  1204.             rejerr = 1;
  1205.             break;
  1206.         }
  1207.  
  1208.         /* Maybe not all options were NAKed; look */
  1209.         /* for matching option in our request     */
  1210.         while (reqopt.type != rejopt.type) {
  1211.             /* This option not NAKed; eat rest   */
  1212.             /* of option from the request packet */
  1213.             reqopt.len -= 2;
  1214.             while (reqopt.len--)
  1215.                 pullchar(&req_bp);
  1216.  
  1217.             /* Get next config option from our request */
  1218.             if (ntohopt(&reqopt, &req_bp) == -1) {
  1219.                 /* Must find match to each NAKed option */
  1220.                 reqopt.type = 0;
  1221.                 rejerr = 1;
  1222.                 break;
  1223.             }
  1224.         }
  1225.  
  1226.         /* Config option headers must match */
  1227.         if ((rejopt.type != reqopt.type)
  1228.            ||(rejopt.len != reqopt.len)) {
  1229.             rejerr = 1;
  1230.             break;
  1231.         }
  1232.  
  1233.         /* Remote host wont negotiate this option */
  1234.         switch(reqopt.type) {
  1235.         case MAX_RCV_UNIT:    /* Maximum Receive Unit */
  1236.             /* Eat MRU value from config packets */
  1237.             pull16(&data);
  1238.             pull16(&req_bp);
  1239.  
  1240.             /* Dont attempt to negotiate MRU */
  1241.             localp->neg_mru = 0;
  1242.             localp->mru = DEF_MRU;
  1243.             break;
  1244.         case ASYNC_CTL_MAP:    /* Async Control Map */
  1245.             /* Eat control map value from config packets */
  1246.             pull32(&data);
  1247.             pull32(&req_bp);
  1248.  
  1249.             /* Dont attempt to negotiate control map */
  1250.             localp->neg_ctl_map = 0;
  1251.             localp->ctl_map = DEF_CTL_MAP;
  1252.             break;
  1253.         case AUTH_TYPE:        /* Authentication Protocol Type */
  1254.             /* Eat auth type value from config packets */
  1255.             pull16(&data);
  1256.             pull16(&req_bp);
  1257.  
  1258.             /* Dont attempt to negotiate auth type */
  1259.             /* Wont open LCP layer without auth protocol */
  1260.             localp->neg_auth_type = 0;
  1261.             localp->auth_type = DEF_AUTH_TYPE;
  1262.             break;
  1263.         case MAGIC_NUMBER:    /* Magic Number */
  1264.             /* Eat magic number value from config packets */
  1265.             pull32(&data);
  1266.             pull32(&req_bp);
  1267.  
  1268.             /* Dont attempt to negotiate control map */
  1269.             localp->neg_magic_num = 0;
  1270.             localp->magic_num = DEF_MAGIC_NUM;
  1271.             break;
  1272.         case PROT_COMPRESS:    /* Protocol Compression */
  1273.             /* Abandon attempt to use protocol compression */
  1274.             localp->neg_prot_compress = 0;
  1275.             localp->prot_compress = DEF_PROT_COMPR;
  1276.             break;
  1277.         case AC_COMPRESS:    /* Addr/Ctl Compression */
  1278.             /* Abandon attempt to use addr/ctl compression */
  1279.             localp->neg_ac_compress = 0;
  1280.             localp->ac_compress = DEF_AC_COMPR;
  1281.             break;
  1282.  
  1283.         case ENCR_TYPE:        /* Encryption type not implemented */
  1284.         case LINK_QUALITY:    /* Link Qual Monitor not implemented */
  1285.         default:        /* Shouldnt happen */
  1286.             rejerr = 1;
  1287.             break;
  1288.         }
  1289.     }
  1290.  
  1291.     free_p(req_bp);
  1292.     free_p(data);
  1293.  
  1294.     if (rejerr) {
  1295.         /* Error in configuration reject */
  1296.         if (Ppptrace > 5)
  1297.             log(-1,"improper LCP REJ echo");
  1298.         return -1;
  1299.     }
  1300.  
  1301.     /* Reject matches last request we made */
  1302.     if (Ppptrace > 5)
  1303.         log(-1,"valid LCP REJ echo");
  1304.     return 0;
  1305. }
  1306.  
  1307. /* Check Link Control options requested by the remote host */
  1308. static void
  1309. lcp_chkreq(sp, reqcnf, data)
  1310. struct slip *sp;
  1311. struct cnfhdr *reqcnf;
  1312. struct mbuf *data;
  1313. {
  1314.     struct pppctl *pppiop;
  1315.     struct lcpctl *lcpiop;
  1316.     int ilen;
  1317.     int16 i16;
  1318.     int32 i32;
  1319.     register char *cp;
  1320.     char cnf_accept = CONFIG_ACK;        /* Overall reply to request */
  1321.     char opt_accept;            /* Per option reply */
  1322.     struct opthdr reqopt;            /* Per option header storage */
  1323.     struct opthdr replyopt;            /* For building reply */
  1324.     struct lcpparm *remotep;        /* Ptr to remote options */
  1325.     struct lcpparm *initp;            /* Ptr to initial lcl opts */
  1326.     struct mbuf *bp;            /* Ptr for building reply */
  1327.     struct mbuf *reply_bp = NULLBUF;    /* Actual reply packet */
  1328.  
  1329.     if (Ppptrace > 5)
  1330.         log(-1, "lcp_chkreq()");
  1331.  
  1332.     pppiop = sp->pppio;
  1333.     lcpiop = &(pppiop->lcpio);
  1334.     remotep = &(lcpiop->remparm);
  1335.     initp = &(lcpiop->initparm);
  1336.  
  1337.     /* Make sure length in LCP config header is realistic */
  1338.     i16 = len_p(data);
  1339.     if (i16 < reqcnf->len)
  1340.         reqcnf->len = i16;
  1341.  
  1342.     /* Process options requested by remote host */
  1343.     while (reqcnf->len > 0) {
  1344.         /* Get header for next option */
  1345.         if (ntohopt(&reqopt, &data) == -1)
  1346.             break;
  1347.  
  1348.         reqcnf->len -= reqopt.len;    /* Count bytes this option */
  1349.         reqopt.len -= 2;        /* Get data len this option */
  1350.         opt_accept = CONFIG_ACK;    /* Assume will accept option */
  1351.  
  1352.         switch(reqopt.type) {
  1353.         case MAX_RCV_UNIT:
  1354.             if (Ppptrace > 5)
  1355.                 log(-1, "remote asking for MRU");
  1356.  
  1357.             /* Max Receive Unit is a 16bit field */
  1358.             ilen = 2;
  1359.             if (reqopt.len < ilen) {
  1360.                 /* Short option data; reject packet */
  1361.                 opt_accept = CONFIG_REJ;
  1362.                 i16 = DEF_MRU;
  1363.                 break;
  1364.             }
  1365.             /* Get proposed value from packet */
  1366.             i16 = pull16(&data);
  1367.             if ((remotep->neg_mru == 0) && (i16 != DEF_MRU)) {
  1368.                 /* Not open for negotiation */
  1369.                 opt_accept = CONFIG_REJ;
  1370.                 break;
  1371.             }
  1372.             /* Check if new value is appropriate */
  1373.             if (i16 < MIN_MRU) {
  1374.                 /* Too small, ask for minimum instead */
  1375.                 opt_accept = CONFIG_NAK;
  1376.                 i16 = MIN_MRU;
  1377.             } else if (i16 > DEF_MRU) {
  1378.                 /* Too big, tell largest value we can use */
  1379.                 opt_accept = CONFIG_NAK;
  1380.                 i16 = DEF_MRU;
  1381.             } else {
  1382.                 /* Value is acceptable */
  1383.                 opt_accept = CONFIG_ACK;
  1384.             }
  1385.             remotep->mru = i16;
  1386.             break;
  1387.         case ASYNC_CTL_MAP:    /* Async Control Map */
  1388.             if (Ppptrace > 5)
  1389.                 log(-1, "remote asking for async control map");
  1390.             /* Async control map is a 32bit field */
  1391.             ilen = 4;
  1392.             if (reqopt.len < ilen) {
  1393.                 /* Short option data; reject packet */
  1394.                 opt_accept = CONFIG_REJ;
  1395.                 i32 = DEF_CTL_MAP;
  1396.                 break;
  1397.             }
  1398.             /* Get proposed value from packet */
  1399.             i32 = pull32(&data);
  1400.             if ((remotep->neg_ctl_map == 0)
  1401.                 && (i32 != DEF_CTL_MAP)) {
  1402.                 /* Not open for negotiation */
  1403.                 opt_accept = CONFIG_REJ;
  1404.                 break;
  1405.             }
  1406.  
  1407.             /* Record new async control character map */
  1408.             opt_accept = CONFIG_ACK;
  1409.             remotep->ctl_map = i32;
  1410.             break;
  1411.         case AUTH_TYPE:
  1412.             if (Ppptrace > 5)
  1413.                 log(-1, "remote asking for Auth Protocol type");
  1414.  
  1415.             /* Auth Protocol Type is a 16bit field */
  1416.             ilen = 2;
  1417.             if (reqopt.len < ilen) {
  1418.                 /* Short option data; reject packet */
  1419.                 opt_accept = CONFIG_REJ;
  1420.                 i16 = DEF_MRU;
  1421.                 break;
  1422.             }
  1423.             /* Get proposed value from packet */
  1424.             i16 = pull16(&data);
  1425.             if ((initp->neg_auth_type == 1)
  1426.                 && (initp->auth_type != DEF_AUTH_TYPE)) {
  1427.                 /* We are requesting auth too;               */
  1428.                 /* we only know PAP auth protocol           */
  1429.                 /* PAP is a one-way authentication protocol */
  1430.                 opt_accept = CONFIG_REJ;
  1431.                 break;
  1432.             }
  1433.             if ((remotep->neg_auth_type == 0)
  1434.                 && (i16 != DEF_AUTH_TYPE)) {
  1435.                 /* Not open for negotiation */
  1436.                 opt_accept = CONFIG_REJ;
  1437.                 break;
  1438.             }
  1439.             /* Check if new value is appropriate */
  1440.             if (i16 == PAP_AUTH_TYPE) {
  1441.                 /* Yes, we know Password Auth Protocol */
  1442.                 opt_accept = CONFIG_ACK;
  1443.             } else {
  1444.                 /* We dont know this protocol */
  1445.                 opt_accept = CONFIG_NAK;
  1446.                 i16 = PAP_AUTH_TYPE;
  1447.             }
  1448.             remotep->auth_type = i16;
  1449.             break;
  1450.         case MAGIC_NUMBER:    /* Magic Number */
  1451.             if (Ppptrace > 5)
  1452.                 log(-1, "remote asking for magic number");
  1453.             /* Magic number is a 32bit field */
  1454.             ilen = 4;
  1455.             if (reqopt.len < ilen) {
  1456.                 /* Short option data; reject packet */
  1457.                 opt_accept = CONFIG_REJ;
  1458.                 i32 = 0L;
  1459.                 break;
  1460.             }
  1461.             /* Get proposed value from packet */
  1462.             i32 = pull32(&data);
  1463.             if ((remotep->neg_magic_num == 0)
  1464.                 || (i32 == 0L)) {
  1465.                 /* Not open for negotiation */
  1466.                 opt_accept = CONFIG_REJ;
  1467.                 break;
  1468.             }
  1469.  
  1470.             /* Remote host cant use same magic number as us */
  1471.             if (i32 == lcpiop->lclparm.magic_num) {
  1472.                 opt_accept = CONFIG_NAK;
  1473.                 ++i32;
  1474.                 break;
  1475.             }
  1476.  
  1477.             /* Record new async control character map */
  1478.             opt_accept = CONFIG_ACK;
  1479.             remotep->magic_num = i32;
  1480.             break;
  1481.         case PROT_COMPRESS:
  1482.             if (Ppptrace > 5)
  1483.                 log(-1, "remote asking for protocol compression");
  1484.             /* Presence of option means do protcol compression */
  1485.             ilen = 0;
  1486.             if ((remotep->neg_prot_compress == 0)
  1487.                 && (!DEF_PROT_COMPR)) {
  1488.                 /* We wont do protocol compression */
  1489.                 opt_accept = CONFIG_REJ;
  1490.                 break;
  1491.             }
  1492.  
  1493.             /* Accept request for protocol compression */
  1494.             opt_accept = CONFIG_ACK;
  1495.             remotep->prot_compress = 1;
  1496.             break;
  1497.         case AC_COMPRESS:
  1498.             if (Ppptrace > 5)
  1499.                 log(-1, "remote asking for addr/ctl compression");
  1500.             /* Presence of option means do addr/ctl compression */
  1501.             ilen = 0;
  1502.             if ((remotep->neg_ac_compress == 0)
  1503.                 && (!DEF_AC_COMPR)) {
  1504.                 /* We wont do addr/ctl compression */
  1505.                 opt_accept = CONFIG_REJ;
  1506.                 break;
  1507.             }
  1508.  
  1509.             /* Accept request for addr/ctl compression */
  1510.             opt_accept = CONFIG_ACK;
  1511.             remotep->ac_compress = 1;
  1512.             break;
  1513.  
  1514.         case ENCR_TYPE:        /* Encryption type not implemented */
  1515.         case LINK_QUALITY:    /* Link Qual Monitor not implemented */
  1516.         default:        /* Unknown option */
  1517.             if (Ppptrace > 5)
  1518.                 log(-1, "remote asking for unimplemented option: %x   len: %d",
  1519.                     reqopt.type, reqopt.len);
  1520.             opt_accept = CONFIG_REJ;
  1521.             ilen = reqopt.len;
  1522.             if (len_p(data) < ilen)
  1523.                 ilen = len_p(data);
  1524.             /* Look for standard sizes */
  1525.             if (ilen == 2)
  1526.                 i16 = pull16(&data);
  1527.             else if (ilen == 4) {
  1528.                 i32 = pull32(&data);
  1529.             }
  1530.             /* Other lengths dequeued at echo time */
  1531.  
  1532.             break;
  1533.         }
  1534.         if ((opt_accept == CONFIG_ACK) &&
  1535.             (cnf_accept != CONFIG_ACK))
  1536.             /* This option was good, but a previous      */
  1537.             /* option was not. Return only those options */
  1538.             /* which are being nacked/rejected.          */
  1539.             continue;
  1540.  
  1541.         if (opt_accept == CONFIG_NAK) {
  1542.             if (cnf_accept == CONFIG_REJ)
  1543.                 /* Return only those options */
  1544.                 /* which are being rejected. */
  1545.                 continue;
  1546.             if (cnf_accept == CONFIG_ACK) {
  1547.                 /* Discard current list of good options */
  1548.                 free_p(reply_bp);
  1549.                 reply_bp = NULLBUF;
  1550.                 /* Send a list of nacked options */
  1551.                 cnf_accept = CONFIG_NAK;
  1552.             }
  1553.         }
  1554.  
  1555.         if (opt_accept == CONFIG_REJ) {
  1556.             if (cnf_accept != CONFIG_REJ) {
  1557.                 /* Discard current list of good options */
  1558.                 free_p(reply_bp);
  1559.                 reply_bp = NULLBUF;
  1560.                 /* Send a list of rejected options */
  1561.                 cnf_accept = CONFIG_REJ;
  1562.             }
  1563.         }
  1564.  
  1565.         /* Add option response to the return list */
  1566.         replyopt.type = reqopt.type;
  1567.         replyopt.len = ilen + OPT_HDRLEN;
  1568.         if ((bp = htonopt(&replyopt)) == NULLBUF)
  1569.             break;
  1570.         append(&reply_bp,bp);
  1571.         if (ilen) {
  1572.             if ((bp = alloc_mbuf(ilen)) == NULLBUF)
  1573.                 break;
  1574.             cp = bp->data;
  1575.             switch(ilen) {
  1576.             case 2:
  1577.                 put16(cp,i16);
  1578.                 bp->cnt += 2;
  1579.                 break;
  1580.             case 4:
  1581.                 put32(cp,i32);
  1582.                 bp->cnt += 4;
  1583.                 break;
  1584.             default:
  1585.                 while (ilen--)
  1586.                     bp->data[bp->cnt++] = pullchar(&data);
  1587.             }
  1588.             append(&reply_bp,bp);
  1589.         }
  1590.     }
  1591.  
  1592.     /* Send ACK/NAK/REJ to remote host */
  1593.     if (cnf_accept == CONFIG_ACK) {
  1594.         if (Ppptrace > 1)
  1595.             log(-1, "accept all options requested by remote peer");
  1596.  
  1597.         /* Accept configuration requested by remote host */
  1598.         lcp_sendreply(sp, CONFIG_ACK, reqcnf->id, reply_bp);
  1599.         if (lcpiop->lcp_state == LCP_REQ_SENT) {
  1600.             lcpiop->lcp_state = LCP_ACK_SENT;
  1601.         } else {
  1602.             /* LCP link now open */
  1603.             lcp_open(sp);
  1604.         }
  1605.     } else {
  1606.         if (Ppptrace > 1)
  1607.             log(-1,"options requested by remote peer not accepted: %s",
  1608.                 ((cnf_accept==CONFIG_NAK) ? "NAK" : "REJ"));
  1609.  
  1610.         /* NAK/REJ config request made by remote host */
  1611.         lcp_sendreply(sp, cnf_accept, reqcnf->id, reply_bp);
  1612.  
  1613.         /* Start timer against wait for amended config request */
  1614.         if (lcpiop->lcp_state == LCP_ACK_RCVD)
  1615.             lcp_timer(sp);
  1616.     }
  1617.     free_p(data);
  1618.     return;
  1619. }
  1620.  
  1621. /****************************************************************************/
  1622.  
  1623. /* Timeout while waiting for reply from remote host */
  1624. static void
  1625. lcp_timeout(vp)
  1626. void *vp;
  1627. {
  1628.     struct slip *sp;
  1629.     struct pppctl *pppiop;
  1630.     struct lcpctl *lcpiop;
  1631.  
  1632.     if (Ppptrace > 1)
  1633.         log(-1, "lcp_timeout()");
  1634.  
  1635.     /* Load pointers to interface that timed-out */
  1636.     sp = (struct slip *)vp;
  1637.     pppiop = sp->pppio;
  1638.     lcpiop = &(pppiop->lcpio);
  1639.  
  1640.     /* Attempt to get things going again */
  1641.     switch(lcpiop->lcp_state) {
  1642.     case LCP_ACK_SENT:
  1643.         /* Remote host isnt listening to our request */
  1644.         lcp_reset(pppiop);
  1645.     case LCP_REQ_SENT:
  1646.     case LCP_ACK_RCVD:
  1647.         if (lcpiop->active == 0) {
  1648.             /* If passive open, we got a CONFIG_REQ from remote */
  1649.             /* host but no ACK in response to our CONFIG_REQ    */
  1650.             if (++lcpiop->ack_retry > LCP_RETRY_MAX) {
  1651.                 /* Remote host doesnt seem to be listening */
  1652.                 lcp_shutdown(sp);
  1653.                 break;
  1654.             }
  1655.         }
  1656.         /* Timeout waiting for ACK to our request,         */
  1657.         /* or timeout waiting for request from remote host */
  1658.         lcp_sendreq(sp);
  1659.         break;
  1660.  
  1661.     case LCP_TERMINATE:
  1662.         /* Timeout waiting for terminate ACK; send another request */
  1663.         if (++lcpiop->ack_retry > LCP_TERM_RETRY) {
  1664.             /* No response to our polite request; give it up */
  1665.  
  1666.             if (Ppptrace)
  1667.                 log(-1,"%s: PPP/LCP Connection Closed without reply from remote peer",sp->iface->name);
  1668.             if (lcpiop->active == 0)
  1669.                 lcpiop->lcp_state = LCP_LISTEN;
  1670.             else
  1671.                 lcpiop->lcp_state = LCP_CLOSED;
  1672.  
  1673.             lcp_sendreply(sp,TERMINATE_ACK,0,NULLBUF);
  1674.             lcp_reset(pppiop);
  1675.             tprintf("Still no response; marking LCP layer as closed\n");
  1676.             pppiop->state = PPP_CLOSED;
  1677.             psignal(lcpiop,0);
  1678.         } else {
  1679.             /* Request remote host to close data link */
  1680.             tprintf("Timeout waiting for response to our LCP terminate request\n");
  1681.             lcp_timer(sp);
  1682.             lcp_sendreply(sp, TERMINATE_REQ, 0, NULLBUF);
  1683.         }
  1684.         break;
  1685.  
  1686.     case LCP_CLOSED:
  1687.     case LCP_LISTEN:
  1688.     case LCP_OPEN:
  1689.     default:
  1690.         /* Confusion; shutdown the connection */
  1691.         lcp_shutdown(sp);
  1692.         break;
  1693.     }
  1694.     return;
  1695. }
  1696.  
  1697. /* Set a timer in case an expected event does not occur */
  1698. static void
  1699. lcp_timer(sp)
  1700. struct slip *sp;
  1701. {
  1702.     struct pppctl *pppiop;
  1703.     struct lcpctl *lcpiop;
  1704.     struct timer *t;
  1705.  
  1706.     if (Ppptrace > 5)
  1707.         log(-1,"lcp_timer()");
  1708.  
  1709.     pppiop = sp->pppio;
  1710.     lcpiop = &(pppiop->lcpio);
  1711.     t = &(lcpiop->lcp_tm);
  1712.     t->func = (void (*)())lcp_timeout;
  1713.     t->arg = (void *)sp;
  1714.     start_timer(t);
  1715.     return;
  1716. }
  1717.  
  1718. /****************************************************************************/
  1719.  
  1720. /* Send an LCP packet to the remote host */
  1721. static int
  1722. lcp_sendreply(sp,code,id,data)
  1723. struct slip *sp;
  1724. char code;
  1725. unsigned char id;
  1726. struct mbuf *data;
  1727. {
  1728.     struct iface *iface;
  1729.     struct cnfhdr hdr;
  1730.  
  1731.     /* Load LCP header values */
  1732.     hdr.code = code;
  1733.     switch(code) {
  1734.     case CONFIG_REQ:
  1735.     case TERMINATE_REQ:
  1736.     case ECHO_REQ:
  1737.         /* Save ID field for match aginst replies from remote host */
  1738.         sp->pppio->lcpio.lastid = Pppid;
  1739.     case PROT_REJ:
  1740.     case DISCARD_REQ:
  1741.         /* Use a unique ID field value */
  1742.         hdr.id = Pppid++;
  1743.         break;
  1744.  
  1745.     case CONFIG_ACK:
  1746.     case CONFIG_NAK:
  1747.     case CONFIG_REJ:
  1748.     case TERMINATE_ACK:
  1749.     case CODE_REJ:
  1750.     case ECHO_REPLY:
  1751.         /* Use ID sent by remote host */
  1752.         hdr.id = id;
  1753.         break;
  1754.  
  1755.     default:
  1756.         /* Shouldnt happen */
  1757.         if (Ppptrace)
  1758.             log(-1, "bogus code: %x", code);
  1759.         return -1;
  1760.     }
  1761.     hdr.len = len_p(data) + CNF_HDRLEN;
  1762.     if (Ppptrace > 1) {
  1763.         log(-1, "%s: PPP/LCP Send: current state: %s   LCP option: %s   id: %d   len: %d",
  1764.             sp->iface->name,
  1765.             LCPStates[sp->pppio->lcpio.lcp_state],
  1766.             LCPCodes[code],hdr.id,hdr.len);
  1767.     }
  1768.  
  1769.     /* Prepend LCP header to packet data */
  1770.     if ((data = htoncnf(&hdr,data)) == NULLBUF)
  1771.         return -1;
  1772.  
  1773.     /* Send LCP packet to remote host */
  1774.     sp->pppio->sndlcp++;
  1775.     iface = sp->iface;
  1776.     return( (*iface->output)
  1777.         (iface, NULLCHAR, NULLCHAR, PPP_LCP_TYPE, data) );
  1778. }
  1779.  
  1780. /* Process incoming LCP packet */
  1781. void
  1782. lcpproc(iface,bp)
  1783. struct iface *iface;
  1784. struct mbuf *bp;
  1785. {
  1786.     struct slip *sp;
  1787.     struct cnfhdr hdr;
  1788.  
  1789.     sp = &Slip[iface->xdev];
  1790.  
  1791.     /* Extract LCP header */
  1792.     ntohcnf(&hdr, &bp);
  1793.     hdr.len -= CNF_HDRLEN;            /* Length includes envelope */
  1794.     trim_mbuf(&bp, hdr.len);        /* Trim off FCS bytes */
  1795.  
  1796.     if (Ppptrace > 1)
  1797.         log(-1,    "%s: PPP/LCP Recv: current state: %s:   LCP option: %s  id: %d len: %d",
  1798.             iface->name,
  1799.             LCPStates[sp->pppio->lcpio.lcp_state],
  1800.             LCPCodes[hdr.code], hdr.id, hdr.len);
  1801.  
  1802.     /* Process LCP packet data */
  1803.     switch(hdr.code) {
  1804.     case CONFIG_REQ:            /* Request of remote host */
  1805.         lcp_rcvreq(sp, &hdr, bp);
  1806.         break;
  1807.     case CONFIG_ACK:            /* Remote accepted our req */
  1808.         lcp_rcvack(sp, &hdr, bp);
  1809.         break;
  1810.     case CONFIG_NAK:            /* Remote adjusted our req */
  1811.         lcp_rcvnak(sp, &hdr, bp);
  1812.         break;
  1813.     case CONFIG_REJ:            /* Remote rejected our req */
  1814.         lcp_rcvrej(sp, &hdr, bp);
  1815.         break;
  1816.     case TERMINATE_REQ:            /* Remote request to close */
  1817.         lcp_rcvtermreq(sp, &hdr);
  1818.         break;
  1819.     case TERMINATE_ACK:            /* Remote closed on request */
  1820.         lcp_rcvtermack(sp);
  1821.         break;
  1822.  
  1823.     case CODE_REJ:
  1824.     case PROT_REJ:
  1825.     case ECHO_REQ:
  1826.     case ECHO_REPLY:
  1827.     case DISCARD_REQ:
  1828.         if (Ppptrace)
  1829.             log(-1,"Unimplemented LCP packet type: %x; dropping packet",hdr.code);
  1830.         free_p(bp);
  1831.         break;
  1832.     default:
  1833.         if (Ppptrace)
  1834.             log(-1,"Unknown LCP packet type: %x; dropping packet",hdr.code);
  1835.         free_p(bp);
  1836.         break;
  1837.     }
  1838.     return;
  1839. }
  1840.