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