home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 3 / hamradioversion3.0examsandprograms1992.iso / packet / n17jsrc / ppppap.c < prev    next >
C/C++ Source or Header  |  1991-06-24  |  17KB  |  747 lines

  1. /*
  2.  *  PPPPAP.C    -- Password Authentication Protocol for PPP
  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 "proc.h"
  16. #include "iface.h"
  17. #include "session.h"
  18. #include "socket.h"
  19. #include "ppp.h"
  20. #include "pppfsm.h"
  21. #include "ppppap.h"
  22. #include "cmdparse.h"
  23. #include "files.h"
  24.  
  25. static int dopap_user        __ARGS((int argc, char *argv[], void *p));
  26.  
  27. static void pap_input __ARGS((int mustask, void *v1, void *v2));
  28. static void pap_pwdlookup __ARGS((struct pap_s *pap_p));
  29. static void pap_getpassword __ARGS((struct fsm_s *fsm_p, int mustask));
  30.  
  31. static struct mbuf *pap_makereq __ARGS((struct fsm_s *fsm_p));
  32.  
  33. static int pap_verify __ARGS((char *username, char *password));
  34. static void pap_shutdown __ARGS((struct fsm_s *fsm_p));
  35. static void pap_opening __ARGS((struct fsm_s *fsm_p, int flag));
  36.  
  37. static int pap_request    __ARGS((struct fsm_s *fsm_p,
  38.             struct config_hdr *hdr,
  39.             struct mbuf *data));
  40. static int pap_check    __ARGS((struct fsm_s *fsm_p,
  41.             struct config_hdr *hdr,
  42.             struct mbuf *data));
  43. static void pap_timeout    __ARGS((void *vp));
  44.  
  45. static void pap_reset    __ARGS((struct fsm_s *fsm_p));
  46. static void pap_free    __ARGS((struct fsm_s *fsm_p));
  47. static void pap_init    __ARGS((struct ppp_s *ppp_p));
  48.  
  49.  
  50. static struct fsm_constant_s pap_constants = {
  51.     "Pap",
  52.     PPP_PAP_PROTOCOL,
  53.     0x000E,                /* codes 1-3 recognized */
  54.  
  55.     Pap,
  56.     PAP_REQ_TRY,
  57.     PAP_FAIL_MAX,
  58.     0,
  59.     PAP_TIMEOUT * 1000L,
  60.  
  61.     pap_free,
  62.  
  63.     fsm_no_action,        /* pap_reset, */
  64.     fsm_no_action,        /* pap_starting, */
  65.     fsm_no_action,        /* pap_opening, */
  66.     fsm_no_action,        /* pap_closing, */
  67.     fsm_no_action,        /* pap_stopping, */
  68.  
  69.     pap_makereq,
  70.     fsm_no_check,        /* pap_request, */
  71.     fsm_no_check,        /* pap_ack, */
  72.     fsm_no_check,        /* pap_nak, */
  73.     fsm_no_check,        /* pap_reject */
  74. };
  75.  
  76.  
  77. /****************************************************************************/
  78.  
  79. /* "ppp <iface> pap" subcommands */
  80. static struct cmds Papcmds[] = {
  81.     "timeout",    doppp_timeout,    0,    0,    NULLCHAR,
  82.     "try",        doppp_try,    0,    0,    NULLCHAR,
  83.     "user",        dopap_user,    0,    0,    NULLCHAR,
  84.     NULLCHAR,
  85. };
  86.  
  87.  
  88. int
  89. doppp_pap(argc,argv,p)
  90. int argc;
  91. char *argv[];
  92. void *p;
  93. {
  94.     register struct iface *ifp = p;
  95.     register struct ppp_s *ppp_p = ifp->extension;
  96.  
  97.     pap_init(ppp_p);
  98.     return subcmd(Papcmds, argc, argv, &(ppp_p->fsm[Pap]));
  99. }
  100.  
  101.  
  102. /* Set user/password */
  103. int
  104. dopap_user(argc,argv,p)
  105. int argc;
  106. char *argv[];
  107. void *p;
  108. {
  109.     register struct fsm_s *fsm_p = p;
  110.     register struct pap_s *pap_p = fsm_p->pdv;
  111.  
  112.     if (argc < 2) {
  113.         tprintf("%s\n",
  114.             (pap_p->username == NULLCHAR) ? "None" : pap_p->username);
  115.         return 0;
  116.     }
  117.     free(pap_p->username);
  118.     pap_p->username = NULLCHAR;
  119.     free(pap_p->password);
  120.     pap_p->password = NULLCHAR;
  121.  
  122.     if (stricmp(argv[1],"none") != 0) {
  123.         pap_p->username = strdup(argv[1]);
  124.         if (argc > 2) {
  125.             pap_p->password = strdup(argv[2]);
  126.         } else {
  127.             pap_getpassword( fsm_p, FALSE);
  128.         }
  129.     }
  130.     return 0;
  131. }
  132.  
  133.  
  134. /****************************************************************************/
  135. /* Bring up a session on the console for for the username/password.
  136.  * Return a NULLCHAR in either username or password if aborted.
  137.  */
  138. static void
  139. pap_input(mustask, v1, v2)
  140. int mustask;
  141. void *v1;
  142. void *v2;
  143. {
  144.     struct iface *iface = v1;
  145.     struct pap_s *pap_p = v2;
  146.     char buf[21];
  147.     struct session *sp;
  148.  
  149.     /* Allocate a session control block */
  150.     if((sp = newsession("PPP/PAP Auth",PPPPASS,0)) == NULLSESSION){
  151.         tprintf("Too many sessions\n");
  152.         return;
  153.     }
  154.  
  155.     if (mustask)
  156.         tprintf("\n%s: PPP/PAP Password Authentication Failed;"
  157.             " enter ID and password again\n",
  158.             iface->name);
  159.     else
  160.         tprintf("\n%s: PPP/PAP Password Authentication Required\n",
  161.             iface->name);
  162.     tprintf("%s: PPP/PAP  user: ",iface->name);
  163.     usflush(sp->output);
  164.  
  165.     /* Only ask for the user if it is unknown */
  166.     if (pap_p->username == NULLCHAR) {
  167.         if (recvline(sp->input,buf,20) < 0) {
  168.             pap_p->username = NULLCHAR;
  169.         } else {
  170.             rip(buf);
  171.             pap_p->username = strdup(buf);
  172.         }
  173.     } else {
  174.         tprintf("%s\n",pap_p->username);
  175.     }
  176.  
  177.     if (pap_p->username != NULLCHAR) {
  178.         /* turn off echo */
  179.         sp->ttystate.echo = 0;
  180.         tprintf("%s: PPP/PAP Password: ",iface->name);
  181.         usflush(sp->output);
  182.         if (recvline(sp->input,buf,20) < 0)
  183.             pap_p->password = NULLCHAR;
  184.         else {
  185.             rip(buf);
  186.             pap_p->password = strdup(buf);
  187.         }
  188.         tprintf("\n");
  189.         /* Turn echo back on */
  190.         sp->ttystate.echo = 1;
  191.     }
  192.  
  193.     freesession(sp);
  194.     psignal(pap_p,0);
  195. }
  196.  
  197.  
  198. /* Check the FTP userfile for this user; get password if available */
  199. static void
  200. pap_pwdlookup(pap_p)
  201. struct pap_s *pap_p;
  202. {
  203.     char *buf;
  204.     char *password;
  205.     int permission;
  206.  
  207.     if ( pap_p->username == NULLCHAR )
  208.         return;
  209.  
  210.     if ( (buf = userlookup( pap_p->username, &password, NULLCHARP,
  211.             &permission, NULL )) == NULLCHAR )
  212.         return;
  213.  
  214.     /* Check permissions for this user */
  215.     if ( (permission & PPP_PWD_LOOKUP) == 0 ) {
  216.         /* Not in ftpuser file for password lookup */
  217.         free(buf);
  218.         return;
  219.     }
  220.  
  221.     /* Save the password from this userfile record */
  222.     pap_p->password = strdup(password);
  223.     free(buf);
  224. }
  225.  
  226.  
  227. /* Get user ID and password
  228.  * Return a NULLCHAR in either username or password if undefined
  229.  */
  230. static void
  231. pap_getpassword(fsm_p,mustask)
  232. struct fsm_s *fsm_p;
  233. int mustask;
  234. {
  235.     struct pap_s *pap_p = fsm_p->pdv;
  236.  
  237.     if (mustask) {
  238.         free(pap_p->username);
  239.         pap_p->username = NULLCHAR;
  240.         free(pap_p->password);
  241.         pap_p->password = NULLCHAR;
  242.     } else if ( pap_p->username != NULLCHAR
  243.          && pap_p->password == NULLCHAR) {
  244.         pap_pwdlookup(pap_p);
  245.     }
  246.  
  247.     if ((pap_p->username == NULLCHAR)
  248.      || (pap_p->password == NULLCHAR)) {
  249.         char *ifn = if_name( fsm_p->ppp_p->iface, " PAP" );
  250.         newproc( ifn,
  251.             256, pap_input, mustask, fsm_p->ppp_p->iface, pap_p, 0);
  252.         free( ifn );
  253.         pwait( fsm_p->pdv );
  254.     }
  255. }
  256.  
  257. /*******************************************/
  258. /* Verify user and password sent by remote host */
  259. static int
  260. pap_verify(username,password)
  261. char *username;
  262. char *password;
  263. {
  264.     int privs;
  265.     char *path;
  266.     int anony = 0;
  267.  
  268.     /* Use same login as FTP server */
  269.     path = mallocw(128);
  270.     privs = userlogin(username,password,&path,128,&anony);
  271.     free(path);
  272.  
  273.     /* Check privs for this user */
  274.     if (privs == -1) {
  275.         log(-1,"PAP: username/password incorrect or not found: %s",
  276.                 username);
  277.         return -1;
  278.     }
  279.  
  280.     if ((privs & PPP_ACCESS_PRIV) == 0) {
  281.         log(-1,"PAP: no permission for PPP access: %s",
  282.                 username);
  283.         return -1;
  284.     }
  285.     return 0;
  286. }
  287.  
  288.  
  289. /****************************************************************************/
  290. /* Build a request to send to remote host */
  291. static struct mbuf *
  292. pap_makereq(fsm_p)
  293. struct fsm_s *fsm_p;
  294. {
  295.     struct pap_s *pap_p = fsm_p->pdv;
  296.     struct mbuf *req_bp = NULLBUF;
  297.     register char *cp;
  298.     int len;
  299.  
  300.     PPP_DEBUG_ROUTINES("pap_makereq()");
  301.  
  302.     if ( pap_p->username == NULLCHAR
  303.      ||  pap_p->password == NULLCHAR ) {
  304.         fsm_log( fsm_p, "NULL username or password" );
  305.         return NULLBUF;
  306.     }
  307.  
  308. #ifdef PPP_DEBUG_OPTIONS
  309.     if (PPPtrace & PPP_DEBUG_OPTIONS)
  310.         log(-1, "    making user id %s", pap_p->username);
  311. #endif
  312.  
  313.     /* Get buffer for authenticate request packet */
  314.     len = 2 + strlen(pap_p->username) + strlen(pap_p->password);
  315.     if ((req_bp = alloc_mbuf(len)) == NULLBUF)
  316.         return NULLBUF;
  317.  
  318.     /* Load user id and password for authenticate packet */
  319.     cp = req_bp->data;
  320.     *cp++ = (char)strlen(pap_p->username);
  321.     if ( strlen(pap_p->username) > 0 )
  322.         cp = stpcpy(cp, pap_p->username);
  323.  
  324.     *cp++ = (char)strlen(pap_p->password);
  325.     if ( strlen(pap_p->password) > 0 )
  326.         cp = stpcpy(cp, pap_p->password);
  327.  
  328.     req_bp->cnt += len;
  329.     return(req_bp);
  330. }
  331.  
  332.  
  333. /****************************************************************************/
  334.  
  335. /* abandon PAP attempt; shutdown LCP layer */
  336. static void
  337. pap_shutdown(fsm_p)
  338. struct fsm_s *fsm_p;
  339. {
  340.     struct ppp_s *ppp_p = fsm_p->ppp_p;
  341.  
  342.     PPP_DEBUG_ROUTINES("pap_shutdown()");
  343.  
  344.     if (PPPtrace > 1)
  345.         fsm_log( fsm_p, "Failed; close PPP connection" );
  346.  
  347.     ppp_p->phase = pppTERMINATE;
  348.     psignal(ppp_p, 0);
  349. }
  350.  
  351.  
  352. /* Configuration negotiation complete */
  353. static void
  354. pap_opening(fsm_p, flag)
  355. struct fsm_s *fsm_p;
  356. int flag;
  357. {
  358.     register struct ppp_s *ppp_p = fsm_p->ppp_p;
  359.  
  360.     fsm_log(fsm_p, "Open");
  361.  
  362.     stop_timer(&(fsm_p->timer));
  363.  
  364.     if ( !((fsm_p->flags &= ~flag) & (PPP_AP_LOCAL | PPP_AP_REMOTE)) ) {
  365.         fsm_p->state = fsmOPENED;
  366.     }
  367.     if ( !((ppp_p->flags &= ~flag) & (PPP_AP_LOCAL | PPP_AP_REMOTE)) ) {
  368.         ppp_p->phase = pppREADY;
  369.         psignal(ppp_p, 0);
  370.     }
  371. }
  372.  
  373.  
  374. /****************************************************************************/
  375. /* Check request from remote host */
  376. static int
  377. pap_request(fsm_p, hdr, data)
  378. struct fsm_s *fsm_p;
  379. struct config_hdr *hdr;
  380. struct mbuf *data;
  381. {
  382.     struct pap_s *pap_p = fsm_p->pdv;
  383.     struct mbuf *reply_bp;
  384.     int result;
  385.     char *message;
  386.     int mess_length;
  387.     char *username = NULLCHAR;
  388.     int userlen;
  389.     char *password = NULLCHAR;
  390.     int passwordlen;
  391.  
  392.     PPP_DEBUG_ROUTINES("pap_request()");
  393.  
  394.     /* Extract userID/password sent by remote host */
  395.     if ( (userlen = pullchar(&data)) != -1 ) {
  396.         register int i;
  397.         register char *cp;
  398.  
  399.         cp = username = mallocw(userlen+1);
  400.         for ( i = userlen; i-- > 0; ) {
  401.             *cp++ = PULLCHAR(&data);
  402.         }
  403.         *cp = '\0';
  404.     }
  405.  
  406. #ifdef PPP_DEBUG_OPTIONS
  407.     if (PPPtrace & PPP_DEBUG_OPTIONS)
  408.         log(-1,"    checking user: %s", username);
  409. #endif
  410.  
  411.     if ( (passwordlen = pullchar(&data)) != -1 ) {
  412.         register int i;
  413.         register char *cp;
  414.  
  415.         cp = password = mallocw(passwordlen+1);
  416.         for ( i = passwordlen; i-- > 0; ) {
  417.             *cp++ = PULLCHAR(&data);
  418.         }
  419.         *cp = '\0';
  420.     }
  421.  
  422. #ifdef PPP_DEBUG_OPTIONS
  423.     if (PPPtrace & PPP_DEBUG_OPTIONS)
  424.         log(-1,"    checking password: %s", password);
  425. #endif
  426.  
  427.     if (pap_verify(username,password) == 0) {
  428.         free( pap_p->peername );
  429.         pap_p->peername = strdup(username);
  430.         result = CONFIG_ACK;
  431.         message = " Welcome";
  432.     } else {
  433.         result = CONFIG_NAK;
  434.         message = " Invalid username or password";
  435.     }
  436.  
  437.     /* the space at the beginning of the message is crucial */
  438.     mess_length = strlen(message);
  439.     reply_bp = qdata(message,mess_length);
  440.     reply_bp->data[0] = (char)(mess_length - 1);
  441.  
  442.     fsm_send(fsm_p, result, hdr->id, reply_bp);
  443.  
  444.     if (result == CONFIG_NAK) {
  445.         if ( fsm_p->retry_nak > 0 ) {
  446.             fsm_p->retry_nak--;
  447.         } else {
  448.             pap_shutdown(fsm_p);
  449.         }
  450.     }
  451.     free_p(data);
  452.     free(username);
  453.     free(password);
  454.     return (result != CONFIG_ACK);
  455. }
  456.  
  457.  
  458. /* Check acknowledgement from remote host */
  459. static int
  460. pap_check(fsm_p, hdr, data)
  461. struct fsm_s *fsm_p;
  462. struct config_hdr *hdr;
  463. struct mbuf *data;
  464. {
  465.     struct pap_s *pap_p = fsm_p->pdv;
  466.     char *message;
  467.     int mess_length;
  468.     int full_length;
  469.     int len;
  470.  
  471.     PPP_DEBUG_ROUTINES("pap_check()");
  472.  
  473.     /* ID field must match last request we sent */
  474.     if (hdr->id != fsm_p->lastid) {
  475.         PPP_DEBUG_CHECKS("PAP: wrong ID");
  476.         tprintf ("id mismatch hdrid=%d, lastid=%d\n",
  477.             hdr->id, fsm_p->lastid);
  478.         free_p(data);
  479.         return -1;
  480.     }
  481.  
  482.     /* Log ASCII message from remote host, if any */
  483.     if ( (mess_length = pullchar(&data)) != -1 ) {
  484.         message = mallocw( mess_length+1 );
  485.         full_length = len_p(data);
  486.         len = dqdata(data, message, mess_length);
  487.         message[len] = '\0';
  488.  
  489.         free( pap_p->message );
  490.         pap_p->message = message;
  491.  
  492.         if (PPPtrace) {
  493.             log(-1,"%s: PPP/PAP %s %s: %s",
  494.                 fsm_p->ppp_p->iface->name,
  495.                 (len < mess_length) ? "Short"
  496.                    : (mess_length < full_length) ? "Long"
  497.                     : "Valid",
  498.                 (hdr->code == CONFIG_ACK) ? "Ack" : "Nak",
  499.                 message);
  500.         }
  501.         return (len < mess_length  ||  mess_length < full_length);
  502.     }
  503.     free_p(data);
  504.     PPP_DEBUG_CHECKS( "PAP: missing message count" );
  505.     return -1;
  506. }
  507.  
  508.  
  509. /************************************************************************/
  510. /*            E V E N T   P R O C E S S I N G            */
  511. /************************************************************************/
  512.  
  513. /* Process incoming packet */
  514. void
  515. pap_proc(fsm_p,bp)
  516. struct fsm_s *fsm_p;
  517. struct mbuf *bp;
  518. {
  519.     struct pap_s *pap_p = fsm_p->pdv;
  520.     struct config_hdr hdr;
  521.  
  522.     PPPtrace = fsm_p->ppp_p->trace;
  523.  
  524.     ntohcnf(&hdr, &bp);
  525.     if (PPPtrace > 1)
  526.         log(-1,    "%s: PPP/%s Recv,"
  527.             "  option: %s, id: %d, len: %d",
  528.             fsm_p->ppp_p->iface->name,
  529.             fsm_p->pdc->name,
  530.             fsmCodes[hdr.code],
  531.             hdr.id,    hdr.len);
  532.  
  533.     hdr.len -= CONFIG_HDR_LEN;        /* Length includes envelope */
  534.     trim_mbuf(&bp, hdr.len);        /* Trim off padding */
  535.  
  536.     switch(hdr.code) {
  537.     case CONFIG_REQ:
  538.         if ( pap_request(fsm_p, &hdr, bp) == 0) {
  539.             pap_opening(fsm_p, PPP_AP_LOCAL);
  540.         }
  541.         break;
  542.  
  543.     case CONFIG_ACK:
  544.         if (pap_check(fsm_p, &hdr, bp) == 0) {
  545.             pap_opening(fsm_p, PPP_AP_REMOTE);
  546.         }
  547.         break;
  548.  
  549.     case CONFIG_NAK:
  550.         if (pap_check(fsm_p, &hdr, bp) == 0) {
  551.             /* Must have sent a bad user or password */
  552.             /* Get the password again */
  553.             pap_getpassword(fsm_p, TRUE);
  554.  
  555.             if (pap_p->username == NULLCHAR
  556.              || pap_p->password == NULLCHAR) {
  557.                 pap_shutdown(fsm_p);
  558.             } else {
  559.                 fsm_sendreq(fsm_p);
  560.             }
  561.         }
  562.         break;
  563.  
  564.     default:
  565.         if (PPPtrace)
  566.             log(-1, "%s: PPP/Pap: Unknown packet type: %d;"
  567.                 " dropping packet",
  568.                 fsm_p->ppp_p->iface->name,
  569.                 hdr.code);
  570.         free_p(bp);
  571.         break;
  572.     }
  573. }
  574.  
  575.  
  576. /* Timeout while waiting for reply from remote host */
  577. static void
  578. pap_timeout(vp)
  579. void *vp;
  580. {
  581.     struct fsm_s *fsm_p = (struct fsm_s *)vp;
  582.  
  583.     PPPtrace = fsm_p->ppp_p->trace;
  584.  
  585.     fsm_log( fsm_p, "Timeout" );
  586.  
  587.     if (fsm_p->retry > 0) {
  588.         fsm_sendreq(fsm_p);
  589.     } else {
  590.         fsm_log(fsm_p, "Request retry exceeded");
  591.         pap_shutdown(fsm_p);
  592.     }
  593. }
  594.  
  595.  
  596. /************************************************************************/
  597. /*            I N I T I A L I Z A T I O N            */
  598. /************************************************************************/
  599.  
  600. /* Reset state machine */
  601. static void
  602. pap_reset(fsm_p)
  603. struct fsm_s *fsm_p;
  604. {
  605.     PPP_DEBUG_ROUTINES("pap_reset()");
  606.  
  607.     fsm_p->state = fsmCLOSED;
  608.     fsm_p->retry = fsm_p->try_req;
  609.     fsm_p->retry_nak = fsm_p->try_nak;
  610. }
  611.  
  612.  
  613. /* Initialize state machine for local */
  614. int
  615. pap_local(ppp_p)
  616. struct ppp_s *ppp_p;
  617. {
  618.     struct fsm_s *fsm_p = &(ppp_p->fsm[Pap]);
  619.  
  620.     if (ppp_p->fsm[Pap].pdv == NULL)
  621.         pap_init(ppp_p);
  622.  
  623.     PPPtrace = fsm_p->ppp_p->trace;
  624.  
  625.     PPP_DEBUG_ROUTINES("pap_local()");
  626.  
  627.     pap_reset(fsm_p);
  628.     fsm_p->state = fsmLISTEN;
  629.     fsm_p->flags |= PPP_AP_LOCAL;
  630.     return 0;
  631. }
  632.  
  633.  
  634. /* Initialize state machine for remote */
  635. int
  636. pap_remote(ppp_p)
  637. struct ppp_s *ppp_p;
  638. {
  639.     struct fsm_s *fsm_p = &(ppp_p->fsm[Pap]);
  640.     struct pap_s *pap_p = fsm_p->pdv;
  641.  
  642.     if (ppp_p->fsm[Pap].pdv == NULL)
  643.         pap_init(ppp_p);
  644.  
  645.     PPPtrace = fsm_p->ppp_p->trace;
  646.  
  647.     PPP_DEBUG_ROUTINES("pap_remote()");
  648.  
  649.     /* We need to send REQ to remote host */
  650.     /* Get the user and password we will send */
  651.     if ((pap_p->username == NULLCHAR)
  652.      || (pap_p->password == NULLCHAR)) {
  653.         pap_getpassword(fsm_p, FALSE);
  654.  
  655.         if ((pap_p->username == NULLCHAR)
  656.          || (pap_p->password == NULLCHAR)) {
  657.             return -1;
  658.         }
  659.     }
  660.  
  661.     pap_reset(fsm_p);
  662.     fsm_p->state = fsmREQ_Sent;
  663.     fsm_p->flags |= PPP_AP_REMOTE;
  664.     return(fsm_sendreq(fsm_p));
  665. }
  666.  
  667.  
  668. void
  669. pap_down(fsm_p)
  670. struct fsm_s *fsm_p;
  671. {
  672.     if ( fsm_p->pdv == NULL )
  673.         return;
  674.  
  675.     PPPtrace = fsm_p->ppp_p->trace;
  676.  
  677.     fsm_log(fsm_p, "Down");
  678.  
  679.     fsm_p->flags = FALSE;
  680.  
  681.     switch ( fsm_p->state ) {
  682.     case fsmREQ_Sent:
  683.         stop_timer(&(fsm_p->timer));
  684.         /* fallthru */
  685.     case fsmOPENED:
  686.     case fsmLISTEN:
  687.     case fsmTERM_Sent:
  688.         fsm_p->state = fsmCLOSED;
  689.         break;
  690.  
  691.     case fsmCLOSED:
  692.         /* Already closed; nothing to do */
  693.         break;
  694.     }
  695. }
  696.  
  697.  
  698. static void
  699. pap_free(fsm_p)
  700. struct fsm_s *fsm_p;
  701. {
  702.     struct pap_s *pap_p = fsm_p->pdv;
  703.  
  704.     free( pap_p->username );
  705.     free( pap_p->password );
  706.     free( pap_p->peername );
  707.     free( pap_p->message );
  708. }
  709.  
  710.  
  711. /* Initialize configuration structure */
  712. static void
  713. pap_init(ppp_p)
  714. struct ppp_s *ppp_p;
  715. {
  716.     struct fsm_s *fsm_p;
  717.     struct timer *t;
  718.  
  719.     PPPtrace = ppp_p->trace;
  720.  
  721.     PPP_DEBUG_ROUTINES("pap_init()");
  722.  
  723.     if (ppp_p->fsm[Pap].pdv != NULL)
  724.         return;        /* already initialized */
  725.  
  726.     fsm_p = &(ppp_p->fsm[Pap]);
  727.     fsm_p->ppp_p = ppp_p;
  728.     fsm_p->pdc = &pap_constants;
  729.     fsm_p->pdv = callocw(1,sizeof(struct pap_s));
  730.  
  731.     fsm_p->try_req = fsm_p->pdc->try_req;
  732.     fsm_p->try_nak = fsm_p->pdc->try_nak;
  733.     fsm_p->try_terminate = fsm_p->pdc->try_terminate;
  734.  
  735.     pap_reset(fsm_p);
  736.  
  737.     /* Initialize timer */
  738.     t = &(fsm_p->timer);
  739.     t->func = (void (*)())pap_timeout;
  740.     t->arg = (void *)fsm_p;
  741.     set_timer(t, fsm_p->pdc->timeout);
  742.     fsm_timer(fsm_p);
  743.     stop_timer(t);
  744. }
  745.  
  746.  
  747.