home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / SUN / PPP / SUNOS_OL / BKC_PPP.TAR / lcp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-12-31  |  22.3 KB  |  938 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.     u_char *start = p;
  498.     int myopt, myval, xval, plen = len;
  499.     /*
  500.      * Any Rejected CIs must be in exactly the same order that we sent.
  501.      * Check packet length and CI length at each step.
  502.      * If we find any deviations, then this packet is bad.
  503.      */
  504. #define REJCIVOID(opt, neg) \
  505.     myopt = opt; \
  506.     if (neg && \
  507.     len >= 2 && \
  508.     p[1] == 2 && \
  509.     p[0] == opt) { \
  510.     len -= 2; \
  511.     INCPTR(2, p); \
  512.     neg = 0; \
  513.     LCPDEBUG((stderr,"ppp: lcp_rejci rejected void opt %d\n",opt)); \
  514.     }
  515. #define REJCISHORT(opt, neg, val) \
  516.     myopt = opt; myval = val; \
  517.     if (neg && \
  518.     len >= 2 + sizeof (short) && \
  519.     p[1] == 2 + sizeof (short) && \
  520.     p[0] == opt) { \
  521.     len -= 2 + sizeof (short); \
  522.     INCPTR(2, p); \
  523.     GETSHORT(cishort, p); \
  524.     /* Check rejected value. */ \
  525.       xval = cishort; \
  526.     if (cishort != val) \
  527.         goto bad; \
  528.     neg = 0; \
  529.     LCPDEBUG((stderr,"ppp: lcp_rejci rejected short opt %d\n", opt)); \
  530.     }
  531. #define REJCILONG(opt, neg, val) \
  532.     myopt = opt; myval = val; \
  533.     if (neg && \
  534.     len >= 2 + sizeof (long) && \
  535.     p[1] == 2 + sizeof (long) && \
  536.     p[0] == opt) { \
  537.     len -= 2 + sizeof (long); \
  538.     INCPTR(2, p); \
  539.     GETLONG(cilong, p); \
  540.         xval = cilong; \
  541.     /* Check rejected value. */ \
  542.     if (cilong != val) \
  543.         goto bad; \
  544.     neg = 0; \
  545.     LCPDEBUG((stderr,"ppp: lcp_rejci rejected long opt %d\n", opt)); \
  546.     }
  547.  
  548.     REJCISHORT(CI_MRU, go->neg_mru, go->mru)
  549.     REJCILONG(CI_ASYNCMAP, go->neg_asyncmap, go->asyncmap)
  550.     REJCISHORT(CI_AUTHTYPE, go->neg_upap, UPAP)
  551.     REJCISHORT(CI_ENCRYPTTYPE, go->neg_encrypttype, go->encrypttype)
  552.     REJCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber)
  553. #if 0
  554.     REJCI(CI_KEEPALIVE, go->neg_keepalive, go->keepalive)
  555. #endif
  556.     REJCIVOID(CI_PCOMPRESSION, go->neg_pcompression)
  557.     REJCIVOID(CI_ACCOMPRESSION, go->neg_accompression)
  558.  
  559.     /*
  560.      * If there are any remaining CIs, then this packet is bad.
  561.      */
  562.     if (len == 0)
  563.     return;
  564. bad:
  565.     LCPDEBUG((stderr, "ppp: lcp_rejci: received bad Reject!\n"));
  566.     LCPDEBUG((stderr, "ppp: lcp_rejci: plen %d len %d off %d, exp opt %d, found %d, val %d fval %d \n",
  567.     plen, len, p - start, myopt, p[0] &0xff, myval, xval ));
  568.     for(len=0; len < plen; len++) {
  569.     if(!(len % 16))
  570.         LCPDEBUG((stderr,"\nppp: lcp_rejci: "));
  571.     LCPDEBUG((stderr,"%0x ",*start++));
  572.     }
  573.     LCPDEBUG((stderr,"\n"));
  574. }
  575.  
  576.  
  577. /*
  578.  * lcp_reqci - Check the peer's requested CIs and send appropriate response.
  579.  *
  580.  * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
  581.  * appropriately.
  582.  */
  583. u_char lcp_reqci(f, inp, len)
  584.     fsm *f;
  585.     u_char *inp;        /* Requested CIs */
  586.     int *len;            /* Length of requested CIs */
  587. {
  588.     lcp_options *go = &lcp_gotoptions[f->unit];
  589.     lcp_options *ho = &lcp_hisoptions[f->unit];
  590.     lcp_options *ao = &lcp_allowoptions[f->unit];
  591.     u_char *cip;        /* Pointer to Current CI */
  592.     u_char cilen, citype;    /* Parsed len, type, char value */
  593.     u_short cishort;        /* Parsed short value */
  594.     u_long cilong;        /* Parse long value */
  595.     int rc = CONFACK;        /* Final packet return code */
  596.     int orc;            /* Individual option return code */
  597.     u_char *p = inp;        /* Pointer to next char to parse */
  598.     u_char *ucp = inp;        /* Pointer to current output char */
  599.     int l = *len;        /* Length left */
  600.  
  601.     /*
  602.      * Reset all his options.
  603.      */
  604.     ho->neg_mru = 0;
  605.     ho->neg_asyncmap = 0;
  606.     ho->neg_upap = 0;
  607.     ho->neg_encrypttype = 0;
  608.     ho->neg_magicnumber = 0;
  609. #if 0
  610.     ho->neg_keepalive = 0;
  611. #endif
  612.     ho->neg_pcompression = 0;
  613.     ho->neg_accompression = 0;
  614.  
  615.     /*
  616.      * Process all his options.
  617.      */
  618.     while (l) {
  619.     orc = CONFACK;            /* Assume success */
  620.     cip = p;            /* Remember begining of CI */
  621.     if (l < 2 ||            /* Not enough data for CI header or */
  622.         p[1] < 2 ||            /*  CI length too small or */
  623.         p[1] > l) {            /*  CI length too big? */
  624.         LCPDEBUG((stderr, "ppp: lcp_reqci: bad CI length!\n"));
  625.         orc = CONFREJ;        /* Reject bad CI */
  626.         cilen = l;            /* Reject till end of packet */
  627.         l = 0;            /* Don't loop again */
  628.         goto endswitch;
  629.     }
  630.     GETCHAR(citype, p);        /* Parse CI type */
  631.     GETCHAR(cilen, p);        /* Parse CI length */
  632.     l -= cilen;            /* Adjust remaining length */
  633.     cilen -= 2;            /* Adjust cilen to just data */
  634.  
  635.     switch (citype) {        /* Check CI type */
  636.       case CI_MRU:
  637.         LCPDEBUG((stderr, "ppp: lcp_reqci: rcvd MRU"));
  638.         if (!ao->neg_mru ||        /* Allow option? */
  639.         cilen != sizeof (short)) { /* Check CI length */
  640.         INCPTR(cilen, p);     /* Skip rest of CI */
  641.         orc = CONFREJ;        /* Reject CI */
  642.         break;
  643.         }
  644.         GETSHORT(cishort, p);    /* Parse MRU */
  645.         LCPDEBUG((stderr, "(%d)", cishort));
  646.  
  647.         /*
  648.          * He must be able to receive at least our minimum.
  649.          * No need to check a maximum.  If he sends a large number,
  650.          * we'll just ignore it.
  651.          */
  652.         if (cishort < MINMRU) {
  653.         orc = CONFNAK;        /* Nak CI */
  654.         DECPTR(sizeof (short), p); /* Backup */
  655.         PUTSHORT(MINMRU, p);    /* Give him a hint */
  656.         break;
  657.         }
  658.         ho->neg_mru = 1;        /* Remember he sent and MRU */
  659.         ho->mru = cishort;        /* And remember value */
  660.         break;
  661.  
  662.       case CI_ASYNCMAP:
  663.         LCPDEBUG((stderr, "ppp: lcp_reqci: rcvd ASYNCMAP"));
  664.         if (!ao->neg_asyncmap ||
  665.         cilen != sizeof (long)) {
  666.         INCPTR(cilen, p);
  667.         orc = CONFREJ;
  668.         break;
  669.         }
  670.         GETLONG(cilong, p);
  671.         LCPDEBUG((stderr, "(%lx)", cilong));
  672.  
  673.         /* XXX Accept anything he says */
  674. #if 0
  675.         /*
  676.          * Asyncmap must be OR of two maps.
  677.          */
  678.         if ((lcp_wantoptions[f->unit].neg_asyncmap &&
  679.          cilong != (lcp_wantoptions[f->unit].asyncmap | cilong)) ||
  680.         (!lcp_wantoptions[f->unit].neg_asyncmap &&
  681.          cilong != 0xffffffff)) {
  682.         orc = CONFNAK;
  683.         DECPTR(sizeof (long), p);
  684.         PUTLONG(lcp_wantoptions[f->unit].neg_asyncmap ?
  685.             lcp_wantoptions[f->unit].asyncmap | cilong :
  686.             0xffffffff, p);
  687.         break;
  688.         }
  689. #endif
  690.         ho->neg_asyncmap = 1;
  691.         ho->asyncmap = cilong;
  692.         break;
  693.  
  694.       case CI_AUTHTYPE:
  695.         LCPDEBUG((stderr, "ppp: lcp_reqci: rcvd AUTHTYPE"));
  696.         if (!ao->neg_upap ||
  697.         cilen < sizeof (short)) {
  698.         INCPTR(cilen, p);
  699.         orc = CONFREJ;
  700.         break;
  701.         }
  702.         GETSHORT(cishort, p);
  703.         LCPDEBUG((stderr, "(%x)", cishort));
  704.  
  705.         /*
  706.          * Authtype must be UPAP.
  707.          */
  708.         if (cishort != UPAP) {
  709.         DECPTR(sizeof (short), p);
  710.         orc = CONFNAK;
  711.         PUTSHORT(UPAP, p);
  712.         INCPTR(cilen - sizeof (u_short), p);
  713.         break;
  714.         }
  715.         INCPTR(cilen - sizeof (u_short), p);
  716.         ho->neg_upap = 1;
  717.         break;
  718.  
  719. #if 0
  720. /* XXX */
  721.       case CI_ENCRYPTTYPE:
  722.         if (!ao->neg_encrypttype ||
  723.         cilen != sizeof (short)) {
  724.         INCPTR(cilen, p);
  725.         orc = CONFREJ;
  726.         break;
  727.         }
  728.         GETSHORT(cishort, p);
  729.         LCPDEBUG((stderr, "(%d)", cishort));
  730.  
  731.         /*
  732.          * Encrypttype must be XXX.
  733.          */
  734.         if (XXX) {
  735.         DECPTR(sizeof (short), p);
  736.         orc = CONFNAK;
  737.         PUTSHORT(XXX, p);
  738.         break;
  739.         }
  740.         ho->neg_encrypttype = 1;
  741.         ho->encrypttype = cishort;
  742.         break;
  743. #endif
  744.  
  745.       case CI_MAGICNUMBER:
  746.         LCPDEBUG((stderr, "ppp: lcp_reqci: rcvd MAGICNUMBER"));
  747.         if (!ao->neg_magicnumber ||
  748.         cilen != sizeof (long)) {
  749.         INCPTR(cilen, p);
  750.         orc = CONFREJ;
  751.         break;
  752.         }
  753.         GETLONG(cilong, p);
  754.         LCPDEBUG((stderr, "(%lx)", cilong));
  755.  
  756.         /*
  757.          * He must have a different magic number.
  758.          */
  759.         if (go->neg_magicnumber &&
  760.         cilong == go->magicnumber) {
  761.         orc = CONFNAK;
  762.         DECPTR(sizeof (long), p);
  763.         cilong = magic();    /* Don't put magic() inside macro! */
  764.         PUTLONG(cilong, p);
  765.         break;
  766.         }
  767.         ho->neg_magicnumber = 1;
  768.         ho->magicnumber = cilong;
  769.         break;
  770.  
  771. #if 0
  772.       case CI_KEEPALIVE:
  773.         if (!ao->neg_keepalive ||
  774.         cilen != )) {
  775.         INCPTR(cilen, p);
  776.         orc = CONFREJ;
  777.         break;
  778.         }
  779.         GET(ci, p);
  780.         LCPDEBUG((stderr, "(%d)", cishort));
  781.  
  782.         /*
  783.          * He must XXX
  784.          */
  785.         if () {
  786.         orc = CONFNAK;
  787.         DECPTR(sizeof (), p);
  788.         PUT(, p);
  789.         break;
  790.         }
  791.         ho->neg_keepalive = 1;
  792.         ho->keepalive = ;
  793.         break;
  794. #endif
  795.  
  796.       case CI_PCOMPRESSION:
  797.         LCPDEBUG((stderr, "ppp: lcp_reqci: rcvd PCOMPRESSION"));
  798.         if (!ao->neg_pcompression ||
  799.         cilen != 0) {
  800.         INCPTR(cilen, p);
  801.         orc = CONFREJ;
  802.         break;
  803.         }
  804.         ho->neg_pcompression = 1;
  805.         break;
  806.  
  807.       case CI_ACCOMPRESSION:
  808.         LCPDEBUG((stderr, "ppp: lcp_reqci: rcvd ACCOMPRESSION"));
  809.         if (!ao->neg_accompression ||
  810.         cilen != 0) {
  811.         INCPTR(cilen, p);
  812.         orc = CONFREJ;
  813.         break;
  814.         }
  815.         ho->neg_accompression = 1;
  816.         break;
  817.  
  818.       default:
  819.         LCPDEBUG((stderr, "ppp: lcp_reqci: rcvd unknown option %d",
  820.               citype));
  821.         INCPTR(cilen, p);
  822.         orc = CONFREJ;
  823.         break;
  824.     }
  825.     cilen += 2;            /* Adjust cilen whole CI */
  826.  
  827. endswitch:
  828.     LCPDEBUG((stderr, " (%s)\n",
  829.           orc == CONFACK ? "ACK" : (orc == CONFNAK ? "NAK" : "REJ")));
  830.     if (orc == CONFACK &&        /* Good CI */
  831.         rc != CONFACK)        /*  but prior CI wasnt? */
  832.         continue;            /* Don't send this one */
  833.  
  834.     if (orc == CONFNAK) {        /* Nak this CI? */
  835.         if (rc == CONFREJ)        /* Rejecting prior CI? */
  836.         continue;        /* Don't send this one */
  837.         if (rc == CONFACK) {    /* Ack'd all prior CIs? */
  838.         rc = CONFNAK;        /* Not anymore... */
  839.         ucp = inp;        /* Backup */
  840.         }
  841.     }
  842.     if (orc == CONFREJ &&        /* Reject this CI */
  843.         rc != CONFREJ) {        /*  but no prior ones? */
  844.         rc = CONFREJ;
  845.         ucp = inp;            /* Backup */
  846.     }
  847.     if (ucp != cip)            /* Need to move CI? */
  848.         BCOPY(cip, ucp, cilen);    /* Move it */
  849.     INCPTR(cilen, ucp);        /* Update output pointer */
  850.     }
  851.  
  852.     /*
  853.      * XXX If we wanted to send additional NAKs (for unsent CIs), the
  854.      * code would go here.  This must be done with care since it might
  855.      * require a longer packet than we received.
  856.      */
  857.  
  858.     *len = ucp - inp;            /* Compute output length */
  859.     LCPDEBUG((stderr, "ppp: lcp_reqci: returning %s.\n",
  860.           rc == CONFACK ? "CONFACK" :
  861.           rc == CONFNAK ? "CONFNAK" : "CONFREJ"));
  862.     return (rc);            /* Return final code */
  863. }
  864.  
  865.  
  866. /*
  867.  * lcp_up - LCP has come UP.
  868.  *
  869.  * Start UPAP, IPCP, etc.
  870.  */
  871. void lcp_up(f)
  872.     fsm *f;
  873. {
  874.     lcp_options *ho = &lcp_hisoptions[f->unit];
  875.     lcp_options *go = &lcp_gotoptions[f->unit];
  876.     int auth = 0;
  877.  
  878.     if (ho->neg_mru)
  879.     SIFMTU(f->unit, ho->mru);
  880.     if (ho->neg_asyncmap)
  881.     SIFASYNCMAP(f->unit, ho->asyncmap);
  882.     if (ho->neg_pcompression)
  883.     SIFPCOMPRESSION(f->unit);
  884.     if (ho->neg_accompression)
  885.     SIFACCOMPRESSION(f->unit);
  886.     SIFUP(f->unit);        /* Bring the interface up (set IFF_UP) */
  887.     upap_lowerup(f->unit);    /* Enable UPAP */
  888.     ipcp_lowerup(f->unit);    /* Enable IPCP */
  889.     if (go->neg_upap) {
  890.     upap_authpeer(f->unit);
  891.     auth = 1;
  892.     }
  893.     if (ho->neg_upap) {
  894.     upap_authwithpeer(f->unit);
  895.     auth = 1;
  896.     }
  897.     if (!auth)
  898.     ipcp_activeopen(f->unit);
  899. }
  900.  
  901.  
  902. /*
  903.  * lcp_down - LCP has gone DOWN.
  904.  *
  905.  * Alert other protocols.
  906.  */
  907. void lcp_down(f)
  908.     fsm *f;
  909. {
  910.     SIFDOWN(f->unit);
  911.     SIFMTU(f->unit, MTU);
  912.     SIFASYNCMAP(f->unit, 0xffffffff);
  913.     CIFPCOMPRESSION(f->unit);
  914.     CIFACCOMPRESSION(f->unit);
  915.     upap_lowerdown(f->unit);
  916.     ipcp_lowerdown(f->unit);
  917. }
  918.  
  919.  
  920. /*
  921.  * lcp_closed - LCP has CLOSED.
  922.  *
  923.  * Alert other protocols.
  924.  */
  925. void lcp_closed(f)
  926.     fsm *f;
  927. {
  928.     if (lcp_wantoptions[f->unit].restart) {
  929.     if (lcp_wantoptions[f->unit].passive)
  930.         lcp_passiveopen(f->unit);    /* Start protocol in passive mode */
  931.     else
  932.         lcp_activeopen(f->unit);    /* Start protocol in active mode */
  933.     }
  934.     else {
  935.     EXIT(f->unit);
  936.     }
  937. }
  938.