home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / SUN / PPP / SUNOS_OL / DDP_PPP.TAR / lcp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-01-03  |  21.6 KB  |  921 lines

  1. /*
  2.  * lcp.c - PPP Link Control Protocol.
  3.  *
  4.  * Copyright (c) 1989 Carnegie Mellon University.
  5.  * All rights reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms are permitted
  8.  * provided that the above copyright notice and this paragraph are
  9.  * duplicated in all such forms and that any documentation,
  10.  * advertising materials, and other materials related to such
  11.  * distribution and use acknowledge that the software was developed
  12.  * by Carnegie Mellon University.  The name of the
  13.  * University may not be used to endorse or promote products derived
  14.  * from this software without specific prior written permission.
  15.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  16.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  17.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  18.  */
  19.  
  20. /*
  21.  * TODO:
  22.  * Keepalive.
  23.  * Encryption.
  24.  * Send NAKs for unsent CIs.
  25.  * Keep separate MTU, MRU.
  26.  * Option tracing.
  27.  * Extra data on authtype option.
  28.  * Test restart.
  29.  */
  30.  
  31. #include <stdio.h>
  32. #include <sys/ioctl.h>
  33. #include <sys/types.h>
  34. #include <sys/socket.h>
  35. #include <sys/time.h>
  36.  
  37. #include <net/if.h>
  38. #include <netinet/in.h>
  39.  
  40. #include "ppp.h"
  41. #include "fsm.h"
  42. #include "lcp.h"
  43.  
  44.  
  45. void lcp_resetci();        /* Reset our Configuration Information */
  46. int lcp_cilen();        /* Return length of our CI */
  47. void lcp_addci();        /* Add our CIs */
  48. int lcp_ackci();        /* Ack some CIs */
  49. void lcp_nakci();        /* Nak some CIs */
  50. void lcp_rejci();        /* Reject some CIs */
  51. u_char lcp_reqci();        /* Check the requested CIs */
  52. void lcp_up();            /* We're UP */
  53. void lcp_down();        /* We're DOWN */
  54. void lcp_closed();        /* We're CLOSED */
  55.  
  56.  
  57. fsm lcp_fsm[NPPP];        /* LCP fsm structure */
  58.  
  59. fsm_callbacks lcp_callbacks = {    /* LCP callback routines */
  60.     lcp_resetci,        /* Reset our Configuration Information */
  61.     lcp_cilen,            /* Length of our Configuration Information */
  62.     lcp_addci,            /* Add our Configuration Information */
  63.     lcp_ackci,            /* ACK our Configuration Information */
  64.     lcp_nakci,            /* NAK our Configuration Information */
  65.     lcp_rejci,            /* Reject our Configuration Information */
  66.     lcp_reqci,            /* Request peer's Configuration Information */
  67.     lcp_up,            /* Called when fsm reaches OPEN state */
  68.     lcp_down,            /* Called when fsm leaves OPEN state */
  69.     lcp_closed,            /* Called when fsm reaches CLOSED state */
  70.     NULL,            /* Called when Protocol-Reject received */
  71.     NULL            /* Retransmission is necessary */
  72. };
  73.  
  74.  
  75. lcp_options lcp_wantoptions[NPPP]; /* Options that we want to request */
  76. lcp_options lcp_gotoptions[NPPP]; /* Options that peer ack'd */
  77. lcp_options lcp_allowoptions[NPPP]; /* Options that we allow peer to request */
  78. lcp_options lcp_hisoptions[NPPP]; /* Options that we ack'd */
  79.  
  80.  
  81. #define DEFWARNLOOPS    10    /* XXX Move to lcp.h */
  82. int lcp_warnloops = DEFWARNLOOPS; /* Warn about a loopback this often */
  83.  
  84.  
  85. /*
  86.  * lcp_init - Initialize LCP.
  87.  */
  88. void lcp_init(unit)
  89.     int unit;
  90. {
  91.     fsm *f = &lcp_fsm[unit];
  92.     lcp_options *wo = &lcp_wantoptions[unit];
  93.     lcp_options *ao = &lcp_allowoptions[unit];
  94.  
  95.     f->unit = unit;
  96.     f->protocol = LCP;
  97.     f->timeouttime = DEFTIMEOUT;
  98.     f->maxtermtransmits = DEFMAXTERMTRANSMITS;
  99.     f->maxnakloops = DEFMAXNAKLOOPS;
  100.     f->callbacks = &lcp_callbacks;
  101.  
  102.     wo->passive = 0;
  103.     wo->restart = 0;            /* Set to 1 in kernels or multi-line
  104.                        implementations */
  105.  
  106.     wo->neg_mru = 1;
  107.     wo->mru = DEFMRU;
  108.     wo->neg_asyncmap = 1;
  109.     wo->asyncmap = 0;
  110.     wo->neg_upap = 0;            /* Set to 1 on server */
  111.     wo->neg_encrypttype = 0;
  112.     wo->encrypttype = 0;
  113.     wo->neg_magicnumber = 1;
  114. #if 0
  115.     wo->neg_keepalive = 0;
  116. #endif
  117.     wo->neg_pcompression = 1;
  118.     wo->neg_accompression = 1;
  119.  
  120.     ao->neg_mru = 1;
  121.     ao->neg_asyncmap = 1;
  122.     ao->neg_upap = 0;            /* Set to 1 on client */
  123.     ao->neg_encrypttype = 0;
  124.     ao->neg_magicnumber = 1;
  125. #if 0
  126.     ao->neg_keepalive = 0;
  127. #endif
  128.     ao->neg_pcompression = 1;
  129.     ao->neg_accompression = 1;
  130.  
  131.     fsm_init(f);
  132. }
  133.  
  134.  
  135. /*
  136.  * lcp_activeopen - Actively open LCP.
  137.  */
  138. void lcp_activeopen(unit)
  139.     int unit;
  140. {
  141.     fsm_activeopen(&lcp_fsm[unit]);
  142. }
  143.  
  144.  
  145. /*
  146.  * lcp_passiveopen - Passively open LCP.
  147.  */
  148. void lcp_passiveopen(unit)
  149.     int unit;
  150. {
  151.     fsm_passiveopen(&lcp_fsm[unit]);
  152. }
  153.  
  154.  
  155. /*
  156.  * lcp_close - Close LCP.
  157.  */
  158. void lcp_close(unit)
  159.     int unit;
  160. {
  161.     fsm_close(&lcp_fsm[unit]);
  162. }
  163.  
  164.  
  165. /*
  166.  * lcp_lowerup - The lower layer is up.
  167.  */
  168. void lcp_lowerup(unit)
  169.     int unit;
  170. {
  171.     SIFDOWN(unit);
  172.     SIFMTU(unit, MTU);
  173.     SIFASYNCMAP(unit, 0xffffffff);
  174.     CIFPCOMPRESSION(unit);
  175.     CIFACCOMPRESSION(unit);
  176.  
  177.     fsm_lowerup(&lcp_fsm[unit]);
  178. }
  179.  
  180.  
  181. /*
  182.  * lcp_lowerdown - The lower layer is down.
  183.  */
  184. void lcp_lowerdown(unit)
  185.     int unit;
  186. {
  187.     fsm_lowerdown(&lcp_fsm[unit]);
  188. }
  189.  
  190.  
  191. /*
  192.  * lcp_input - Input LCP packet.
  193.  */
  194. void lcp_input(unit, p, len)
  195.     int unit;
  196.     PACKET *p;
  197.     int len;
  198. {
  199.     fsm_input(&lcp_fsm[unit], p, len);
  200. }
  201.  
  202.  
  203. /*
  204.  * lcp_protrej - A Protocol-Reject was received.
  205.  */
  206. void lcp_protrej(unit)
  207.     int unit;
  208. {
  209.     /*
  210.      * Can't reject LCP!
  211.      */
  212.     FSMDEBUG((stderr,
  213.           "ppp: lcp_protrej: Received Protocol-Reject for LCP!\n"));
  214. }
  215.  
  216.  
  217. /*
  218.  * lcp_sprotrej - Send a Protocol-Reject for some protocol.
  219.  */
  220. void lcp_sprotrej(unit, p, len)
  221.     int unit;
  222.     PACKET *p;
  223.     int len;
  224. {
  225.     fsm_sdata(&lcp_fsm[unit], PROTREJ, ++lcp_fsm[unit].id,
  226.           PACKET_DATA(p), len);
  227.     PACKET_FREE(p);
  228. }
  229.  
  230.  
  231. /*
  232.  * lcp_resetci - Reset our CI.
  233.  */
  234. void lcp_resetci(f)
  235.     fsm *f;
  236. {
  237.     lcp_wantoptions[f->unit].magicnumber = magic();
  238.     lcp_wantoptions[f->unit].numloops = 0;
  239.     lcp_gotoptions[f->unit] = lcp_wantoptions[f->unit];
  240. }
  241.  
  242.  
  243. /*
  244.  * lcp_cilen - Return length of our CI.
  245.  */
  246. int lcp_cilen(f)
  247.     fsm *f;
  248. {
  249.     lcp_options *go = &lcp_gotoptions[f->unit];
  250.  
  251. #define LENCIVOID(neg) (neg ? 2 : 0)
  252. #define LENCISHORT(neg)  (neg ? 4 : 0)
  253. #define LENCILONG(neg)  (neg ? 6 : 0)
  254.  
  255.     return (LENCISHORT(go->neg_mru) +
  256.         LENCILONG(go->neg_asyncmap) +
  257.         LENCISHORT(go->neg_upap) +
  258.         LENCISHORT(go->neg_encrypttype) +
  259.         LENCILONG(go->neg_magicnumber) +
  260. #if 0
  261.         LENCI(go->neg_keepalive) +
  262. #endif
  263.         LENCIVOID(go->neg_pcompression) +
  264.         LENCIVOID(go->neg_accompression));
  265. }
  266.  
  267.  
  268. /*
  269.  * lcp_addci - Add our desired CIs to a packet.
  270.  */
  271. void lcp_addci(f, ucp)
  272.     fsm *f;
  273.     u_char *ucp;
  274. {
  275.     lcp_options *go = &lcp_gotoptions[f->unit];
  276.  
  277. #define ADDCIVOID(opt, neg) \
  278.     if (neg) { \
  279.     PUTCHAR(opt, ucp); \
  280.     PUTCHAR(2, ucp); \
  281.     }
  282. #define ADDCISHORT(opt, neg, val) \
  283.     if (neg) { \
  284.     PUTCHAR(opt, ucp); \
  285.     PUTCHAR(2 + sizeof (short), ucp); \
  286.     PUTSHORT(val, ucp); \
  287.     }
  288. #define ADDCILONG(opt, neg, val) \
  289.     if (neg) { \
  290.     PUTCHAR(opt, ucp); \
  291.     PUTCHAR(2 + sizeof (long), ucp); \
  292.     PUTLONG(val, ucp); \
  293.     }
  294.  
  295.     ADDCISHORT(CI_MRU, go->neg_mru, go->mru)
  296.     ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap, go->asyncmap)
  297.     ADDCISHORT(CI_AUTHTYPE, go->neg_upap, UPAP)
  298.     ADDCISHORT(CI_ENCRYPTTYPE, go->neg_encrypttype, go->encrypttype)
  299.     ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber)
  300. #if 0
  301.     ADDCI(CI_KEEPALIVE, go->neg_keepalive, go->keepalive)
  302. #endif
  303.     ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression)
  304.     ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression)
  305. }
  306.  
  307.  
  308. /*
  309.  * lcp_ackci - Ack our CIs.
  310.  *
  311.  * Returns:
  312.  *    0 - Ack was bad.
  313.  *    1 - Ack was good.
  314.  */
  315. int lcp_ackci(f, p, len)
  316.     fsm *f;
  317.     u_char *p;
  318.     int len;
  319. {
  320.     lcp_options *go = &lcp_gotoptions[f->unit];
  321.     u_char cilen, citype;
  322.     u_short cishort;
  323.     u_long cilong;
  324.  
  325.     /*
  326.      * CIs must be in exactly the same order that we sent.
  327.      * Check packet length and CI length at each step.
  328.      * If we find any deviations, then this packet is bad.
  329.      */
  330. #define ACKCIVOID(opt, neg) \
  331.     if (neg) { \
  332.     if ((len -= 2) < 0) \
  333.         goto bad; \
  334.     GETCHAR(citype, p); \
  335.     GETCHAR(cilen, p); \
  336.     if (cilen != 2 || \
  337.         citype != opt) \
  338.         goto bad; \
  339.     }
  340. #define ACKCISHORT(opt, neg, val) \
  341.     if (neg) { \
  342.     if ((len -= 2 + sizeof (short)) < 0) \
  343.         goto bad; \
  344.     GETCHAR(citype, p); \
  345.     GETCHAR(cilen, p); \
  346.     if (cilen != 2 + sizeof (short) || \
  347.         citype != opt) \
  348.         goto bad; \
  349.     GETSHORT(cishort, p); \
  350.     if (cishort != val) \
  351.         goto bad; \
  352.     }
  353. #define ACKCILONG(opt, neg, val) \
  354.     if (neg) { \
  355.     if ((len -= 2 + sizeof (long)) < 0) \
  356.         goto bad; \
  357.     GETCHAR(citype, p); \
  358.     GETCHAR(cilen, p); \
  359.     if (cilen != 2 + sizeof (long) || \
  360.         citype != opt) \
  361.         goto bad; \
  362.     GETLONG(cilong, p); \
  363.     if (cilong != val) \
  364.         goto bad; \
  365.     }
  366.  
  367.     ACKCISHORT(CI_MRU, go->neg_mru, go->mru)
  368.     ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap, go->asyncmap)
  369.     ACKCISHORT(CI_AUTHTYPE, go->neg_upap, UPAP)
  370.     ACKCISHORT(CI_ENCRYPTTYPE, go->neg_encrypttype, go->encrypttype)
  371.     ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber)
  372. #if 0
  373.     ACKCI(CI_KEEPALIVE, go->neg_keepalive, go->keepalive)
  374. #endif
  375.     ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression)
  376.     ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression)
  377.  
  378.     /*
  379.      * If there are any remaining CIs, then this packet is bad.
  380.      */
  381.     if (len != 0)
  382.     goto bad;
  383.     return (1);
  384. bad:
  385.     LCPDEBUG((stderr, "ppp: lcp_acki: received bad Ack!\n"));
  386.     return (0);
  387. }
  388.  
  389.  
  390. /*
  391.  * lcp_nakci - NAK some of our CIs.
  392.  */
  393. void lcp_nakci(f, p, len)
  394.     fsm *f;
  395.     u_char *p;
  396.     int len;
  397. {
  398.     lcp_options *go = &lcp_gotoptions[f->unit];
  399.     lcp_options *wo = &lcp_wantoptions[f->unit];
  400.     u_short cishort;
  401.     u_long cilong;
  402.  
  403.     /*
  404.      * Any Nak'd CIs must be in exactly the same order that we sent.
  405.      * Check packet length and CI length at each step.
  406.      * If we find any deviations, then this packet is bad.
  407.      */
  408. #define NAKCIVOID(opt, neg, code) \
  409.     if (neg && \
  410.     len >= 2 && \
  411.     p[1] == 2 && \
  412.     p[0] == opt) { \
  413.     len -= 2; \
  414.     INCPTR(2, p); \
  415.     code \
  416.     }
  417. #define NAKCISHORT(opt, neg, code) \
  418.     if (neg && \
  419.     len >= 2 + sizeof (short) && \
  420.     p[1] == 2 + sizeof (short) && \
  421.     p[0] == opt) { \
  422.     len -= 2 + sizeof (short); \
  423.     INCPTR(2, p); \
  424.     GETSHORT(cishort, p); \
  425.     code \
  426.     }
  427. #define NAKCILONG(opt, neg, code) \
  428.     if (neg && \
  429.     len >= 2 + sizeof (long) && \
  430.     p[1] == 2 + sizeof (long) && \
  431.     p[0] == opt) { \
  432.     len -= 2 + sizeof (long); \
  433.     INCPTR(2, p); \
  434.     GETLONG(cilong, p); \
  435.     code \
  436.     }
  437.  
  438.     /*
  439.      * We don't care if they want to send us smaller packets than
  440.      * we want.  Therefore, accept any MRU less than what we asked for,
  441.      * but then ignore the new value when setting the MRU in the kernel.
  442.      * If they send us a bigger MRU than what we asked, reject it and
  443.      * let him decide to accept our value.
  444.      */
  445.     NAKCISHORT(CI_MRU, go->neg_mru,
  446.            if (cishort <= wo->mru)
  447.             go->mru = cishort;
  448.            else
  449.             goto bad;
  450.            )
  451.     NAKCILONG(CI_ASYNCMAP, go->neg_asyncmap,
  452.           go->asyncmap |= cilong;
  453.           )
  454.     NAKCISHORT(CI_AUTHTYPE, go->neg_upap,
  455.            fprintf(stderr, "ppp: Peer refuses to authenticate!\n");
  456.            )
  457.     NAKCISHORT(CI_ENCRYPTTYPE, go->neg_encrypttype,
  458.            go->neg_encrypttype = 0;
  459.            )
  460.     NAKCILONG(CI_MAGICNUMBER, go->neg_magicnumber,
  461.           go->magicnumber = magic();
  462.           if (++go->numloops % lcp_warnloops == 0)
  463.           fprintf(stderr, "ppp: The line appears to be looped back.\n");
  464.           )
  465. #if 0
  466.     NAKCI(CI_KEEPALIVE, go->neg_keepalive,
  467.       )
  468. #endif
  469.     NAKCIVOID(CI_PCOMPRESSION, go->neg_pcompression,
  470.            go->neg_pcompression = 0;
  471.           )
  472.     NAKCIVOID(CI_ACCOMPRESSION, go->neg_accompression,
  473.            go->neg_accompression = 0;
  474.           )
  475.  
  476.     /*
  477.      * If there are any remaining CIs, then this packet is bad.
  478.      */
  479.     if (len == 0)
  480.     return;
  481. bad:
  482.     LCPDEBUG((stderr, "ppp: lcp_nakci: received bad Nak!\n"));
  483. }
  484.  
  485.  
  486. /*
  487.  * lcp_rejci - Reject some of our CIs.
  488.  */
  489. void lcp_rejci(f, p, len)
  490.     fsm *f;
  491.     u_char *p;
  492.     int len;
  493. {
  494.     lcp_options *go = &lcp_gotoptions[f->unit];
  495.     u_short cishort;
  496.     u_long cilong;
  497.  
  498.     /*
  499.      * Any Rejected CIs must be in exactly the same order that we sent.
  500.      * Check packet length and CI length at each step.
  501.      * If we find any deviations, then this packet is bad.
  502.      */
  503. #define REJCIVOID(opt, neg) \
  504.     if (neg && \
  505.     len >= 2 && \
  506.     p[1] == 2 && \
  507.     p[0] == opt) { \
  508.     len -= 2; \
  509.     INCPTR(2, p); \
  510.     neg = 0; \
  511.     }
  512. #define REJCISHORT(opt, neg, val) \
  513.     if (neg && \
  514.     len >= 2 + sizeof (short) && \
  515.     p[1] == 2 + sizeof (short) && \
  516.     p[0] == opt) { \
  517.     len -= 2 + sizeof (short); \
  518.     INCPTR(2, p); \
  519.     GETSHORT(cishort, p); \
  520.     /* Check rejected value. */ \
  521.     if (cishort != val) \
  522.         goto bad; \
  523.     neg = 0; \
  524.     }
  525. #define REJCILONG(opt, neg, val) \
  526.     if (neg && \
  527.     len >= 2 + sizeof (long) && \
  528.     p[1] == 2 + sizeof (long) && \
  529.     p[0] == opt) { \
  530.     len -= 2 + sizeof (long); \
  531.     INCPTR(2, p); \
  532.     GETLONG(cilong, p); \
  533.     /* Check rejected value. */ \
  534.     if (cilong != val) \
  535.         goto bad; \
  536.     neg = 0; \
  537.     }
  538.  
  539.     REJCISHORT(CI_MRU, go->neg_mru, go->mru)
  540.     REJCILONG(CI_ASYNCMAP, go->neg_asyncmap, go->asyncmap)
  541.     REJCISHORT(CI_AUTHTYPE, go->neg_upap, UPAP)
  542.     REJCISHORT(CI_ENCRYPTTYPE, go->neg_encrypttype, go->encrypttype)
  543.     REJCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber)
  544. #if 0
  545.     REJCI(CI_KEEPALIVE, go->neg_keepalive, go->keepalive)
  546. #endif
  547.     REJCIVOID(CI_PCOMPRESSION, go->neg_pcompression)
  548.     REJCIVOID(CI_ACCOMPRESSION, go->neg_accompression)
  549.  
  550.     /*
  551.      * If there are any remaining CIs, then this packet is bad.
  552.      */
  553.     if (len == 0)
  554.     return;
  555. bad:
  556.     LCPDEBUG((stderr, "ppp: lcp_rejci: received bad Reject!\n"));
  557. }
  558.  
  559.  
  560. /*
  561.  * lcp_reqci - Check the peer's requested CIs and send appropriate response.
  562.  *
  563.  * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
  564.  * appropriately.
  565.  */
  566. u_char lcp_reqci(f, inp, len)
  567.     fsm *f;
  568.     u_char *inp;        /* Requested CIs */
  569.     int *len;            /* Length of requested CIs */
  570. {
  571.     lcp_options *go = &lcp_gotoptions[f->unit];
  572.     lcp_options *ho = &lcp_hisoptions[f->unit];
  573.     lcp_options *ao = &lcp_allowoptions[f->unit];
  574.     u_char *cip;        /* Pointer to Current CI */
  575.     u_char cilen, citype;    /* Parsed len, type, char value */
  576.     u_short cishort;        /* Parsed short value */
  577.     u_long cilong;        /* Parse long value */
  578.     int rc = CONFACK;        /* Final packet return code */
  579.     int orc;            /* Individual option return code */
  580.     u_char *p = inp;        /* Pointer to next char to parse */
  581.     u_char *ucp = inp;        /* Pointer to current output char */
  582.     int l = *len;        /* Length left */
  583.  
  584.     /*
  585.      * Reset all his options.
  586.      */
  587.     ho->neg_mru = 0;
  588.     ho->neg_asyncmap = 0;
  589.     ho->neg_upap = 0;
  590.     ho->neg_encrypttype = 0;
  591.     ho->neg_magicnumber = 0;
  592. #if 0
  593.     ho->neg_keepalive = 0;
  594. #endif
  595.     ho->neg_pcompression = 0;
  596.     ho->neg_accompression = 0;
  597.  
  598.     /*
  599.      * Process all his options.
  600.      */
  601.     while (l) {
  602.     orc = CONFACK;            /* Assume success */
  603.     cip = p;            /* Remember begining of CI */
  604.     if (l < 2 ||            /* Not enough data for CI header or */
  605.         p[1] < 2 ||            /*  CI length too small or */
  606.         p[1] > l) {            /*  CI length too big? */
  607.         LCPDEBUG((stderr, "ppp: lcp_reqci: bad CI length!\n"));
  608.         orc = CONFREJ;        /* Reject bad CI */
  609.         cilen = l;            /* Reject till end of packet */
  610.         l = 0;            /* Don't loop again */
  611.         goto endswitch;
  612.     }
  613.     GETCHAR(citype, p);        /* Parse CI type */
  614.     GETCHAR(cilen, p);        /* Parse CI length */
  615.     l -= cilen;            /* Adjust remaining length */
  616.     cilen -= 2;            /* Adjust cilen to just data */
  617.  
  618.     switch (citype) {        /* Check CI type */
  619.       case CI_MRU:
  620.         LCPDEBUG((stderr, "ppp: lcp_reqci: rcvd MRU"));
  621.         if (!ao->neg_mru ||        /* Allow option? */
  622.         cilen != sizeof (short)) { /* Check CI length */
  623.         INCPTR(cilen, p);     /* Skip rest of CI */
  624.         orc = CONFREJ;        /* Reject CI */
  625.         break;
  626.         }
  627.         GETSHORT(cishort, p);    /* Parse MRU */
  628.         LCPDEBUG((stderr, "(%d)", cishort));
  629.  
  630.         /*
  631.          * He must be able to receive at least our minimum.
  632.          * No need to check a maximum.  If he sends a large number,
  633.          * we'll just ignore it.
  634.          */
  635.         if (cishort < MINMRU) {
  636.         orc = CONFNAK;        /* Nak CI */
  637.         DECPTR(sizeof (short), p); /* Backup */
  638.         PUTSHORT(MINMRU, p);    /* Give him a hint */
  639.         break;
  640.         }
  641.         ho->neg_mru = 1;        /* Remember he sent and MRU */
  642.         ho->mru = cishort;        /* And remember value */
  643.         break;
  644.  
  645.       case CI_ASYNCMAP:
  646.         LCPDEBUG((stderr, "ppp: lcp_reqci: rcvd ASYNCMAP"));
  647.         if (!ao->neg_asyncmap ||
  648.         cilen != sizeof (long)) {
  649.         INCPTR(cilen, p);
  650.         orc = CONFREJ;
  651.         break;
  652.         }
  653.         GETLONG(cilong, p);
  654.         LCPDEBUG((stderr, "(%lx)", cilong));
  655.  
  656.         /* XXX Accept anything he says */
  657. #if 0
  658.         /*
  659.          * Asyncmap must be OR of two maps.
  660.          */
  661.         if ((lcp_wantoptions[f->unit].neg_asyncmap &&
  662.          cilong != (lcp_wantoptions[f->unit].asyncmap | cilong)) ||
  663.         (!lcp_wantoptions[f->unit].neg_asyncmap &&
  664.          cilong != 0xffffffff)) {
  665.         orc = CONFNAK;
  666.         DECPTR(sizeof (long), p);
  667.         PUTLONG(lcp_wantoptions[f->unit].neg_asyncmap ?
  668.             lcp_wantoptions[f->unit].asyncmap | cilong :
  669.             0xffffffff, p);
  670.         break;
  671.         }
  672. #endif
  673.         ho->neg_asyncmap = 1;
  674.         ho->asyncmap = cilong;
  675.         break;
  676.  
  677.       case CI_AUTHTYPE:
  678.         LCPDEBUG((stderr, "ppp: lcp_reqci: rcvd AUTHTYPE"));
  679.         if (!ao->neg_upap ||
  680.         cilen < sizeof (short)) {
  681.         INCPTR(cilen, p);
  682.         orc = CONFREJ;
  683.         break;
  684.         }
  685.         GETSHORT(cishort, p);
  686.         LCPDEBUG((stderr, "(%x)", cishort));
  687.  
  688.         /*
  689.          * Authtype must be UPAP.
  690.          */
  691.         if (cishort != UPAP) {
  692.         DECPTR(sizeof (short), p);
  693.         orc = CONFNAK;
  694.         PUTSHORT(UPAP, p);
  695.         INCPTR(cilen - sizeof (u_short), p);
  696.         break;
  697.         }
  698.         INCPTR(cilen - sizeof (u_short), p);
  699.         ho->neg_upap = 1;
  700.         break;
  701.  
  702. #if 0
  703. /* XXX */
  704.       case CI_ENCRYPTTYPE:
  705.         if (!ao->neg_encrypttype ||
  706.         cilen != sizeof (short)) {
  707.         INCPTR(cilen, p);
  708.         orc = CONFREJ;
  709.         break;
  710.         }
  711.         GETSHORT(cishort, p);
  712.         LCPDEBUG((stderr, "(%d)", cishort));
  713.  
  714.         /*
  715.          * Encrypttype must be XXX.
  716.          */
  717.         if (XXX) {
  718.         DECPTR(sizeof (short), p);
  719.         orc = CONFNAK;
  720.         PUTSHORT(XXX, p);
  721.         break;
  722.         }
  723.         ho->neg_encrypttype = 1;
  724.         ho->encrypttype = cishort;
  725.         break;
  726. #endif
  727.  
  728.       case CI_MAGICNUMBER:
  729.         LCPDEBUG((stderr, "ppp: lcp_reqci: rcvd MAGICNUMBER"));
  730.         if (!ao->neg_magicnumber ||
  731.         cilen != sizeof (long)) {
  732.         INCPTR(cilen, p);
  733.         orc = CONFREJ;
  734.         break;
  735.         }
  736.         GETLONG(cilong, p);
  737.         LCPDEBUG((stderr, "(%lx)", cilong));
  738.  
  739.         /*
  740.          * He must have a different magic number.
  741.          */
  742.         if (go->neg_magicnumber &&
  743.         cilong == go->magicnumber) {
  744.         orc = CONFNAK;
  745.         DECPTR(sizeof (long), p);
  746.         cilong = magic();    /* Don't put magic() inside macro! */
  747.         PUTLONG(cilong, p);
  748.         break;
  749.         }
  750.         ho->neg_magicnumber = 1;
  751.         ho->magicnumber = cilong;
  752.         break;
  753.  
  754. #if 0
  755.       case CI_KEEPALIVE:
  756.         if (!ao->neg_keepalive ||
  757.         cilen != )) {
  758.         INCPTR(cilen, p);
  759.         orc = CONFREJ;
  760.         break;
  761.         }
  762.         GET(ci, p);
  763.         LCPDEBUG((stderr, "(%d)", cishort));
  764.  
  765.         /*
  766.          * He must XXX
  767.          */
  768.         if () {
  769.         orc = CONFNAK;
  770.         DECPTR(sizeof (), p);
  771.         PUT(, p);
  772.         break;
  773.         }
  774.         ho->neg_keepalive = 1;
  775.         ho->keepalive = ;
  776.         break;
  777. #endif
  778.  
  779.       case CI_PCOMPRESSION:
  780.         LCPDEBUG((stderr, "ppp: lcp_reqci: rcvd PCOMPRESSION"));
  781.         if (!ao->neg_pcompression ||
  782.         cilen != 0) {
  783.         INCPTR(cilen, p);
  784.         orc = CONFREJ;
  785.         break;
  786.         }
  787.         ho->neg_pcompression = 1;
  788.         break;
  789.  
  790.       case CI_ACCOMPRESSION:
  791.         LCPDEBUG((stderr, "ppp: lcp_reqci: rcvd ACCOMPRESSION"));
  792.         if (!ao->neg_accompression ||
  793.         cilen != 0) {
  794.         INCPTR(cilen, p);
  795.         orc = CONFREJ;
  796.         break;
  797.         }
  798.         ho->neg_accompression = 1;
  799.         break;
  800.  
  801.       default:
  802.         LCPDEBUG((stderr, "ppp: lcp_reqci: rcvd unknown option %d",
  803.               citype));
  804.         INCPTR(cilen, p);
  805.         orc = CONFREJ;
  806.         break;
  807.     }
  808.     cilen += 2;            /* Adjust cilen whole CI */
  809.  
  810. endswitch:
  811.     LCPDEBUG((stderr, " (%s)\n",
  812.           orc == CONFACK ? "ACK" : (orc == CONFNAK ? "NAK" : "REJ")));
  813.     if (orc == CONFACK &&        /* Good CI */
  814.         rc != CONFACK)        /*  but prior CI wasnt? */
  815.         continue;            /* Don't send this one */
  816.  
  817.     if (orc == CONFNAK) {        /* Nak this CI? */
  818.         if (rc == CONFREJ)        /* Rejecting prior CI? */
  819.         continue;        /* Don't send this one */
  820.         if (rc == CONFACK) {    /* Ack'd all prior CIs? */
  821.         rc = CONFNAK;        /* Not anymore... */
  822.         ucp = inp;        /* Backup */
  823.         }
  824.     }
  825.     if (orc == CONFREJ &&        /* Reject this CI */
  826.         rc != CONFREJ) {        /*  but no prior ones? */
  827.         rc = CONFREJ;
  828.         ucp = inp;            /* Backup */
  829.     }
  830.     if (ucp != cip)            /* Need to move CI? */
  831.         BCOPY(cip, ucp, cilen);    /* Move it */
  832.     INCPTR(cilen, ucp);        /* Update output pointer */
  833.     }
  834.  
  835.     /*
  836.      * XXX If we wanted to send additional NAKs (for unsent CIs), the
  837.      * code would go here.  This must be done with care since it might
  838.      * require a longer packet than we received.
  839.      */
  840.  
  841.     *len = ucp - inp;            /* Compute output length */
  842.     LCPDEBUG((stderr, "ppp: lcp_reqci: returning %s.\n",
  843.           rc == CONFACK ? "CONFACK" :
  844.           rc == CONFNAK ? "CONFNAK" : "CONFREJ"));
  845.     return (rc);            /* Return final code */
  846. }
  847.  
  848.  
  849. /*
  850.  * lcp_up - LCP has come UP.
  851.  *
  852.  * Start UPAP, IPCP, etc.
  853.  */
  854. void lcp_up(f)
  855.     fsm *f;
  856. {
  857.     lcp_options *ho = &lcp_hisoptions[f->unit];
  858.     lcp_options *go = &lcp_gotoptions[f->unit];
  859.     int auth = 0;
  860.  
  861.     if (ho->neg_mru)
  862.     SIFMTU(f->unit, ho->mru);
  863.     if (ho->neg_asyncmap)
  864.     SIFASYNCMAP(f->unit, ho->asyncmap);
  865.     if (ho->neg_pcompression)
  866.     SIFPCOMPRESSION(f->unit);
  867.     if (ho->neg_accompression)
  868.     SIFACCOMPRESSION(f->unit);
  869.     SIFUP(f->unit);        /* Bring the interface up (set IFF_UP) */
  870.     upap_lowerup(f->unit);    /* Enable UPAP */
  871.     ipcp_lowerup(f->unit);    /* Enable IPCP */
  872.     if (go->neg_upap) {
  873.     upap_authpeer(f->unit);
  874.     auth = 1;
  875.     }
  876.     if (ho->neg_upap) {
  877.     upap_authwithpeer(f->unit);
  878.     auth = 1;
  879.     }
  880.     if (!auth)
  881.     ipcp_activeopen(f->unit);
  882. }
  883.  
  884.  
  885. /*
  886.  * lcp_down - LCP has gone DOWN.
  887.  *
  888.  * Alert other protocols.
  889.  */
  890. void lcp_down(f)
  891.     fsm *f;
  892. {
  893.     SIFDOWN(f->unit);
  894.     SIFMTU(f->unit, MTU);
  895.     SIFASYNCMAP(f->unit, 0xffffffff);
  896.     CIFPCOMPRESSION(f->unit);
  897.     CIFACCOMPRESSION(f->unit);
  898.     upap_lowerdown(f->unit);
  899.     ipcp_lowerdown(f->unit);
  900. }
  901.  
  902.  
  903. /*
  904.  * lcp_closed - LCP has CLOSED.
  905.  *
  906.  * Alert other protocols.
  907.  */
  908. void lcp_closed(f)
  909.     fsm *f;
  910. {
  911.     if (lcp_wantoptions[f->unit].restart) {
  912.     if (lcp_wantoptions[f->unit].passive)
  913.         lcp_passiveopen(f->unit);    /* Start protocol in passive mode */
  914.     else
  915.         lcp_activeopen(f->unit);    /* Start protocol in active mode */
  916.     }
  917.     else {
  918.     EXIT(f->unit);
  919.     }
  920. }
  921.