home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR3 / KA9Q212.ZIP / PPPLCP.C < prev    next >
C/C++ Source or Header  |  1993-07-16  |  28KB  |  1,132 lines

  1. /*
  2.  *  PPPLCP.C    -- negotiate data link options
  3.  *
  4.  *    This implementation of PPP is declared to be in the public domain.
  5.  *
  6.  *    Jan 91    Bill_Simpson@um.cc.umich.edu
  7.  *        Computer Systems Consulting Services
  8.  *
  9.  *    Acknowledgements and correction history may be found in PPP.C
  10.  */
  11.  
  12. /****************************************************************************
  13. *    $Id: ppplcp.c 1.4 93/07/16 11:49:20 ROOT_DOS Exp $
  14. *    29 May 92    1.2        GT    lcp_stopping (): don't shut down device.        *
  15. *    11 Aug 92    1.3        GT    Make dolcp_open () public.                        *
  16. *    14 Jul 93    1.4        GT    Fix warnings.                                    *
  17. ****************************************************************************/
  18.  
  19. #include <stdio.h>
  20. #include "global.h"
  21. #include "mbuf.h"
  22. #include "iface.h"
  23. #include "socket.h"
  24. #include "ppp.h"
  25. #include "pppfsm.h"
  26. #include "ppplcp.h"
  27. #include "ppppap.h"
  28. #include "cmdparse.h"
  29. #include "devparam.h"
  30. #include "trace.h"
  31. #include "ip.h"
  32.  
  33.  
  34. /* These defaults are defined in the PPP RFCs, and must not be changed */
  35. static struct lcp_value_s lcp_default = {
  36.     FALSE,        /* no need to negotiate defaults */
  37.  
  38.     LCP_MRU_DEFAULT,
  39.     LCP_ACCM_DEFAULT,
  40.     0,        /* no authentication */
  41.     0,        /* no encryption */
  42.     0L,        /* no magic number */
  43.     0L,        /* no reporting period */
  44. };
  45.  
  46. /* for test purposes, accept anything we understand in the NAK */
  47. static int16 lcp_negotiate = LCP_N_MRU | LCP_N_ACCM | LCP_N_AUTHENT
  48.         | LCP_N_PFC | LCP_N_ACFC | LCP_N_MAGIC;
  49.  
  50. static byte_t option_length[] = {
  51.      0,        /* unused */
  52.      4,        /* MRU */
  53.      6,        /* ACCM */
  54.      4,        /* authentication */
  55.      4,        /* encryption */
  56.      6,        /* magic number */
  57.      6,        /* monitor reporting period */
  58.      2,        /* Protocol compression */
  59.      2        /* Address/Control compression */
  60. };
  61.  
  62.  
  63. static int dolcp_local        __ARGS((int argc, char *argv[], void *p));
  64. #if    0
  65. static int dolcp_open        __ARGS((int argc, char *argv[], void *p));
  66. #endif
  67. static int dolcp_remote        __ARGS((int argc, char *argv[], void *p));
  68.  
  69. static int dolcp_accm        __ARGS((int argc, char *argv[], void *p));
  70. static int dolcp_acfc        __ARGS((int argc, char *argv[], void *p));
  71. static int dolcp_auth        __ARGS((int argc, char *argv[], void *p));
  72. static int dolcp_magic        __ARGS((int argc, char *argv[], void *p));
  73. static int dolcp_mru        __ARGS((int argc, char *argv[], void *p));
  74. static int dolcp_pfc        __ARGS((int argc, char *argv[], void *p));
  75. static int dolcp_default    __ARGS((int argc, char *argv[], void *p));
  76.  
  77. static void lcp_option __ARGS((struct mbuf **bpp,
  78.             struct lcp_value_s *value_p,
  79.             byte_t o_type,
  80.             byte_t o_length,
  81.             struct mbuf **copy_bpp ));
  82. static void lcp_makeoptions __ARGS((struct mbuf **bpp,
  83.             struct lcp_value_s *value_p,
  84.             int16 negotiating));
  85. static struct mbuf *lcp_makereq __ARGS((struct fsm_s *fsm_p));
  86.  
  87. static int lcp_check __ARGS((struct mbuf **bpp,
  88.             struct lcp_s *lcp_p,
  89.             struct lcp_side_s *side_p,
  90.             struct option_hdr *option_p,
  91.             int request));
  92.  
  93. static int lcp_request    __ARGS((struct fsm_s *fsm_p,
  94.             struct config_hdr *config,
  95.             struct mbuf *data));
  96. static int lcp_ack    __ARGS((struct fsm_s *fsm_p,
  97.             struct config_hdr *ackcnf,
  98.             struct mbuf *data));
  99. static int lcp_nak    __ARGS((struct fsm_s *fsm_p,
  100.             struct config_hdr *nakcnf,
  101.             struct mbuf *data));
  102. static int lcp_reject    __ARGS((struct fsm_s *fsm_p,
  103.             struct config_hdr *rejcnf,
  104.             struct mbuf *data));
  105.  
  106. static void lcp_reset    __ARGS((struct fsm_s *fsm_p));
  107. static void lcp_starting __ARGS((struct fsm_s *fsm_p));
  108. static void lcp_stopping __ARGS((struct fsm_s *fsm_p));
  109.  
  110. static void lcp_closing __ARGS((struct fsm_s *fsm_p));
  111. static void lcp_opening __ARGS((struct fsm_s *fsm_p));
  112.  
  113. static void lcp_free    __ARGS((struct fsm_s *fsm_p));
  114.  
  115.  
  116. static struct fsm_constant_s lcp_constants = {
  117.     "Lcp",
  118.     PPP_LCP_PROTOCOL,
  119.     0x0FFE,                /* codes 1-11 recognized */
  120.  
  121.     Lcp,
  122.     LCP_REQ_TRY,
  123.     LCP_NAK_TRY,
  124.     LCP_TERM_TRY,
  125.     LCP_TIMEOUT * 1000L,
  126.  
  127.     lcp_free,
  128.  
  129.     lcp_reset,
  130.     lcp_starting,
  131.     lcp_opening,
  132.     lcp_closing,
  133.     lcp_stopping,
  134.  
  135.     lcp_makereq,
  136.     lcp_request,
  137.     lcp_ack,
  138.     lcp_nak,
  139.     lcp_reject
  140. };
  141.  
  142.  
  143. /************************************************************************/
  144.  
  145. /* "ppp <iface> lcp" subcommands */
  146. static struct cmds Lcpcmds[] = {
  147.     { "close",    doppp_close,    0,    0,    NULLCHAR },
  148.     { "listen",    doppp_passive,    0,    0,    NULLCHAR },
  149.     { "local",    dolcp_local,    0,    0,    NULLCHAR },
  150.     { "open",        dolcp_open,    0,    0,    NULLCHAR },
  151.     { "remote",    dolcp_remote,    0,    0,    NULLCHAR },
  152.     { "timeout",    doppp_timeout,    0,    0,    NULLCHAR },
  153.     { "try",        doppp_try,    0,    0,    NULLCHAR },
  154.     { NULLCHAR },
  155. };
  156.  
  157. /* "ppp <iface> lcp [local | remote]" subcommands */
  158. static struct cmds Lcpside_cmds[] = {
  159.     { "accm",        dolcp_accm,    0,    0,    NULLCHAR },
  160.     { "acfc",        dolcp_acfc,    0,    0,    NULLCHAR },
  161.     { "authenticate",    dolcp_auth,    0,    0,    NULLCHAR },
  162.     { "magic",    dolcp_magic,    0,    0,    NULLCHAR },
  163.     { "mru",        dolcp_mru,    0,    0,    NULLCHAR },
  164.     { "pfc",        dolcp_pfc,    0,    0,    NULLCHAR },
  165.     { "default",    dolcp_default,    0,    0,    NULLCHAR },
  166.     { NULLCHAR },
  167. };
  168.  
  169.  
  170. int
  171. doppp_lcp(argc,argv,p)
  172. int argc;
  173. char *argv[];
  174. void *p;
  175. {
  176.     register struct iface *ifp = p;
  177.     register struct ppp_s *ppp_p = ifp->edv;
  178.  
  179.     return subcmd(Lcpcmds, argc, argv, &(ppp_p->fsm[Lcp]));
  180. }
  181.  
  182.  
  183. static int
  184. dolcp_local(argc,argv,p)
  185. int argc;
  186. char *argv[];
  187. void *p;
  188. {
  189.     struct fsm_s *fsm_p = p;
  190.     struct lcp_s *lcp_p = fsm_p->pdv;
  191.     return subcmd(Lcpside_cmds, argc, argv, &(lcp_p->local));
  192. }
  193.  
  194.  
  195. #if    0
  196. static
  197. #endif
  198. int
  199. dolcp_open(argc,argv,p)
  200. int argc;
  201. char *argv[];
  202. void *p;
  203. {
  204.     struct fsm_s *fsm_p = p;
  205.  
  206.     doppp_active( argc, argv, p );
  207.  
  208.     if ( fsm_p->ppp_p->phase >= pppLCP ) {
  209.         fsm_start( fsm_p );
  210.     }
  211.     return 0;
  212. }
  213.  
  214.  
  215. static int
  216. dolcp_remote(argc,argv,p)
  217. int argc;
  218. char *argv[];
  219. void *p;
  220. {
  221.     struct fsm_s *fsm_p = p;
  222.     struct lcp_s *lcp_p = fsm_p->pdv;
  223.     return subcmd(Lcpside_cmds, argc, argv, &(lcp_p->remote));
  224. }
  225.  
  226. /************************************************************************/
  227.  
  228. static int
  229. dolcp_accm(argc,argv,p)
  230. int argc;
  231. char *argv[];
  232. void *p;
  233. {
  234.     struct lcp_side_s *side_p = p;
  235.  
  236.     if (argc < 2) {
  237.         tprintf("0x%08lx\n",side_p->want.accm);
  238.     } else if (stricmp(argv[1],"allow") == 0) {
  239.         return bit16cmd(&(side_p->will_negotiate),LCP_N_ACCM,
  240.             "Allow ACCM", --argc, &argv[1] );
  241.     } else {
  242.         side_p->want.accm = strtoul(argv[1], NULLCHARP, 0);
  243.         if ( side_p->want.accm != LCP_ACCM_DEFAULT )
  244.             side_p->want.negotiate |= LCP_N_ACCM;
  245.         else
  246.             side_p->want.negotiate &= ~LCP_N_ACCM;
  247.     }
  248.     return 0;
  249. }
  250.  
  251.  
  252. static int
  253. dolcp_acfc(argc,argv,p)
  254. int argc;
  255. char *argv[];
  256. void *p;
  257. {
  258.     struct lcp_side_s *side_p = p;
  259.  
  260.     if (stricmp(argv[1],"allow") == 0) {
  261.         return bit16cmd(&(side_p->will_negotiate),LCP_N_ACFC,
  262.             "Allow Address/Control Field Compression", --argc, &argv[1] );
  263.     }
  264.     return bit16cmd( &(side_p->want.negotiate), LCP_N_ACFC,
  265.         "Address/Control Field Compression", argc, argv );
  266. }
  267.  
  268.  
  269. static int
  270. dolcp_auth(argc,argv,p)
  271. int argc;
  272. char *argv[];
  273. void *p;
  274. {
  275.     struct lcp_side_s *side_p = p;
  276.  
  277.     if (argc < 2) {
  278.         if ( side_p->want.negotiate & LCP_N_AUTHENT ) {
  279.             switch ( side_p->want.authentication ) {
  280.             case PPP_PAP_PROTOCOL:
  281.                 tprintf("Pap\n");
  282.                 break;
  283.             default:
  284.                 tprintf("0x%04x\n", side_p->want.authentication);
  285.                 break;
  286.             };
  287.         } else {
  288.             tprintf("None\n");
  289.         }
  290.     } else if (stricmp(argv[1],"allow") == 0) {
  291.         return bit16cmd(&(side_p->will_negotiate),LCP_N_AUTHENT,
  292.             "Allow Authentication", --argc, &argv[1] );
  293.     } else if (stricmp(argv[1],"pap") == 0) {
  294.         side_p->want.negotiate |= LCP_N_AUTHENT;
  295.         side_p->want.authentication = PPP_PAP_PROTOCOL;
  296.     } else if (stricmp(argv[1],"none") == 0) {
  297.         side_p->want.negotiate &= ~LCP_N_AUTHENT;
  298.     } else {
  299.         tprintf("allow pap none\n");
  300.         return 1;
  301.     }
  302.     return 0;
  303. }
  304.  
  305.  
  306. static int
  307. dolcp_magic(argc,argv,p)
  308. int argc;
  309. char *argv[];
  310. void *p;
  311. {
  312.     struct lcp_side_s *side_p = p;
  313.     int result = 0;
  314.  
  315.     if (argc < 2) {
  316.         tprintf("%d\n",side_p->want.magic_number);
  317.     } else if (stricmp(argv[1],"allow") == 0) {
  318.         return bit16cmd(&(side_p->will_negotiate),LCP_N_MAGIC,
  319.             "Allow Magic Number", --argc, &argv[1] );
  320.     } else {
  321.         register int32 x = strtoul(argv[1], NULLCHARP, 0);
  322.  
  323.         if ( !x ) {
  324.             int test;
  325.  
  326.             /* Check for keyword */
  327.             result = setbool( &test, "Magic Number", argc, argv );
  328.  
  329.             if ( test ) {
  330.                 /* Make a non-zero random number */
  331.                 x = Clock << ((Clock & 0xf)+8);
  332.             }
  333.         }
  334.         if ( x ) {
  335.             side_p->want.negotiate |= LCP_N_MAGIC;
  336.         } else {
  337.             side_p->want.negotiate &= ~LCP_N_MAGIC;
  338.         }
  339.         side_p->want.magic_number = x;
  340.     }
  341.     return result;
  342. }
  343.  
  344.  
  345. static int
  346. dolcp_mru(argc,argv,p)
  347. int argc;
  348. char *argv[];
  349. void *p;
  350. {
  351.     struct lcp_side_s *side_p = p;
  352.  
  353.     if (argc < 2) {
  354.         tprintf("%d\n",side_p->want.mru);
  355.     } else if (stricmp(argv[1],"allow") == 0) {
  356.         return bit16cmd(&(side_p->will_negotiate),LCP_N_MRU,
  357.             "Allow MRU", --argc, &argv[1] );
  358.     } else {
  359.         register int x = (int)strtol( argv[1], NULLCHARP, 0 );
  360.  
  361.         if (x < LCP_MRU_LO || x > LCP_MRU_HI) {
  362.             tprintf("MRU %s (%d) out of range %d thru %d\n",
  363.                 argv[1], x, LCP_MRU_LO, LCP_MRU_HI);
  364.             return -1;
  365.         } else if ( x != LCP_MRU_DEFAULT ) {
  366.             side_p->want.negotiate |= LCP_N_MRU;
  367.         } else {
  368.             side_p->want.negotiate &= ~LCP_N_MRU;
  369.         }
  370.         side_p->want.mru = x;
  371.     }
  372.     return 0;
  373. }
  374.  
  375.  
  376. static int
  377. dolcp_pfc(argc,argv,p)
  378. int argc;
  379. char *argv[];
  380. void *p;
  381. {
  382.     struct lcp_side_s *side_p = p;
  383.  
  384.     if (stricmp(argv[1],"allow") == 0) {
  385.         return bit16cmd(&(side_p->will_negotiate),LCP_N_PFC,
  386.             "Allow Protocol Field Compression", --argc, &argv[1] );
  387.     }
  388.     return bit16cmd( &(side_p->want.negotiate), LCP_N_PFC,
  389.         "Protocol Field Compression", argc, argv );
  390. }
  391.  
  392.  
  393. static int
  394. dolcp_default(argc,argv,p)
  395. int argc;
  396. char *argv[];
  397. void *p;
  398. {
  399.     struct lcp_side_s *side_p = p;
  400.  
  401.     ASSIGN( side_p->want, lcp_default );
  402.     return 0;
  403. }
  404.  
  405.  
  406. /************************************************************************/
  407. /*            E V E N T   P R O C E S S I N G            */
  408. /************************************************************************/
  409.  
  410. static void
  411. lcp_option( bpp, value_p, o_type, o_length, copy_bpp )
  412. struct mbuf **bpp;
  413. struct lcp_value_s *value_p;
  414. byte_t o_type;
  415. byte_t o_length;
  416. struct mbuf **copy_bpp;
  417. {
  418.     struct mbuf *bp;
  419.     register char *cp;
  420.     register int toss = o_length - OPTION_HDR_LEN;
  421.  
  422.     if ((bp = alloc_mbuf(o_length)) == NULLBUF) {
  423.         return;
  424.     }
  425.     cp = bp->data;
  426.     *cp++ = o_type;
  427.     *cp++ = o_length;
  428.  
  429.     switch ( o_type ) {
  430.     case LCP_MRU:
  431.         put16(cp, value_p->mru);
  432.         toss -= 2;
  433. #ifdef PPP_DEBUG_OPTIONS
  434. if (PPPtrace & PPP_DEBUG_OPTIONS)
  435.     trace_log(PPPiface, "    making MRU: %d", value_p->mru);
  436. #endif
  437.         break;
  438.  
  439.     case LCP_ACCM:
  440.         put32(cp, value_p->accm);
  441.         toss -= 4;
  442. #ifdef PPP_DEBUG_OPTIONS
  443. if (PPPtrace & PPP_DEBUG_OPTIONS)
  444.     trace_log(PPPiface, "    making ACCM: 0x%08lx", value_p->accm);
  445. #endif
  446.         break;
  447.  
  448.     case LCP_AUTHENT:
  449.         put16(cp, value_p->authentication);
  450.         toss -= 2;
  451. #ifdef PPP_DEBUG_OPTIONS
  452. if (PPPtrace & PPP_DEBUG_OPTIONS)
  453.     trace_log(PPPiface, "    making Auth Protocol: 0x%04x",
  454.         value_p->authentication);
  455. #endif
  456.         break;
  457.  
  458.     case LCP_MAGIC:
  459.         put32(cp, value_p->magic_number);
  460.         toss -= 4;
  461. #ifdef PPP_DEBUG_OPTIONS
  462. if (PPPtrace & PPP_DEBUG_OPTIONS)
  463.     trace_log(PPPiface, "    making Magic Number: 0x%08lx",
  464.         value_p->magic_number);
  465. #endif
  466.         break;
  467.  
  468.     case LCP_PFC:
  469. #ifdef PPP_DEBUG_OPTIONS
  470. if (PPPtrace & PPP_DEBUG_OPTIONS)
  471.     trace_log(PPPiface, "    making Protocol compression");
  472. #endif
  473.         break;
  474.  
  475.     case LCP_ACFC:
  476. #ifdef PPP_DEBUG_OPTIONS
  477. if (PPPtrace & PPP_DEBUG_OPTIONS)
  478.     trace_log(PPPiface, "    making Addr/Ctl compression");
  479. #endif
  480.         break;
  481.  
  482.     case LCP_ENCRYPT:        /* not implemented */
  483.     case LCP_QUALITY:        /* not implemented */
  484.     default:
  485. #ifdef PPP_DEBUG_OPTIONS
  486. if (PPPtrace & PPP_DEBUG_OPTIONS)
  487.     trace_log(PPPiface, "    making unimplemented type %d", o_type);
  488. #endif
  489.         break;
  490.     };
  491.  
  492.     while ( toss-- > 0 ) {
  493.         *cp++ = pullchar(copy_bpp);
  494.     }
  495.     bp->cnt += o_length;
  496.     append(bpp, bp);
  497. }
  498.  
  499.  
  500. /************************************************************************/
  501. /* Build a list of options */
  502. static void
  503. lcp_makeoptions(bpp, value_p, negotiating)
  504. struct mbuf **bpp;
  505. struct lcp_value_s *value_p;
  506. int16 negotiating;
  507. {
  508.     register int o_type;
  509.  
  510.     PPP_DEBUG_ROUTINES("lcp_makeoptions()");
  511.  
  512.     for ( o_type = 1; o_type <= LCP_OPTION_LIMIT; o_type++ ) {
  513.         if (negotiating & (1 << o_type)) {
  514.             lcp_option( bpp, value_p,
  515.                 o_type, option_length[ o_type ], NULLBUFP);
  516.         }
  517.     }
  518. }
  519.  
  520.  
  521. /************************************************************************/
  522. /* Build a request to send to remote host */
  523. static struct mbuf *
  524. lcp_makereq(fsm_p)
  525. struct fsm_s *fsm_p;
  526. {
  527.     struct lcp_s *lcp_p = fsm_p->pdv;
  528.     struct mbuf *req_bp = NULLBUF;
  529.  
  530.     PPP_DEBUG_ROUTINES("lcp_makereq()");
  531.  
  532.     lcp_makeoptions( &req_bp, &(lcp_p->local.work),
  533.                 lcp_p->local.work.negotiate );
  534.     return(req_bp);
  535. }
  536.  
  537.  
  538. /************************************************************************/
  539. /* Check the options, updating the working values.
  540.  * Returns -1 if ran out of data, ACK/NAK/REJ as appropriate.
  541.  */
  542. static int
  543. lcp_check( bpp, lcp_p, side_p, option_p, request )
  544. struct mbuf **bpp;
  545. struct lcp_s *lcp_p;
  546. struct lcp_side_s *side_p;
  547. struct option_hdr *option_p;
  548. int request;
  549. {
  550.     int toss = option_p->len - OPTION_HDR_LEN;
  551.     int option_result = CONFIG_ACK;        /* Assume good values */
  552.  
  553.     switch(option_p->type) {
  554.     case LCP_MRU:
  555.         side_p->work.mru = pull16(bpp);
  556.         toss -= 2;
  557. #ifdef PPP_DEBUG_OPTIONS
  558. if (PPPtrace & PPP_DEBUG_OPTIONS)
  559.     trace_log(PPPiface, "    checking MRU: %d", side_p->work.mru);
  560. #endif
  561.         /* Check if new value is appropriate */
  562.         if (side_p->work.mru < LCP_MRU_LO) {
  563.             side_p->work.mru = LCP_MRU_LO;
  564.             option_result = CONFIG_NAK;
  565.         } else if (side_p->work.mru > LCP_MRU_HI) {
  566.             side_p->work.mru = LCP_MRU_HI;
  567.             option_result = CONFIG_NAK;
  568.         }
  569.         if ( request && (side_p->want.negotiate & LCP_N_MRU)
  570.           && side_p->work.mru > side_p->want.mru ) {
  571.             side_p->work.mru = side_p->want.mru;
  572.             option_result = side_p->want.mru;
  573.         }
  574.         break;
  575.  
  576.     case LCP_ACCM:
  577.         side_p->work.accm = pull32(bpp);
  578.         toss -= 4;
  579. #ifdef PPP_DEBUG_OPTIONS
  580. if (PPPtrace & PPP_DEBUG_OPTIONS)
  581.     trace_log(PPPiface, "    checking ACCM: 0x%08lx", side_p->work.accm);
  582. #endif
  583.         /* Remote host may ask to escape more control  */
  584.         /* characters than we require, but must escape */
  585.         /* at least the control chars that we require. */
  586.         if ( (!request || (side_p->want.negotiate & LCP_N_ACCM))
  587.           && side_p->work.accm !=
  588.                (side_p->work.accm | side_p->want.accm) ) {
  589.             side_p->work.accm |= side_p->want.accm;
  590.             option_result = CONFIG_NAK;
  591.         }
  592.         break;
  593.  
  594.     case LCP_AUTHENT:
  595.         side_p->work.authentication = pull16(bpp);
  596.         toss -= 2;
  597. #ifdef PPP_DEBUG_OPTIONS
  598. if (PPPtrace & PPP_DEBUG_OPTIONS)
  599.     trace_log(PPPiface, "    checking Auth Protocol: 0x%04x",
  600.         side_p->work.authentication);
  601. #endif
  602.         /* Check if new value is appropriate */
  603.         switch ( side_p->work.authentication ) {
  604.         case PPP_PAP_PROTOCOL:
  605.             /* Yes */
  606.             break;
  607.         default:
  608.             side_p->work.authentication = PPP_PAP_PROTOCOL;
  609.             option_result = CONFIG_NAK;
  610.             break;
  611.         };
  612.         break;
  613.  
  614.     case LCP_MAGIC:
  615.         side_p->work.magic_number = pull32(bpp);
  616.         toss -= 4;
  617. #ifdef PPP_DEBUG_OPTIONS
  618. if (PPPtrace & PPP_DEBUG_OPTIONS)
  619.     trace_log(PPPiface, "    checking Magic Number: 0x%08lx",
  620.         side_p->work.magic_number);
  621. #endif
  622.  
  623.         /* Ensure that magic numbers are different */
  624.         if (side_p->work.magic_number == 0L
  625.          || lcp_p->remote.work.magic_number == lcp_p->local.work.magic_number) {
  626.             side_p->work.magic_number += Clock;
  627.             option_result = CONFIG_NAK;
  628.         }
  629.         break;
  630.  
  631.     case LCP_PFC:
  632. #ifdef PPP_DEBUG_OPTIONS
  633. if (PPPtrace & PPP_DEBUG_OPTIONS)
  634.     trace_log(PPPiface, "    checking Protocol compression");
  635. #endif
  636.         break;
  637.  
  638.     case LCP_ACFC:
  639. #ifdef PPP_DEBUG_OPTIONS
  640. if (PPPtrace & PPP_DEBUG_OPTIONS)
  641.     trace_log(PPPiface, "    checking Addr/Ctl compression");
  642. #endif
  643.         break;
  644.  
  645.     case LCP_ENCRYPT:        /* not implemented */
  646.     case LCP_QUALITY:        /* not implemented */
  647.     default:
  648.         option_result = CONFIG_REJ;
  649.         break;
  650.     };
  651.  
  652.     if (option_p->type > LCP_OPTION_LIMIT
  653.      || !(side_p->will_negotiate & (1 << option_p->type))) {
  654.         option_result = CONFIG_REJ;
  655.     }
  656.  
  657.     if ( toss < 0 )
  658.         return -1;
  659.  
  660.     if ( !request  &&  toss > 0 ) {
  661.         /* toss extra bytes in option */
  662.         while( toss-- > 0 ) {
  663.             if ( pullchar(bpp) == -1 )
  664.                 return -1;
  665.         }
  666.     }
  667.  
  668.     return (option_result);
  669. }
  670.  
  671.  
  672. /************************************************************************/
  673. /* Check Link Control options requested by the remote host */
  674. static int
  675. lcp_request(fsm_p, config, data)
  676. struct fsm_s *fsm_p;
  677. struct config_hdr *config;
  678. struct mbuf *data;
  679. {
  680.     struct lcp_s *lcp_p = fsm_p->pdv;
  681.     int32 signed_length = config->len;
  682.     struct mbuf *reply_bp = NULLBUF;    /* reply packet */
  683.     int reply_result = CONFIG_ACK;        /* reply to request */
  684.     int16 desired;                /* desired to negotiate */
  685.     struct option_hdr option;        /* option header storage */
  686.     int option_result;            /* option reply */
  687.  
  688.     PPP_DEBUG_ROUTINES("lcp_request()");
  689.     lcp_p->remote.work.negotiate = FALSE;    /* clear flags */
  690.  
  691.     /* Process options requested by remote host */
  692.     while (signed_length > 0  &&  ntohopt(&option, &data) != -1) {
  693.         if ((signed_length -= option.len) < 0) {
  694.             PPP_DEBUG_CHECKS("LCP REQ: bad header length");
  695.             free_p(data);
  696.             free_p(reply_bp);
  697.             return -1;
  698.         }
  699.  
  700.         if ( ( option_result = lcp_check( &data, lcp_p,
  701.                 &(lcp_p->remote), &option, TRUE ) ) == -1 ) {
  702.             PPP_DEBUG_CHECKS("LCP REQ: ran out of data");
  703.             free_p(data);
  704.             free_p(reply_bp);
  705.             return -1;
  706.         }
  707.  
  708. #ifdef PPP_DEBUG_OPTIONS
  709. if (PPPtrace & PPP_DEBUG_OPTIONS) {
  710.     trace_log(PPPiface, "LCP REQ: result %s, option %d, length %d",
  711.         fsmCodes[option_result],
  712.         option.type,
  713.         option.len);
  714. }
  715. #endif
  716.         if ( option_result < reply_result ) {
  717.             continue;
  718.         } else if ( option_result > reply_result ) {
  719.             /* Discard current list of replies */
  720.             free_p(reply_bp);
  721.             reply_bp = NULLBUF;
  722.             reply_result = option_result;
  723.         }
  724.  
  725.         /* remember that we processed option */
  726.         if ( option_result != CONFIG_REJ
  727.           && option.type <= LCP_OPTION_LIMIT ) {
  728.             lcp_p->remote.work.negotiate |= (1 << option.type);
  729.         }
  730.  
  731.         /* Add option response to the return list */
  732.         lcp_option( &reply_bp, &(lcp_p->remote.work),
  733.             option.type, option.len, &data );
  734.     }
  735.  
  736.     /* Now check for any missing options which are desired */
  737.     if ( fsm_p->retry_nak > 0
  738.      &&  (desired = lcp_p->remote.want.negotiate
  739.                & ~lcp_p->remote.work.negotiate) != 0 ) {
  740.         switch ( reply_result ) {
  741.         case CONFIG_ACK:
  742.             free_p(reply_bp);
  743.             reply_bp = NULLBUF;
  744.             reply_result = CONFIG_NAK;
  745.             /* fallthru */
  746.         case CONFIG_NAK:
  747.             lcp_makeoptions( &reply_bp, &(lcp_p->remote.want),
  748.                 desired );
  749.             fsm_p->retry_nak--;
  750.             break;
  751.         case CONFIG_REJ:
  752.             /* do nothing */
  753.             break;
  754.         };
  755.     } else if ( reply_result == CONFIG_NAK ) {
  756.         /* if too many NAKs, reject instead */
  757.         if ( fsm_p->retry_nak > 0 )
  758.             fsm_p->retry_nak--;
  759.         else
  760.             reply_result = CONFIG_REJ;
  761.     }
  762.  
  763.     /* Send ACK/NAK/REJ to remote host */
  764.     fsm_send(fsm_p, reply_result, config->id, reply_bp);
  765.     free_p(data);
  766.     return (reply_result != CONFIG_ACK);
  767. }
  768.  
  769.  
  770. /************************************************************************/
  771. /* Process configuration ACK sent by remote host */
  772. static int
  773. lcp_ack(fsm_p, config, data)
  774. struct fsm_s *fsm_p;
  775. struct config_hdr *config;
  776. struct mbuf *data;
  777. {
  778.     struct mbuf *req_bp;
  779.     int error = FALSE;
  780.  
  781.     PPP_DEBUG_ROUTINES("lcp_ack()");
  782.  
  783.     /* ID field must match last request we sent */
  784.     if (config->id != fsm_p->lastid) {
  785.         PPP_DEBUG_CHECKS("LCP ACK: wrong ID");
  786.         free_p(data);
  787.         return -1;
  788.     }
  789.  
  790.     /* Get a copy of last request we sent */
  791.     req_bp = lcp_makereq(fsm_p);
  792.  
  793.     /* Overall buffer length should match */
  794.     if (config->len != len_p(req_bp)) {
  795.         PPP_DEBUG_CHECKS("LCP ACK: buffer length mismatch");
  796.         error = TRUE;
  797.     } else {
  798.         register int req_char;
  799.         register int ack_char;
  800.  
  801.         /* Each byte should match */
  802.         while ((req_char = pullchar(&req_bp)) != -1) {
  803.             if ((ack_char = pullchar(&data)) == -1
  804.              || ack_char != req_char ) {
  805.                 PPP_DEBUG_CHECKS("LCP ACK: data mismatch");
  806.                 /*trace_log(PPPiface, "req=%02X, ack=%02X", req_char, ack_char);*/
  807.                 error = TRUE;
  808.                 break;
  809.             }
  810.         }
  811.     }
  812.     free_p(req_bp);
  813.     free_p(data);
  814.  
  815.     if (error) {
  816.         return -1;
  817.     }
  818.  
  819.     PPP_DEBUG_CHECKS("LCP ACK: valid");
  820.     return 0;
  821. }
  822.  
  823.  
  824. /************************************************************************/
  825. /* Process configuration NAK sent by remote host */
  826. static int
  827. lcp_nak(fsm_p, config, data)
  828. struct fsm_s *fsm_p;
  829. struct config_hdr *config;
  830. struct mbuf *data;
  831. {
  832.     struct lcp_s *lcp_p = fsm_p->pdv;
  833.     struct lcp_side_s *local_p = &(lcp_p->local);
  834.     int32 signed_length = config->len;
  835.     struct option_hdr option;
  836.     int last_option = 0;
  837.     int result;
  838.  
  839.     PPP_DEBUG_ROUTINES("lcp_nak()");
  840.  
  841.     /* ID field must match last request we sent */
  842.     if (config->id != fsm_p->lastid) {
  843.         PPP_DEBUG_CHECKS("LCP NAK: wrong ID");
  844.         free_p(data);
  845.         return -1;
  846.     }
  847.  
  848.     /* First, process in order.  Then, process extra "important" options */
  849.     while (signed_length > 0  &&  ntohopt(&option, &data) != -1) {
  850.         if ((signed_length -= option.len) < 0) {
  851.             PPP_DEBUG_CHECKS("LCP NAK: bad header length");
  852.             free_p(data);
  853.             return -1;
  854.         }
  855.         if ( option.type > LCP_OPTION_LIMIT ) {
  856.             PPP_DEBUG_CHECKS("LCP NAK: option out of range");
  857.         } else if ( option.type < last_option
  858.           || !(local_p->work.negotiate & (1 << option.type)) ) {
  859.             if (local_p->work.negotiate & (1 << option.type)) {
  860.                 PPP_DEBUG_CHECKS("LCP NAK: option out of order");
  861.                 free_p(data);
  862.                 return -1;        /* was requested */
  863.             }
  864.             local_p->work.negotiate |= (1 << option.type);
  865.             last_option = LCP_OPTION_LIMIT + 1;
  866.         } else {
  867.             last_option = option.type;
  868.         }
  869.         if ( ( result = lcp_check( &data, lcp_p,
  870.                 local_p, &option, FALSE ) ) == -1 ) {
  871.             PPP_DEBUG_CHECKS("LCP NAK: ran out of data");
  872.             free_p(data);
  873.             return -1;
  874.         }
  875.         /* update the negotiation status */
  876.         if ( result == CONFIG_REJ
  877.           && option.type <= LCP_OPTION_LIMIT ) {
  878.             local_p->work.negotiate &= ~(1 << option.type);
  879.         }
  880.     }
  881.     PPP_DEBUG_CHECKS("LCP NAK: valid");
  882.     free_p(data);
  883.     return 0;
  884. }
  885.  
  886.  
  887. /************************************************************************/
  888. /* Process configuration reject sent by remote host */
  889. static int
  890. lcp_reject(fsm_p, config, data)
  891. struct fsm_s *fsm_p;
  892. struct config_hdr *config;
  893. struct mbuf *data;
  894. {
  895.     struct lcp_s *lcp_p = fsm_p->pdv;
  896.     struct lcp_side_s *local_p = &(lcp_p->local);
  897.     int32 signed_length = config->len;
  898.     struct option_hdr option;
  899.     int last_option = 0;
  900.  
  901.     PPP_DEBUG_ROUTINES("lcp_reject()");
  902.  
  903.     /* ID field must match last request we sent */
  904.     if (config->id != fsm_p->lastid) {
  905.         PPP_DEBUG_CHECKS("LCP REJ: wrong ID");
  906.         free_p(data);
  907.         return -1;
  908.     }
  909.  
  910.     /* Process in order, checking for errors */
  911.     while (signed_length > 0  &&  ntohopt(&option, &data) != -1) {
  912.         register int k;
  913.  
  914.         if ((signed_length -= option.len) < 0) {
  915.             PPP_DEBUG_CHECKS("LCP REJ: bad header length");
  916.             free_p(data);
  917.             return -1;
  918.         }
  919.         if ( option.type > LCP_OPTION_LIMIT ) {
  920.             PPP_DEBUG_CHECKS("LCP REJ: option out of range");
  921.         } else if ( option.type < last_option
  922.          || !(local_p->work.negotiate & (1 << option.type))) {
  923.             PPP_DEBUG_CHECKS("LCP REJ: option out of order");
  924.             free_p(data);
  925.             return -1;
  926.         }
  927.         for ( k = option.len - OPTION_HDR_LEN; k-- > 0; ) {
  928.             if ( pullchar(&data) == -1 ) {
  929.                 PPP_DEBUG_CHECKS("LCP REJ: ran out of data");
  930.                 free_p(data);
  931.                 return -1;
  932.             }
  933.         }
  934.         last_option = option.type;
  935.  
  936.         if ( option.type <= LCP_OPTION_LIMIT ) {
  937.             local_p->work.negotiate &= ~(1 << option.type);
  938.         }
  939.     }
  940.     PPP_DEBUG_CHECKS("LCP REJ: valid");
  941.     free_p(data);
  942.     return 0;
  943. }
  944.  
  945.  
  946. /************************************************************************/
  947. /*            I N I T I A L I Z A T I O N            */
  948. /************************************************************************/
  949.  
  950. /* Check for PPP Network-Layer Protocol Phase */
  951. void
  952. ppp_ready(ppp_p)
  953. struct ppp_s *ppp_p;
  954. {
  955.     if ( !(ppp_p->flags & (PPP_AP_LOCAL | PPP_AP_REMOTE)) ) {
  956.         /* no pending authentication */
  957.         ppp_p->phase = pppREADY;
  958.  
  959.         ppp_p->upsince = secclock();
  960.         fsm_start( &(ppp_p->fsm[IPcp]) );
  961.     }
  962. }
  963.  
  964.  
  965. /****************************************************************************/
  966. /* Reset configuration options before request */
  967. static void
  968. lcp_reset(fsm_p)
  969. struct fsm_s *fsm_p;
  970. {
  971.     struct lcp_s *lcp_p =     fsm_p->pdv;
  972.  
  973.     PPP_DEBUG_ROUTINES("lcp_reset()");
  974.  
  975.     if ( lcp_p->local.want.negotiate & LCP_N_MAGIC ) {
  976.         lcp_p->local.want.magic_number += Clock;
  977.     }
  978.  
  979.     ASSIGN( lcp_p->local.work, lcp_p->local.want );
  980.     lcp_p->local.will_negotiate |= lcp_p->local.want.negotiate;
  981.  
  982.     lcp_p->remote.work.negotiate = FALSE;
  983.     lcp_p->remote.will_negotiate |= lcp_p->remote.want.negotiate;
  984. }
  985.  
  986.  
  987. /************************************************************************/
  988. /* Prepare to begin configuration exchange */
  989. static void
  990. lcp_starting(fsm_p)
  991. struct fsm_s *fsm_p;
  992. {
  993.     PPP_DEBUG_ROUTINES("lcp_starting()");
  994.  
  995.     fsm_p->ppp_p->phase = pppLCP;
  996. }
  997.  
  998.  
  999. /************************************************************************/
  1000. /* After termination */
  1001. static void
  1002. lcp_stopping(fsm_p)
  1003. struct fsm_s *fsm_p;
  1004. {
  1005. #if    0
  1006.     struct iface *ifp = fsm_p->ppp_p->iface;
  1007. #endif
  1008.  
  1009.     PPP_DEBUG_ROUTINES("lcp_stopping()");
  1010.  
  1011. #if    0
  1012.     /* Tell the dialer to shut down */
  1013.     if ( ifp->supv != NULLPROC )
  1014.         alert( ifp->supv, EABORT );
  1015.  
  1016.     /* Now, tell the device to go down.
  1017.      * In turn, it should tell our IO status
  1018.      * when it has gone down.
  1019.      */
  1020.  
  1021.     ifp->ioctl(ifp,PARAM_DOWN,TRUE,0L);
  1022. #endif
  1023.  
  1024. }
  1025.  
  1026.  
  1027. /************************************************************************/
  1028. /* Close higher levels in preparation for link shutdown */
  1029. static void
  1030. lcp_closing(fsm_p)
  1031. struct fsm_s *fsm_p;
  1032. {
  1033.     struct ppp_s *ppp_p = fsm_p->ppp_p;
  1034.  
  1035.     ppp_p->phase = pppTERMINATE;
  1036.  
  1037.     fsm_down( &(ppp_p->fsm[IPcp]) );
  1038.     pap_down( &(ppp_p->fsm[Pap]) );
  1039. }
  1040.  
  1041.  
  1042. #ifdef TURBOC_SWITCH_BUG
  1043. #pragma option -G-
  1044. #endif
  1045.  
  1046. /************************************************************************/
  1047. /* configuration negotiation complete */
  1048. static void
  1049. lcp_opening(fsm_p)
  1050. struct fsm_s *fsm_p;
  1051. {
  1052.     struct lcp_s *lcp_p =     fsm_p->pdv;
  1053.     struct iface *ifp =     fsm_p->ppp_p->iface;
  1054.  
  1055.     if (ifp->mtu != lcp_p->remote.work.mru) {
  1056.         /* Set new Max Transmission Unit for outgoing packets */
  1057.         ifp->mtu = lcp_p->remote.work.mru;
  1058.         if (PPPtrace > 1)
  1059.             trace_log(PPPiface,"    Set new MTU for outgoing packets: %d",
  1060.                 ifp->mtu);
  1061.     }
  1062.  
  1063.     /* check for authentication */
  1064.     fsm_p->ppp_p->phase = pppAP;
  1065.     fsm_p->ppp_p->flags &= ~(PPP_AP_LOCAL | PPP_AP_REMOTE);
  1066.     free(fsm_p->ppp_p->peername);
  1067.     fsm_p->ppp_p->peername = NULLCHAR;
  1068.  
  1069.     if (lcp_p->local.work.negotiate & LCP_N_AUTHENT) {
  1070.         switch (lcp_p->local.work.authentication) {
  1071.         case PPP_PAP_PROTOCOL:
  1072.             pap_local(fsm_p->ppp_p);
  1073.             break;
  1074.         };
  1075.     }
  1076.     if (lcp_p->remote.work.negotiate & LCP_N_AUTHENT) {
  1077.         switch (lcp_p->remote.work.authentication) {
  1078.         case PPP_PAP_PROTOCOL:
  1079.             pap_remote(fsm_p->ppp_p);
  1080.             break;
  1081.         };
  1082.     }
  1083.  
  1084.     /* re-check for authentication */
  1085.     ppp_ready(fsm_p->ppp_p);
  1086. }
  1087.  
  1088. #ifdef TURBOC_SWITCH_BUG
  1089. #pragma option -G
  1090. #endif
  1091.  
  1092.  
  1093. /************************************************************************/
  1094. static void
  1095. lcp_free(fsm_p)
  1096. struct fsm_s *fsm_p;
  1097. {
  1098.     /* nothing to do */
  1099. }
  1100.  
  1101.  
  1102. /* Initialize configuration structure */
  1103. void
  1104. lcp_init(ppp_p)
  1105. struct ppp_s *ppp_p;
  1106. {
  1107.     struct fsm_s *fsm_p = &(ppp_p->fsm[Lcp]);
  1108.     struct lcp_s *lcp_p;
  1109.  
  1110.     PPPtrace = ppp_p->trace;
  1111.     PPPiface = ppp_p->iface;
  1112.  
  1113.     PPP_DEBUG_ROUTINES("lcp_init()");
  1114.  
  1115.     fsm_p->ppp_p = ppp_p;
  1116.     fsm_p->pdc = &lcp_constants;
  1117.     fsm_p->pdv =
  1118.     lcp_p = callocw(1,sizeof(struct lcp_s));
  1119.  
  1120.     /* Set option parameters to first request defaults */
  1121.     ASSIGN( lcp_p->local.want, lcp_default );
  1122.     lcp_p->local.will_negotiate = lcp_negotiate;
  1123.  
  1124.     ASSIGN( lcp_p->remote.want, lcp_default );
  1125.     ASSIGN( lcp_p->remote.work, lcp_default );
  1126.     lcp_p->remote.will_negotiate = lcp_negotiate;
  1127.  
  1128.     fsm_init(fsm_p);
  1129. }
  1130.  
  1131.  
  1132.