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