home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 1 / HamRadio.cdr / misc / tcpipsrc / pppipcp.c < prev    next >
C/C++ Source or Header  |  1990-12-09  |  44KB  |  1,698 lines

  1. /*
  2.  *  PPPIPCP.C    -- negotiate IP parameters
  3.  *
  4.  *    12-89    -- Katie Stevens (dkstevens@ucdavis.edu)
  5.  *           UC Davis, Computing Services
  6.  *    PPP.04    02-90    [ks] make automatic route entry a private route
  7.  *    PPP.07    04-90    [ks] make IP addr negotiation independent of
  8.  *                 whether host is active or passive open
  9.  *                 thanks to Brad Clements, bkc@omnigate.clarkson.edu
  10.  *                 dont bring up IP unless both addrs are known
  11.  *    PPP.08    05-90    [ks] IP compr: we request means we want to rcv compr;
  12.  *                 remote requests means we should xmt compr TCP.
  13.  *                 improve PPP trace reporting
  14.  *    PPP.09    05-90    [ks] add UPAP auth protocol
  15.  *    PPP.10    07-90    [ks] make ppp open/close/reset work properly
  16.  *                 add peerID-to-IPaddr lookup table
  17.  *                 add peer IP lookup pool
  18.  *    PPP.13    08-90    [ks] add timestamp on PPP link open
  19.  *    PPP.14    08-90    [ks] change UPAP to PAP for consistency with RFC1172
  20.  *                 make IPCP timeout configurable
  21.  *    PPP.15    09-90    [ks] update to KA9Q NOS v900828
  22.  */
  23.  
  24. #include <stdio.h>
  25. #include <ctype.h>
  26. #include <time.h>
  27. #include "global.h"
  28. #include "files.h"
  29. #include "netuser.h"
  30. #include "mbuf.h"
  31. /*#include "proc.h"*/
  32. #include "iface.h"
  33. #include "pktdrvr.h"
  34. #include "ip.h"
  35. #include "tcp.h"
  36. #include "slcompre.h"
  37. #include "ppp.h"
  38. #include "slip.h"
  39. #include "proc.h"
  40.  
  41. extern int32 Ip_addr;
  42.  
  43. /* Counter for PPP id field */
  44. extern unsigned char Pppid;
  45.  
  46. /* PPP tracing */
  47. extern int Ppptrace;
  48.  
  49. static void ipcp_open __ARGS((struct slip *sp));
  50. static int ipcp_addr_idle __ARGS((int32 addr));
  51. static int32 ipcp_lookuppeer __ARGS((char *peerid));
  52. static int32 ipcp_poolnext __ARGS((struct ipcppool *poolp));
  53. static void ipcp_reset_tcp __ARGS((struct slip *sp));
  54.  
  55. static int ipcp_sendreq __ARGS((struct slip *sp));
  56. static struct mbuf *ipcp_makereq __ARGS((struct ipcpctl *ipcpiop));
  57.  
  58. static void ipcp_rcvack __ARGS((struct slip *sp, struct cnfhdr *rcnf,
  59.             struct mbuf *data));
  60. static void ipcp_rcvnak __ARGS((struct slip *sp, struct cnfhdr *rcnf,
  61.             struct mbuf *data));
  62. static void ipcp_rcvrej __ARGS((struct slip *sp, struct cnfhdr *rcnf,
  63.             struct mbuf *data));
  64. static void ipcp_rcvreq __ARGS((struct slip *sp, struct cnfhdr *rcnf,
  65.             struct mbuf *data));
  66. static void ipcp_rcvtermack __ARGS((struct slip *sp));
  67. static void ipcp_rcvtermreq __ARGS((struct slip *sp, struct cnfhdr *rcnf));
  68. static void ipcp_shutdown __ARGS((struct slip *sp));
  69.  
  70. static int ipcp_chkack __ARGS((struct slip *sp, struct cnfhdr *ackcnf,
  71.             struct mbuf *data));
  72. static int ipcp_chknak __ARGS((struct slip *sp, struct cnfhdr *nakcnf,
  73.             struct mbuf *data));
  74. static int ipcp_chkrej __ARGS((struct slip *sp, struct cnfhdr *rejcnf,
  75.             struct mbuf *data));
  76. static void ipcp_chkreq __ARGS((struct slip *sp, struct cnfhdr *reqcnf,
  77.             struct mbuf *data));
  78.  
  79. static void ipcp_timeout __ARGS((void *vp));
  80. static void ipcp_timer __ARGS((struct slip *sp));
  81.  
  82. static int ipcp_sendreply __ARGS((struct slip *sp, char code,
  83.             unsigned char id, struct mbuf *data));
  84.  
  85. /* In PPPLCP.C */
  86. /* Possible IPCP states same as possible LCP states */
  87. extern char *LCPStates[];
  88. extern char *LCPCodes[];
  89.  
  90. /****************************************************************************/
  91.  
  92. /* Initialize IP Control Protocol state machine for config exchange */
  93. int
  94. ipcp_start(sp)
  95. struct slip *sp;
  96. {
  97.     struct pppctl *pppiop;
  98.     struct lcpctl *lcpiop;
  99.     struct ipcpctl *ipcpiop;
  100.  
  101.     if (Ppptrace > 5)
  102.         log(-1, "ipcp_start()");
  103.  
  104.     pppiop = sp->pppio;
  105.     lcpiop = &(pppiop->lcpio);
  106.     ipcpiop = &(pppiop->ipcpio);
  107.  
  108.     /* Just finished LCP negotiation; prepare for IPCP negotiation */
  109.     pppiop->state = PPP_IPCP;
  110.     ipcp_reset(sp);
  111.     /* Can set peer_addr with 'ppp peer' command */
  112.     ipcpiop->attempt_dest = ipcpiop->peer_addr;
  113.     /* If not already set, can lookup PAP peer ID in PPPHOSTS file */
  114.     if ((ipcpiop->peer_addr == 0L) &&
  115.         (lcpiop->lclparm.auth_type == PAP_AUTH_TYPE)) {
  116.         ipcpiop->attempt_dest = ipcp_lookuppeer(lcpiop->pap_user);
  117.     }
  118.     /* If still not set, can get next address from PPP pool */
  119.     if ((ipcpiop->peer_addr == 0L) &&
  120.         (ipcpiop->peer_pool != NULLPOOL)) {
  121.         ipcpiop->attempt_dest = ipcp_poolnext(ipcpiop->peer_pool);
  122.     }
  123.     if (ipcpiop->attempt_dest == 0L)
  124.         ipcpiop->accept_addrs = 1;
  125.  
  126.     if (!ipcpiop->active) {
  127.         /* Passive open; wait until remote host attempts connection */
  128.         ipcpiop->ipcp_state = IPCP_LISTEN;
  129.         return 0;
  130.     }
  131.  
  132.     /* Active open; begin IPCP configuration negotiation */
  133.     ipcpiop->ipcp_state = IPCP_CLOSED;    
  134.     return(ipcp_sendreq(sp));
  135. }
  136.  
  137. /*******************************************/
  138.  
  139. /* Close the IP connection from local side */
  140. int
  141. ipcp_close(sp)
  142. struct slip *sp;
  143. {
  144.     struct pppctl *pppiop;
  145.     struct ipcpctl *ipcpiop;
  146.  
  147.     if (Ppptrace > 5)
  148.         log(-1,"ipcp_close()");
  149.  
  150.     pppiop = sp->pppio;
  151.     ipcpiop = &(pppiop->ipcpio);
  152.     if ((ipcpiop->ipcp_state == IPCP_CLOSED) ||
  153.         (ipcpiop->ipcp_state == IPCP_LISTEN))   {
  154.         /* Already closed */
  155.         return 0;
  156.     }
  157.  
  158.     if (Ppptrace > 1)
  159.         log(-1,"%s: PPP/IPCP IP Closing",sp->iface->name);
  160.  
  161.     /* Reset IP connections on this interface */
  162.     ipcp_reset_tcp(sp);
  163.     /* Remove routing entry from route table */
  164.     rt_drop(ipcpiop->attempt_dest, (unsigned int)32);
  165.  
  166.     /* Set a timer against our request to shutdown */
  167.     ipcp_timer(sp);
  168.     /* Ask remote host to shutdown */
  169.     ipcpiop->ipcp_state = IPCP_TERMINATE;
  170.     ipcpiop->ack_retry = 0;
  171.     if (ipcp_sendreply(sp, TERMINATE_REQ, 0, NULLBUF) == 0)
  172.         pwait(ipcpiop);
  173.     return 0;
  174. }
  175.  
  176. /* Initialize our IPCP configuration options to compiled default options */
  177. void
  178. ipcp_init(sp)
  179. struct slip *sp;
  180. {
  181.     struct pppctl *pppiop;
  182.     struct ipcpctl *ipcpiop;
  183.     struct timer *t;
  184.  
  185.     if (Ppptrace > 5)
  186.         log(-1, "ipcp_init()");
  187.  
  188.     pppiop = sp->pppio;
  189.     ipcpiop = &(pppiop->ipcpio);
  190.     t = &(ipcpiop->ipcp_tm);
  191.     ipcpiop->ipcp_state = IPCP_CLOSED;
  192.  
  193.     /* Set option parameters to first request defaults */
  194.     ipcpiop->peer_addr = 0L;
  195.     ipcpiop->neg_ip_compr = 0;
  196.     ipcpiop->ip_compr_type = DEF_IP_COMPR;
  197.     /* Initialize timer */
  198.     set_timer(t,IPCP_TIMEOUT*1000L);
  199.     ipcp_timer(sp);
  200.     stop_timer(&(ipcpiop->ipcp_tm));
  201.  
  202.     ipcp_reset(sp);
  203. }
  204.  
  205. /* IP Control configuration negotiation complete */
  206. static void
  207. ipcp_open(sp)
  208. struct slip *sp;
  209. {
  210.     struct pppctl *pppiop;
  211.     struct ipcpctl *ipcpiop;
  212.  
  213.     pppiop = sp->pppio;
  214.     ipcpiop = &(pppiop->ipcpio);
  215.  
  216.     /* Mark IPCP layer as open */
  217.     if (Ppptrace)
  218.         log(-1,"%s: PPP/IPCP IP Open",sp->iface->name);
  219.     ipcpiop->ipcp_state = IPCP_OPEN;
  220.  
  221.     /* Make sure we found out IP address at each end */
  222.     if ((ipcpiop->attempt_src != ipcpiop->accept_dest)
  223.         || (ipcpiop->attempt_src == 0L)) {
  224.         if (Ppptrace)
  225.             log(-1,"Couldnt negotiate local IP addr for interface %s",
  226.                 sp->iface->name);
  227.         ipcp_shutdown(sp);
  228.         return;
  229.     }
  230.     if ((ipcpiop->attempt_dest != ipcpiop->accept_src)
  231.         || (ipcpiop->attempt_dest == 0L)) {
  232.         if (Ppptrace)
  233.             log(-1,"Couldnt negotiate remote peer IP addr for interface %s",
  234.                 sp->iface->name);
  235.         ipcp_shutdown(sp);
  236.         return;
  237.     }
  238.  
  239.     /* Set IP compression to reflect negotiated option */
  240.     if (ipcpiop->lcl_ip_compr == IPCP_VJCOMPR) {
  241.         sp->escaped |= PPP_RCV_VJCOMPR;
  242.         if (Ppptrace > 1)
  243.             log(-1,"    Begin Van Jacobson TCP/IP header compression on incoming packets");
  244.     } else {
  245.         sp->escaped &= ~PPP_RCV_VJCOMPR;
  246.     }
  247.     if (ipcpiop->rem_ip_compr == IPCP_VJCOMPR) {
  248.         sp->escaped |= PPP_XMT_VJCOMPR;
  249.         if (Ppptrace > 1)
  250.             log(-1,"    Begin Van Jacobson TCP/IP header compression on outgoing packets");
  251.     } else {
  252.         sp->escaped &= ~PPP_XMT_VJCOMPR;
  253.     }
  254.     if ((sp->escaped & (PPP_RCV_VJCOMPR | PPP_XMT_VJCOMPR)) != 0) {
  255.         /* Initialize compression control structure */
  256.         sp->slcomp = (struct slcompress *)mallocw(sizeof(struct slcompress));
  257.         sl_compress_init(sp->slcomp);
  258.     }
  259.  
  260.     /* Set our IP address to reflect negotiated option */
  261.     if (ipcpiop->attempt_src != sp->iface->addr) {
  262.         if (Ip_addr == 0L)
  263.             Ip_addr = ipcpiop->attempt_src;
  264.         sp->iface->addr = ipcpiop->attempt_src;
  265.         if (Ppptrace > 1)
  266.             log(-1,"    Saving new IP addr for interface %s: %s",
  267.                 sp->iface->name,inet_ntoa(sp->iface->addr));
  268.     }
  269.  
  270.     /* Add point-to-point route to remote PPP host */
  271.     rt_add(ipcpiop->attempt_dest, (unsigned int)32, (int32)0,
  272.         sp->iface, (int32)1, (int32)0, (char)1);
  273.     if (Ppptrace > 1)
  274.         log(-1,"    Add route to peer (%s) on interface %s",
  275.             inet_ntoa(ipcpiop->attempt_dest),
  276.             sp->iface->name);
  277.  
  278. /* Allow any queued IP traffic */
  279.     pppiop->state = PPP_OPEN;
  280.     pppiop->upsince = time(0L);
  281. }
  282.  
  283. /* Reset IPCP configuration options for initial request */
  284. int
  285. ipcp_reset(sp)
  286. struct slip *sp;
  287. {
  288.     struct pppctl *pppiop;
  289.     struct ipcpctl *ipcpiop;
  290.  
  291.     if (Ppptrace > 5)
  292.         log(-1, "ipcp_reset()");
  293.  
  294.     pppiop = sp->pppio;
  295.     ipcpiop = &(pppiop->ipcpio);
  296.     ipcpiop->ipcp_state = IPCP_CLOSED;
  297.     ipcpiop->ack_retry = 0;
  298.     ipcpiop->active = pppiop->lcpio.active;
  299.  
  300.     /* Set up for IP addr exchange; attempt values set in ipcp_start() */
  301.     ipcpiop->attempt_addrs = 1;
  302.     ipcpiop->attempt_src = Ip_addr;
  303.     /* If we dont know our IP address, or if we dont know IP addr */
  304.     /* of the remote host, accept address assignment from remote  */
  305.     if ((ipcpiop->attempt_src == 0L)||(ipcpiop->attempt_dest == 0L)) {
  306.         ipcpiop->accept_addrs = 1;
  307.     } else {
  308.         ipcpiop->accept_addrs = 0;
  309.     }
  310.     ipcpiop->accept_src = ipcpiop->attempt_dest;
  311.     ipcpiop->accept_dest = ipcpiop->attempt_src;
  312.  
  313.     /* Reset IP header compression options to first request defaults */
  314.     ipcpiop->attempt_ip_compr = ipcpiop->neg_ip_compr;
  315.     ipcpiop->lcl_ip_compr = ipcpiop->ip_compr_type;
  316.     ipcpiop->accept_ip_compr = 1;
  317.     ipcpiop->rem_ip_compr = DEF_IP_COMPR;
  318.     sp->escaped &= ~PPP_RCV_VJCOMPR;
  319.     sp->escaped &= ~PPP_XMT_VJCOMPR;
  320.  
  321.     return 0;
  322. }
  323.  
  324. /*******************************************/
  325.  
  326. static int
  327. ipcp_addr_idle(addr)
  328. int32 addr;
  329. {
  330.     struct iface *ifp;
  331.     struct pppctl *pppiop;
  332.  
  333.     /* Check if peer IP address is already in use on another interface */
  334.     for (ifp=Ifaces; ifp != NULLIF; ifp = ifp->next) {
  335.         if ((Slip[ifp->xdev].iface == ifp) &&
  336.             (Slip[ifp->xdev].type == CL_PPP)) {
  337.             pppiop = Slip[ifp->xdev].pppio;
  338.             if ((pppiop->ipcpio.ipcp_state != IPCP_CLOSED) &&
  339.                 (pppiop->ipcpio.attempt_dest == addr))        {
  340.                 return 0;
  341.             }
  342.         }
  343.     }
  344.     return 1;
  345. }
  346.  
  347. /* Check if we have a specific IP address to assign to remote peer host */
  348. static int32
  349. ipcp_lookuppeer(peerid)
  350. char *peerid;
  351. {
  352.     FILE *peerfp;
  353.     char buf[128];
  354.     char *cp;
  355.     int32 peer_addr = 0L;
  356.  
  357.     if ((peerfp = fopen(Userfile, READ_TEXT)) == NULLFILE)
  358.         return 0L;
  359.     while (fgets(buf,128,peerfp) != NULLCHAR) {
  360.         if(buf[0] == '#')
  361.             continue;    /* Comment */
  362.         if((cp = strchr(buf,' ')) == NULLCHAR)
  363.             /* Bogus entry */
  364.             continue;
  365.         *cp++ = '\0';        /* Now points to password */
  366.         if(stricmp(peerid,buf) == 0) {
  367.             ++cp;
  368.             if ((cp = strrchr(cp,' ')) == NULLCHAR)
  369.                 /* No IP address given */
  370.                 break;
  371.             ++cp;
  372.             peer_addr = resolve(cp);
  373.             break;        /* Found user name */
  374.         }
  375.     }
  376.     fclose(peerfp);
  377.     return(peer_addr);
  378. }
  379.  
  380. static int32
  381. ipcp_poolnext(poolp)
  382. struct ipcppool *poolp;
  383. {
  384.     int i;
  385.     int32 nextaddr = 0L;
  386.  
  387.     for (i=0; i<=(poolp->peer_max - poolp->peer_min); ++i) {
  388.         if (ipcp_addr_idle(poolp->peer_next))
  389.             nextaddr = poolp->peer_next;
  390.  
  391.         if (poolp->peer_next == poolp->peer_max)
  392.             poolp->peer_next = poolp->peer_min;
  393.         else
  394.             ++poolp->peer_next;
  395.  
  396.         if (nextaddr != 0L)
  397.             break;
  398.     }
  399.     return(nextaddr);
  400. }
  401.  
  402. /* Close all TCP connections in preparation for PPP link shutdown */
  403. static void
  404. ipcp_reset_tcp(sp)
  405. struct slip *sp;
  406. {
  407.     register struct iface *ifp;
  408.     register int i;
  409.     register struct tcb *tcb;
  410.     register struct route *rp;
  411.  
  412.     ifp = sp->iface;
  413.  
  414.     for(i=0;i<NTCB;i++){
  415.         for(tcb=Tcbs[i];tcb != NULLTCB;tcb = tcb->next) {
  416.             if ((tcb->state == TCP_LISTEN) &&
  417.                 (tcb->flags.clone == 1))      {
  418.                 /* Leave servers alone */
  419.                 continue;
  420.             }
  421.             rp = rt_lookup(tcb->conn.remote.address);
  422.             if (rp->iface == ifp) {
  423.                 /* Reset active connections */
  424.                 reset_tcp(tcb);
  425.             }
  426.         }
  427.     }
  428.     /* Wait 1sec for any replys or static */
  429.     pause(1000L);
  430. }
  431.  
  432. /****************************************************************************/
  433.  
  434. /* Send our IPCP configuration request */
  435. static int
  436. ipcp_sendreq(sp)
  437. struct slip *sp;
  438. {
  439.     struct pppctl *pppiop;
  440.     struct ipcpctl *ipcpiop;
  441.     struct mbuf *bp;
  442.  
  443.     if (Ppptrace > 5)
  444.         log(-1,"ipcp_sendreq()");
  445.  
  446.     pppiop = sp->pppio;
  447.     ipcpiop = &(pppiop->ipcpio);
  448.  
  449.     /* Get a packet with our configuration request */
  450.     bp = ipcp_makereq(ipcpiop);
  451.  
  452.     /* Start timer against wait for reply to our config request */
  453.     ipcp_timer(sp);
  454.  
  455.     /* Send IPCP configuration request to remote host */
  456.     pppiop->state = PPP_IPCP;
  457.     if (ipcpiop->ipcp_state != IPCP_ACK_SENT)
  458.         ipcpiop->ipcp_state = IPCP_REQ_SENT;
  459.     return(ipcp_sendreply(sp, CONFIG_REQ, 0, bp));
  460. }
  461.  
  462. /*******************************************/
  463.  
  464. static struct mbuf *
  465. ipcp_makereq(ipcpiop)
  466. struct ipcpctl *ipcpiop;
  467. {
  468.     register char *cp;
  469.     struct mbuf *bp;
  470.     struct mbuf *req_bp = NULLBUF;
  471.  
  472.     if (Ppptrace > 5)
  473.         log(-1,"    ipcp_makereq()");
  474.  
  475.     /* Request our preferred IP control options */
  476.     if (ipcpiop->attempt_addrs) {
  477.         /* Attempt to negotiate IP addrs */
  478.         if (Ppptrace > 5) {
  479.             log(-1,"    asking for src addr: %s",
  480.                 inet_ntoa(ipcpiop->attempt_src));
  481.             log(-1,"    asking for dest addr: %s",
  482.                 inet_ntoa(ipcpiop->attempt_dest));
  483.         }
  484.         if ((bp = alloc_mbuf(10)) == NULLBUF)
  485.             return NULLBUF;
  486.         cp = bp->data;
  487.         *cp++ = IP_ADDRS;
  488.         *cp++ = 10;
  489.         cp = put32(cp, ipcpiop->attempt_src);
  490.         cp = put32(cp, ipcpiop->attempt_dest);
  491.         bp->cnt += 10;
  492.         append(&req_bp, bp);
  493.     }
  494.  
  495.     /* IP header compression */
  496.     if (ipcpiop->attempt_ip_compr) {
  497.         if (Ppptrace > 5) {
  498.             log(-1,"    asking for IP compression: %x",
  499.                 ipcpiop->lcl_ip_compr);
  500.         }
  501.  
  502.         /* Attempt to negotiate IP compression */
  503.         if ((bp = alloc_mbuf(4)) == NULLBUF)
  504.             return NULLBUF;
  505.         cp = bp->data;
  506.         *cp++ = IP_COMPR_TYPE;
  507.         *cp++ = 4;
  508.         put16(cp, ipcpiop->lcl_ip_compr);
  509.         bp->cnt += 4;
  510.         append(&req_bp, bp);
  511.     }
  512.  
  513.     /* Return our config request */
  514.     return(req_bp);
  515. }
  516.  
  517. /****************************************************************************/
  518.  
  519. /* Remote host ACKed our configuration request */
  520. static void
  521. ipcp_rcvack(sp, rcnf, data)
  522. struct slip *sp;
  523. struct cnfhdr *rcnf;
  524. struct mbuf *data;
  525. {
  526.     struct pppctl *pppiop;
  527.     struct ipcpctl *ipcpiop;
  528.  
  529.     if (Ppptrace > 5)
  530.         log(-1, "ipcp_rcvack()");
  531.  
  532.     pppiop = sp->pppio;
  533.     ipcpiop = &(pppiop->ipcpio);
  534.     stop_timer(&ipcpiop->ipcp_tm);
  535.  
  536.     switch(ipcpiop->ipcp_state) {
  537.     case IPCP_REQ_SENT:
  538.         /* Make sure ACK is proper */
  539.         if (ipcp_chkack(sp, rcnf, data) != -1) {
  540.             /* Remote host accepted our request */
  541.             ipcpiop->ipcp_state = IPCP_ACK_RCVD;
  542.         }
  543.  
  544.         /* Still need to settle request from remote host */
  545.         ipcp_timer(sp);
  546.         break;
  547.  
  548.     case IPCP_ACK_SENT:
  549.         /* Make sure ACK is proper */
  550.         if (ipcp_chkack(sp, rcnf, data) == -1) {
  551.             /* Error in ACK from remote host */
  552.             /* Wait for another ACK, then send another request */
  553.             ipcp_timer(sp);
  554.         } else {
  555.             /* IPCP negotiation complete */
  556.             ipcp_open(sp);
  557.         }
  558.         break;
  559.  
  560.     case IPCP_ACK_RCVD:
  561.     case IPCP_OPEN:
  562.         /* Something went wrong; restart negotiations */
  563.         free_p(data);    
  564.         ipcp_reset(sp);
  565.         ipcp_sendreq(sp);
  566.         break;
  567.     case IPCP_TERMINATE:
  568.         /* We are attempting to close connection; wait */
  569.         /* for timeout to resend a Terminate Request */
  570.         free_p(data);
  571.         break;
  572.     case IPCP_CLOSED:
  573.     case IPCP_LISTEN:
  574.     default:
  575.         /* Confusion; shutdown the connection */
  576.         free_p(data);
  577.         ipcp_shutdown(sp);
  578.         break;
  579.     }
  580. }
  581.  
  582. /* Remote host NAKed our configuration request */
  583. static void
  584. ipcp_rcvnak(sp, rcnf, data)
  585. struct slip *sp;
  586. struct cnfhdr *rcnf;
  587. struct mbuf *data;
  588. {
  589.     struct pppctl *pppiop;
  590.     struct ipcpctl *ipcpiop;
  591.  
  592.     if (Ppptrace > 5)
  593.         log(-1, "ipcp_rcvnak()");
  594.  
  595.     pppiop = sp->pppio;
  596.     ipcpiop = &(pppiop->ipcpio);
  597.     stop_timer(&ipcpiop->ipcp_tm);
  598.  
  599.     switch(ipcpiop->ipcp_state) {
  600.     case IPCP_REQ_SENT:
  601.     case IPCP_ACK_SENT:
  602.         /* Update our config request to reflect NAKed options */
  603.         if (ipcp_chknak(sp, rcnf, data) == -1) {
  604.             /* Bad NAK packet */
  605.             /* Wait for another; resend request on timeout */
  606.             ipcp_timer(sp);
  607.         } else {
  608.             /* Send updated config request */
  609.             ipcp_sendreq(sp);
  610.         }
  611.         break;
  612.  
  613.     case IPCP_ACK_RCVD:
  614.     case IPCP_OPEN:
  615.         /* Something went wrong; restart negotiations */
  616.         free_p(data);    
  617.         ipcp_reset(sp);
  618.         ipcp_sendreq(sp);
  619.         break;
  620.     case IPCP_TERMINATE:
  621.         /* We are attempting to close connection; wait */
  622.         /* for timeout to resend a Terminate Request */
  623.         free_p(data);
  624.         break;
  625.     case IPCP_CLOSED:
  626.     case IPCP_LISTEN:
  627.     default:
  628.         /* Confusion; shutdown the connection */
  629.         free_p(data);
  630.         ipcp_shutdown(sp);
  631.         break;
  632.     }
  633. }
  634.  
  635. /* Remote host rejected our configuration request */
  636. static void
  637. ipcp_rcvrej(sp, rcnf, data)
  638. struct slip *sp;
  639. struct cnfhdr *rcnf;
  640. struct mbuf *data;
  641. {
  642.     struct pppctl *pppiop;
  643.     struct ipcpctl *ipcpiop;
  644.  
  645.     if (Ppptrace > 5)
  646.         log(-1, "ipcp_rcvrej()");
  647.  
  648.     pppiop = sp->pppio;
  649.     ipcpiop = &(pppiop->ipcpio);
  650.     stop_timer(&ipcpiop->ipcp_tm);
  651.  
  652.     switch(ipcpiop->ipcp_state) {
  653.     case IPCP_REQ_SENT:
  654.     case IPCP_ACK_SENT:
  655.         /* Update our config request to reflect rejected options */
  656.         if (ipcp_chkrej(sp, rcnf, data) == -1) {
  657.             /* Bad reject packet */
  658.             /* Wait for another; resend request on timeout */
  659.             ipcp_timer(sp);
  660.         } else {
  661.             /* Send updated config request */
  662.             ipcp_sendreq(sp);
  663.         }
  664.         break;
  665.  
  666.     case IPCP_ACK_RCVD:
  667.     case IPCP_OPEN:
  668.         /* Something went wrong; restart negotiations */
  669.         free_p(data);    
  670.         ipcp_reset(sp);
  671.         ipcp_sendreq(sp);
  672.         break;
  673.     case IPCP_TERMINATE:
  674.         /* We are attempting to close connection; wait */
  675.         /* for timeout to resend a Terminate Request */
  676.         free_p(data);
  677.         break;
  678.     case IPCP_CLOSED:
  679.     case IPCP_LISTEN:
  680.     default:
  681.         /* Confusion; shutdown the connection */
  682.         free_p(data);
  683.         ipcp_shutdown(sp);
  684.         break;
  685.     }
  686. }
  687.  
  688. /* Process configuration request sent by remote host */
  689. static void
  690. ipcp_rcvreq(sp, rcnf, data)
  691. struct slip *sp;
  692. struct cnfhdr *rcnf;
  693. struct mbuf *data;
  694. {
  695.     struct pppctl *pppiop;
  696.     struct ipcpctl *ipcpiop;
  697.  
  698.     if (Ppptrace > 5)
  699.         log(-1, "ipcp_rcvreq()");
  700.  
  701.     pppiop = sp->pppio;
  702.     ipcpiop = &(pppiop->ipcpio);
  703.  
  704.     switch(ipcpiop->ipcp_state) {
  705.     case IPCP_LISTEN:    /* Normal event */
  706.     case IPCP_ACK_SENT:    /* Unexpected event */
  707.     case IPCP_OPEN:        /* Unexpected event */
  708.         /* Reset IPCP state machine for configuration negotiation */
  709.         ipcp_reset(sp);
  710.         /* Send our configuration request */    
  711.         ipcp_sendreq(sp);
  712.         /* Evaluate configuration request from remote host */
  713.         ipcp_chkreq(sp, rcnf, data);
  714.         break;
  715.  
  716.     case IPCP_ACK_RCVD:
  717.         /* Stop timer against wait for config request */
  718.         stop_timer(&(ipcpiop->ipcp_tm));
  719.     case IPCP_REQ_SENT:
  720.         /* Evaluate configuration request from remote host */
  721.         ipcp_chkreq(sp, rcnf, data);
  722.         break;
  723.  
  724.     case IPCP_TERMINATE:
  725.         /* We are attempting to close connection; wait */
  726.         /* for timeout to resend a Terminate Request   */
  727.         free_p(data);
  728.         break;
  729.  
  730.     case IPCP_CLOSED:
  731.     default:
  732.         /* We are closed; dont accept any connections */
  733.         free_p(data);
  734.         ipcp_shutdown(sp);
  735.         break;
  736.     }
  737. }
  738.  
  739. /* Remote host closed connection */
  740. static void
  741. ipcp_rcvtermack(sp)
  742. struct slip *sp;
  743. {
  744.     struct pppctl *pppiop;
  745.     struct ipcpctl *ipcpiop;
  746.  
  747.     if (Ppptrace > 5)
  748.         log(-1,"ipcp_rcvtermack()");
  749.  
  750.     pppiop = sp->pppio;
  751.     ipcpiop = &(pppiop->ipcpio);
  752.     stop_timer(&(ipcpiop->ipcp_tm));
  753.  
  754.     switch(ipcpiop->ipcp_state) {
  755.     case IPCP_OPEN:
  756.         /* Remote host has abruptly closed connection */
  757.         /* Reset IP connections on this interface */
  758.         ipcp_reset_tcp(sp);
  759.         /* Remove routing entry from route table */
  760.         rt_drop(ipcpiop->attempt_dest, (unsigned int)32);
  761.         /* Fall through */
  762.     case IPCP_TERMINATE:
  763.         /* Remote host has responded to our terminate request */
  764.         if (Ppptrace)
  765.             log(-1,"%s: PPP/IPCP IP Closed",sp->iface->name);
  766.         if (ipcpiop->active)
  767.             ipcpiop->ipcp_state = IPCP_CLOSED;
  768.         else
  769.             ipcpiop->ipcp_state = IPCP_LISTEN;
  770.         /* Prepare for next open */
  771.         ipcp_reset(sp);
  772.         /* We are done; signal anyone waiting for us to close */
  773.         psignal(ipcpiop,0);
  774.         break;
  775.     case IPCP_REQ_SENT:
  776.         /* Wait for timeout to restart attempt */
  777.         break;
  778.     case IPCP_ACK_SENT:
  779.     case IPCP_ACK_RCVD:
  780.         /* Something went wrong; restart negotiations */
  781.         ipcp_reset(sp);
  782.         ipcp_sendreq(sp);
  783.         break;
  784.     case IPCP_CLOSED:
  785.     case IPCP_LISTEN:
  786.     default:
  787.         /* Unexpected, but no action needed */
  788.         break;
  789.     }
  790. }
  791.  
  792. /* Remote peer requested that we close the IP layer */
  793. static void
  794. ipcp_rcvtermreq(sp, rcnf)
  795. struct slip *sp;
  796. struct cnfhdr *rcnf;
  797. {
  798.     struct pppctl *pppiop;
  799.     struct ipcpctl *ipcpiop;
  800.  
  801.     if (Ppptrace > 5)
  802.         log(-1, "ipcp_shutdown()");
  803.  
  804.     pppiop = sp->pppio;
  805.     ipcpiop = &(pppiop->ipcpio);
  806.  
  807.     /* Reset IP connections on this interface */
  808.     ipcp_reset_tcp(sp);
  809.     /* Remove routing entry from route table */
  810.     rt_drop(ipcpiop->attempt_dest, (unsigned int)32);
  811.  
  812.     if (Ppptrace)
  813.         log(-1,"%s: PPP/IPCP Peer requested close",sp->iface->name);
  814.     ipcpiop->active = 0;
  815.     ipcpiop->ipcp_state = IPCP_LISTEN;
  816.  
  817.     ipcp_sendreply(sp, TERMINATE_ACK, rcnf->id, NULLBUF);
  818.     ipcp_reset(sp);
  819. }
  820.  
  821. /* Shutdown the IPCP connection */
  822. static void
  823. ipcp_shutdown(sp)
  824. struct slip *sp;
  825. {
  826.     struct pppctl *pppiop;
  827.     struct ipcpctl *ipcpiop;
  828.  
  829.     if (Ppptrace > 5)
  830.         log(-1, "ipcp_shutdown()");
  831.  
  832.     pppiop = sp->pppio;
  833.     ipcpiop = &(pppiop->ipcpio);
  834.  
  835.     /* Reset IP connections on this interface */
  836.     ipcp_reset_tcp(sp);
  837.     /* Remove routing entry from route table */
  838.     rt_drop(ipcpiop->attempt_dest, (unsigned int)32);
  839.  
  840.     if (Ppptrace)
  841.         log(-1,"%s: PPP/IPCP IP Shutdown",sp->iface->name);
  842.     if (ipcpiop->active)
  843.         ipcpiop->ipcp_state = IPCP_CLOSED;
  844.     else
  845.         ipcpiop->ipcp_state = IPCP_LISTEN;
  846.  
  847.     ipcp_sendreply(sp,TERMINATE_ACK,0,NULLBUF);
  848.     ipcp_reset(sp);
  849. }
  850.  
  851. /*******************************************/
  852.  
  853. /* Process configuration ACK send by remote host */
  854. static int
  855. ipcp_chkack(sp, ackcnf, data)
  856. struct slip *sp;
  857. struct cnfhdr *ackcnf;
  858. struct mbuf *data;
  859. {
  860.     int ackerr = 0;
  861.     struct pppctl *pppiop;
  862.     struct ipcpctl *ipcpiop;
  863.     struct mbuf *req_bp;
  864.     struct opthdr reqopt;
  865.     struct opthdr ackopt;
  866.     int16 reqi16, acki16;
  867.     int32 reqsrc_ip, reqdest_ip, acksrc_ip, ackdest_ip;
  868.  
  869.     if (Ppptrace > 5)
  870.         log(-1,"ipcp_chkack()");
  871.  
  872.     pppiop = sp->pppio;
  873.     ipcpiop = &(pppiop->ipcpio);
  874.  
  875.     /* IPCP ID field must match last request we sent */
  876.     if (ackcnf->id != ipcpiop->lastid) {
  877.         if (Ppptrace > 1)
  878.             log(-1,"improper IPCP ACK; bad ID");
  879.         free_p(data);
  880.         return -1;
  881.     }
  882.  
  883.     /* Get a copy of last request we sent */
  884.     req_bp = ipcp_makereq(ipcpiop);
  885.  
  886.     /* Overall buffer length should match */
  887.     if (ackcnf->len != len_p(req_bp)) {
  888.         ackerr = 1;
  889.     }
  890.  
  891.     /* ACK must echo all options we requested in the order requested */
  892.     while ((ntohopt(&reqopt, &req_bp) != -1) && (!ackerr)) {
  893.         /* Get config option from ACK packet */
  894.         if (ntohopt(&ackopt, &data) == -1) {
  895.             /* Must have as many acked options as requested */
  896.             ackerr = 1;
  897.             break;
  898.         }
  899.  
  900.         /* Config option headers must match */
  901.         if ((ackopt.type != reqopt.type)
  902.            ||(ackopt.len != reqopt.len)) {
  903.             ackerr = 1;
  904.             break;
  905.         }
  906.  
  907.         /* Config option values must match */
  908.         switch(reqopt.type) {
  909.         case IP_ADDRS:        /* IP address */
  910.             /* Echoed values must match our request */
  911.             reqsrc_ip = pull32(&req_bp);
  912.             reqdest_ip = pull32(&req_bp);
  913.             acksrc_ip = pull32(&data);
  914.             ackdest_ip = pull32(&data);
  915.  
  916.             if (acksrc_ip != reqsrc_ip) {
  917.                 ackerr = 1;
  918.                 break;
  919.             }
  920.             if (ackdest_ip != reqdest_ip) {
  921.                 ackerr = 1;
  922.                 break;
  923.             }
  924.             break;
  925.  
  926.         case IP_COMPR_TYPE:    /* IP header compr */
  927.             /* Echoed values must match our request */
  928.             reqi16 = pull16(&req_bp);
  929.             acki16 = pull16(&data);
  930.  
  931.             if (reqi16 != acki16) {
  932.                 ackerr = 1;
  933.                 break;
  934.             }
  935.             break;
  936.         default:        /* Shouldnt happen */
  937.             ackerr = 1;
  938.             break;
  939.         }
  940.     }
  941.  
  942.     free_p(req_bp);
  943.     free_p(data);
  944.  
  945.     if (ackerr) {
  946.         /* Error in configuration ACK */
  947.         if (Ppptrace > 5)
  948.             log(-1,"improper IPCP ACK echo");
  949.         return -1;
  950.     }
  951.  
  952.     /* ACK matches last request we made */
  953.     if (Ppptrace > 5)
  954.         log(-1,"valid IPCP ACK echo");
  955.     return 0;
  956. }
  957.  
  958. /* Process configuration NAK send by remote host */
  959. static int
  960. ipcp_chknak(sp, nakcnf, data)
  961. struct slip *sp;
  962. struct cnfhdr *nakcnf;
  963. struct mbuf *data;
  964. {
  965.     int nakerr = 0;
  966.     struct pppctl *pppiop;
  967.     struct ipcpctl *ipcpiop;
  968.     struct mbuf *req_bp;
  969.     struct opthdr reqopt;
  970.     struct opthdr nakopt;
  971.     int16 naki16;
  972.     int32 naksrc_ip, nakdest_ip;
  973.  
  974.     if (Ppptrace > 5)
  975.         log(-1,"ipcp_chknak()");
  976.  
  977.     pppiop = sp->pppio;
  978.     ipcpiop = &(pppiop->ipcpio);
  979.  
  980.     /* IPCP ID field must match last request we sent */
  981.     if (nakcnf->id != ipcpiop->lastid) {
  982.         if (Ppptrace > 1)
  983.             log(-1,"improper IPCP NAK; bad ID");
  984.         free_p(data);
  985.         return -1;
  986.     }
  987.  
  988.     /* Get a copy of last request we sent */
  989.     req_bp = ipcp_makereq(ipcpiop);
  990.  
  991.     /* Check overall buffer length */
  992.     if (nakcnf->len > len_p(req_bp)) {
  993.         /* Remote cant NAK more options than we requested */
  994.         nakerr = 1;
  995.     }
  996.  
  997.     /* NAKed options must be same order as our original request */
  998.     while ((ntohopt(&nakopt, &data) != -1) && (!nakerr)) {
  999.         /* Get config option from our request */
  1000.         if (ntohopt(&reqopt, &req_bp) == -1) {
  1001.             /* Must find match to each NAKed option */
  1002.             nakerr = 1;
  1003.             break;
  1004.         }
  1005.  
  1006.         /* Maybe not all options were NAKed; look */
  1007.         /* for matching option in our request     */
  1008.         while (reqopt.type != nakopt.type) {
  1009.             /* This option not NAKed; eat rest   */
  1010.             /* of option from the request packet */
  1011.             reqopt.len -= 2;
  1012.             while (reqopt.len--)
  1013.                 pullchar(&req_bp);
  1014.  
  1015.             /* Get next config option from our request */
  1016.             if (ntohopt(&reqopt, &req_bp) == -1) {
  1017.                 /* Must find match to each NAKed option */
  1018.                 reqopt.type = 0;
  1019.                 nakerr = 1;
  1020.                 break;
  1021.             }
  1022.         }
  1023.  
  1024.         /* Config option headers must match */
  1025.         if ((nakopt.type != reqopt.type)
  1026.            ||(nakopt.len != reqopt.len)) {
  1027.             nakerr = 1;
  1028.             break;
  1029.         }
  1030.  
  1031.         /* Remote host replaced our request with new suggestion */
  1032.         switch(reqopt.type) {
  1033.         case IP_ADDRS:        /* IP address */
  1034.             /* Get replacement value from NAK packet */
  1035.             naksrc_ip = pull32(&data);
  1036.             nakdest_ip = pull32(&data);
  1037.             /* Eat option value from our request packet */
  1038.             pull32(&req_bp);
  1039.             pull32(&req_bp);
  1040.  
  1041.             /* Ignore remote if we want to control addrs */
  1042.             if (ipcpiop->accept_addrs != 0) {
  1043.                 /* We asked remote for our addresses */
  1044.                 if (ipcpiop->attempt_src == 0L)
  1045.                     ipcpiop->attempt_src = naksrc_ip;
  1046.                 if (ipcpiop->attempt_dest == 0L)
  1047.                     ipcpiop->attempt_dest = nakdest_ip;
  1048.             }
  1049.             break;
  1050.         case IP_COMPR_TYPE:    /* IP header compr */
  1051.             /* Get replacement value from NAK packet */
  1052.             naki16 = pull16(&data);
  1053.             /* Eat option value from our request packet */
  1054.             pull16(&req_bp);
  1055.  
  1056.             /* See if we can do this type of IP compression */
  1057.             if (naki16 == IPCP_VJCOMPR) {
  1058.                 /* Ask for Van Jacobson TCP compression */
  1059.                 ipcpiop->lcl_ip_compr = IPCP_VJCOMPR;
  1060.             } else {
  1061.                 /* Cant do that type of compr, ask for none */
  1062.                 ipcpiop->lcl_ip_compr = DEF_IP_COMPR;
  1063.             }
  1064.             break;
  1065.         default:        /* Shouldnt happen */
  1066.             nakerr = 1;
  1067.             break;
  1068.         }
  1069.     }
  1070.  
  1071.     free_p(req_bp);
  1072.     free_p(data);
  1073.  
  1074.     if (nakerr) {
  1075.         /* Error in configuration NAK */
  1076.         if (Ppptrace > 5)
  1077.             log(-1,"improper IPCP NAK echo");
  1078.         return -1;
  1079.     }
  1080.  
  1081.     /* NAK matches last request we made */
  1082.     if (Ppptrace > 5)
  1083.         log(-1,"valid IPCP NAK echo");
  1084.     return 0;
  1085. }
  1086.  
  1087. /* Process configuration reject send by remote host */
  1088. static int
  1089. ipcp_chkrej(sp, rejcnf, data)
  1090. struct slip *sp;
  1091. struct cnfhdr *rejcnf;
  1092. struct mbuf *data;
  1093. {
  1094.     int rejerr = 0;
  1095.     struct pppctl *pppiop;
  1096.     struct ipcpctl *ipcpiop;
  1097.     struct mbuf *req_bp;
  1098.     struct opthdr reqopt;
  1099.     struct opthdr rejopt;
  1100.  
  1101.     if (Ppptrace > 5)
  1102.         log(-1,"ipcp_chkrej()");
  1103.  
  1104.     pppiop = sp->pppio;
  1105.     ipcpiop = &(pppiop->ipcpio);
  1106.  
  1107.     /* IPCP ID field must match last request we sent */
  1108.     if (rejcnf->id != ipcpiop->lastid) {
  1109.         if (Ppptrace > 1)
  1110.             log(-1,"improper IPCP REJ; bad ID");
  1111.         free_p(data);
  1112.         return -1;
  1113.     }
  1114.  
  1115.     /* Get a copy of last request we sent */
  1116.     req_bp = ipcp_makereq(ipcpiop);
  1117.  
  1118.     /* Check overall buffer length */
  1119.     if (rejcnf->len > len_p(req_bp)) {
  1120.         /* Remote cant NAK more options than we requested */
  1121.         rejerr = 1;
  1122.     }
  1123.  
  1124.     /* Rejected options must be same order as our original request */
  1125.     while ((ntohopt(&rejopt, &data) != -1) && (!rejerr)) {
  1126.         /* Get config option from our request */
  1127.         if (ntohopt(&reqopt, &req_bp) == -1) {
  1128.             /* Must find match to each NAKed option */
  1129.             rejerr = 1;
  1130.             break;
  1131.         }
  1132.  
  1133.         /* Maybe not all options were NAKed; look */
  1134.         /* for matching option in our request     */
  1135.         while (reqopt.type != rejopt.type) {
  1136.             /* This option not NAKed; eat rest   */
  1137.             /* of option from the request packet */
  1138.             reqopt.len -= 2;
  1139.             while (reqopt.len--)
  1140.                 pullchar(&req_bp);
  1141.  
  1142.             /* Get next config option from our request */
  1143.             if (ntohopt(&reqopt, &req_bp) == -1) {
  1144.                 /* Must find match to each NAKed option */
  1145.                 reqopt.type = 0;
  1146.                 rejerr = 1;
  1147.                 break;
  1148.             }
  1149.         }
  1150.  
  1151.         /* Config option headers must match */
  1152.         if ((rejopt.type != reqopt.type)
  1153.            ||(rejopt.len != reqopt.len)) {
  1154.             rejerr = 1;
  1155.             break;
  1156.         }
  1157.  
  1158.         /* Remote host wont negotiate this option */
  1159.         switch(reqopt.type) {
  1160.         case IP_ADDRS:        /* IP address */
  1161.             /* Eat option values from each packet */
  1162.             pull32(&req_bp);
  1163.             pull32(&req_bp);
  1164.             pull32(&data);
  1165.             pull32(&data);
  1166.  
  1167.             /* Abandon attempt to negotiate IP addrs */
  1168.             ipcpiop->attempt_addrs = 0;
  1169.             break;
  1170.         case IP_COMPR_TYPE:    /* IP header compression */
  1171.             /* Eat option values from each packet */
  1172.             pull16(&req_bp);
  1173.             pull16(&data);
  1174.  
  1175.             /* Abandon attempt to negotiate IP compression */
  1176.             ipcpiop->attempt_ip_compr = 0;
  1177.             ipcpiop->lcl_ip_compr = DEF_IP_COMPR;
  1178.             break;
  1179.         default:        /* Shouldnt happen */
  1180.             rejerr = 1;
  1181.             break;
  1182.         }
  1183.     }
  1184.  
  1185.     free_p(req_bp);
  1186.     free_p(data);
  1187.  
  1188.     if (rejerr) {
  1189.         /* Error in configuration reject */
  1190.         if (Ppptrace > 5)
  1191.             log(-1,"improper IPCP REJ echo");
  1192.         return -1;
  1193.     }
  1194.  
  1195.     /* Reject matches last request we made */
  1196.     if (Ppptrace > 5)
  1197.         log(-1,"valid IPCP REJ echo");
  1198.     return 0;
  1199. }
  1200.  
  1201. /* Check IP Control options requested by the remote host */
  1202. static void
  1203. ipcp_chkreq(sp, reqcnf, data)
  1204. struct slip *sp;
  1205. struct cnfhdr *reqcnf;
  1206. struct mbuf *data;
  1207. {
  1208.     struct pppctl *pppiop;
  1209.     struct ipcpctl *ipcpiop;
  1210.     int ilen;
  1211.     int16 i16;
  1212.     int32 reqsrc_ip, reqdest_ip;
  1213.     register char *cp;
  1214.     char cnf_accept = CONFIG_ACK;        /* Overall reply to request */
  1215.     char opt_accept;            /* Per option reply */
  1216.     struct opthdr reqopt;            /* Per option header storage */
  1217.     struct opthdr replyopt;            /* For building reply */
  1218.     struct mbuf *bp;            /* Ptr for building reply */
  1219.     struct mbuf *reply_bp = NULLBUF;    /* Actual reply packet */
  1220.  
  1221.     if (Ppptrace > 5)
  1222.         log(-1, "ipcp_chkreq()");
  1223.  
  1224.     pppiop = sp->pppio;
  1225.     ipcpiop = &(pppiop->ipcpio);
  1226.  
  1227.     /* Make sure length in IPCP config header is realistic */
  1228.     ilen = len_p(data);
  1229.     if (ilen < reqcnf->len)
  1230.         reqcnf->len = ilen;
  1231.  
  1232.     /* Process options requested by remote host */
  1233.     while (reqcnf->len > 0) {
  1234.         /* Get header for next option */
  1235.         if (ntohopt(&reqopt, &data) == -1)
  1236.             break;
  1237.  
  1238.         reqcnf->len -= reqopt.len;    /* Count bytes this option */
  1239.         reqopt.len -= 2;        /* Get data len this option */
  1240.         opt_accept = CONFIG_ACK;    /* Assume will accept option */
  1241.  
  1242.         switch(reqopt.type) {
  1243.         case IP_ADDRS:        /* IP address */
  1244.             if (Ppptrace > 5)
  1245.                 log(-1, "remote asking to negotiate IP addrs");
  1246.  
  1247.             /* IP Addr is 2 32bit fields */
  1248.             ilen = 8;
  1249.             if (reqopt.len < ilen) {
  1250.                 /* Short option data; reject packet */
  1251.                 opt_accept = CONFIG_REJ;
  1252.                 break;
  1253.             }
  1254.  
  1255.             /* Get proposed value from packet */
  1256.             reqsrc_ip = pull32(&data);
  1257.             reqdest_ip = pull32(&data);
  1258.             if (Ppptrace > 5) {
  1259.                 log(-1,    "src IP addr: %s",
  1260.                     inet_ntoa(reqsrc_ip));
  1261.                 log(-1,    "dest IP addr: %s",
  1262.                     inet_ntoa(reqdest_ip));
  1263.  
  1264.             }
  1265.  
  1266.             /* Check requested IP addresses */
  1267.             if (ipcpiop->accept_addrs == 0) {
  1268.                 /* Request okay if it matches what we want */
  1269.                 if ((reqsrc_ip == ipcpiop->attempt_dest)
  1270.                     && (reqdest_ip == ipcpiop->attempt_src)) {
  1271.                     opt_accept = CONFIG_ACK;    
  1272.                     /* Save these values for later */
  1273.                     ipcpiop->accept_src = reqsrc_ip;
  1274.                     ipcpiop->accept_dest = reqdest_ip;
  1275.                     break;
  1276.                 }
  1277.                 if ((reqsrc_ip == ipcpiop->accept_src)
  1278.                     && (reqdest_ip == ipcpiop->accept_dest)) {
  1279.                     /* We already NAKed these once */
  1280.                     opt_accept = CONFIG_REJ;
  1281.                     break;
  1282.                 }
  1283.  
  1284.                 /* Cant accept suggestion of remote host */
  1285.                 opt_accept = CONFIG_NAK;
  1286.                 /* Save these values in case remote insists */
  1287.                 ipcpiop->accept_src = reqsrc_ip;
  1288.                 ipcpiop->accept_dest = reqdest_ip;
  1289.                 /* Tell remote what to request instead */
  1290.                 reqsrc_ip = ipcpiop->attempt_dest;
  1291.                 reqdest_ip = ipcpiop->attempt_src;
  1292.                 break;
  1293.             }
  1294.  
  1295.             /* Make sure remote is not repeating itself */
  1296.             if ((reqsrc_ip == ipcpiop->accept_src)
  1297.                 && (reqdest_ip == ipcpiop->accept_dest)) {
  1298.                 /* We already NAKed these once */
  1299.                 opt_accept = CONFIG_REJ;
  1300.                 break;
  1301.             }
  1302.  
  1303.             /* Save these values for later */
  1304.             ipcpiop->accept_src = reqsrc_ip;
  1305.             ipcpiop->accept_dest = reqdest_ip;
  1306.             /* Remote host may request IP addrs */
  1307.             if(reqsrc_ip == 0L) {
  1308.                 /* Remote host request its IP addr */
  1309.                 if (ipcpiop->attempt_dest == 0L) {
  1310.                     /* We dont have an addr for remote */
  1311.                     opt_accept = CONFIG_REJ;
  1312.                     break;
  1313.                 } else {
  1314.                     /* Give IP addr to remote peer */
  1315.                     opt_accept = CONFIG_NAK;
  1316.                     reqsrc_ip = ipcpiop->attempt_dest;
  1317.                 }
  1318.             } else {
  1319.                 /* Remote host gave us its IP addr */
  1320.                 if (ipcpiop->attempt_dest == 0L) {
  1321.                     /* We need to know peer IP addr */
  1322.                     ipcpiop->attempt_dest = reqsrc_ip;
  1323.                 } else {
  1324.                     /* We already know peer IP addr */
  1325.                     if (reqsrc_ip != ipcpiop->attempt_dest) {
  1326.                         opt_accept = CONFIG_NAK;
  1327.                         reqsrc_ip = ipcpiop->attempt_dest;
  1328.                     }
  1329.                 }
  1330.             }
  1331.             if (reqdest_ip == 0L) {
  1332.                 /* Remote host requested our IP addr */
  1333.                 if (ipcpiop->attempt_src == 0L) {
  1334.                     /* We dont know our IP addr */
  1335.                     opt_accept = CONFIG_REJ;
  1336.                     break;
  1337.                 } else {
  1338.                     /* Tell remote what our IP addr is */
  1339.                     opt_accept = CONFIG_NAK;
  1340.                     reqdest_ip = ipcpiop->attempt_src;
  1341.                 }
  1342.             } else {
  1343.                 /* Remote host gave us our IP addr */
  1344.                 if (ipcpiop->attempt_src == 0L) {
  1345.                     /* We need to know our IP addr */
  1346.                     ipcpiop->attempt_src = reqdest_ip;
  1347.                 } else {
  1348.                     /* We already know our IP addr */
  1349.                     if (reqdest_ip != ipcpiop->attempt_src) {
  1350.                         opt_accept = CONFIG_NAK;
  1351.                         reqdest_ip = ipcpiop->attempt_src;
  1352.                     }
  1353.                 }
  1354.             }
  1355.             break;
  1356.  
  1357.         case IP_COMPR_TYPE:    /* IP header compression */
  1358.             if (Ppptrace > 5) {
  1359.                 log(-1, "remote asking to negotiate IP compression");
  1360.             }
  1361.  
  1362.             /* IP compression type is a 16 bit field */
  1363.             ilen = 2;
  1364.             if (reqopt.len < ilen) {
  1365.                 /* Short option; reject packet */
  1366.                 opt_accept = CONFIG_REJ;
  1367.                 break;
  1368.             }
  1369.  
  1370.             /* Get proposed value from packet */
  1371.             i16 = pull16(&data);
  1372.             if ((ipcpiop->accept_ip_compr == 0)
  1373.                 && (i16 != DEF_IP_COMPR)) {
  1374.                 /* Not open for negotiation */
  1375.                 opt_accept = CONFIG_REJ;
  1376.                 break;
  1377.             }
  1378.  
  1379.             /* Check if requested compr type is acceptable */
  1380.             if (i16 == IPCP_VJCOMPR) {
  1381.                 /* We can do Van Jacobson TCP header compr */
  1382.                 opt_accept = CONFIG_ACK;
  1383.             } else {
  1384.                 /* Dont know this compr type;
  1385.                  * suggest Van Jacobson TCP header compr
  1386.                  */
  1387.                 opt_accept = CONFIG_NAK;
  1388.                 i16 = IPCP_VJCOMPR;
  1389.             }
  1390.             ipcpiop->rem_ip_compr = i16;
  1391.             break;
  1392.  
  1393.         default:        /* Unknown option */
  1394.             if (Ppptrace > 5)
  1395.                 log(-1,    "remote asking for unimplemented option: %x   len: %d",
  1396.                     reqopt.type, reqopt.len);
  1397.             opt_accept = CONFIG_REJ;
  1398.             ilen = reqopt.len;
  1399.             if (len_p(data) < ilen)
  1400.                 ilen = len_p(data);
  1401.             /* Data dequeued at echo time */
  1402.  
  1403.             break;
  1404.         }
  1405.         if ((opt_accept == CONFIG_ACK) &&
  1406.             (cnf_accept != CONFIG_ACK))
  1407.             /* This option was good, but a previous      */
  1408.             /* option was not. Return only those options */
  1409.             /* which are being nacked/rejected.          */
  1410.             continue;
  1411.  
  1412.         if (opt_accept == CONFIG_NAK) {
  1413.             if (cnf_accept == CONFIG_REJ)
  1414.                 /* Return only those options */
  1415.                 /* which are being rejected. */
  1416.                 continue;
  1417.             if (cnf_accept == CONFIG_ACK) {
  1418.                 /* Discard current list of good options */
  1419.                 free_p(reply_bp);
  1420.                 reply_bp = NULLBUF;
  1421.                 /* Send a list of nacked options */
  1422.                 cnf_accept = CONFIG_NAK;
  1423.             }
  1424.         }
  1425.  
  1426.         if (opt_accept == CONFIG_REJ) {
  1427.             if (cnf_accept != CONFIG_REJ) {
  1428.                 /* Discard current list of good options */
  1429.                 free_p(reply_bp);
  1430.                 reply_bp = NULLBUF;
  1431.                 /* Send a list of rejected options */
  1432.                 cnf_accept = CONFIG_REJ;
  1433.             }
  1434.         }
  1435.  
  1436.         /* Add option response to the return list */
  1437.         replyopt.type = reqopt.type;
  1438.         replyopt.len = ilen + OPT_HDRLEN;
  1439.         if ((bp = htonopt(&replyopt)) == NULLBUF)
  1440.             break;
  1441.         append(&reply_bp,bp);
  1442.         if (ilen) {
  1443.             if ((bp = alloc_mbuf(ilen)) == NULLBUF)
  1444.                 break;
  1445.             cp = bp->data;
  1446.             switch(ilen) {
  1447.             case 2:
  1448.                 put16(cp,i16);
  1449.                 bp->cnt += 2;
  1450.                 break;
  1451.             case 8:
  1452.                 cp = put32(cp, reqsrc_ip);
  1453.                 cp = put32(cp, reqdest_ip);
  1454.                 bp->cnt += 8;
  1455.                 break;
  1456.             default:
  1457.                 while (ilen--)
  1458.                     bp->data[bp->cnt++] = pullchar(&data);
  1459.             }
  1460.             append(&reply_bp,bp);
  1461.         }
  1462.     }
  1463.  
  1464.     /* Send ACK/NAK/REJ to remote host */
  1465.     if (cnf_accept == CONFIG_ACK) {
  1466.         if (Ppptrace > 1)
  1467.             log(-1, "accept all options requested by remote peer");
  1468.  
  1469.         /* Accept configuration requested by remote host */
  1470.         ipcp_sendreply(sp, CONFIG_ACK, reqcnf->id, reply_bp);
  1471.         if (ipcpiop->ipcp_state == IPCP_REQ_SENT) {
  1472.             ipcpiop->ipcp_state = IPCP_ACK_SENT;
  1473.         } else {
  1474.             /* PPP data link now ready for IP traffic */
  1475.             ipcp_open(sp);
  1476.         }
  1477.     } else {
  1478.         if (Ppptrace > 1)
  1479.             log(-1,"options requested by remote peer not accepted: %s",
  1480.                 ((cnf_accept==CONFIG_NAK) ? "NAK" : "REJ"));
  1481.  
  1482.         /* NAK/REJ config request made by remote host */
  1483.         ipcp_sendreply(sp, cnf_accept, reqcnf->id, reply_bp);
  1484.  
  1485.         /* Start timer against wait for amended config request */
  1486.         if (ipcpiop->ipcp_state == IPCP_ACK_RCVD)
  1487.             ipcp_timer(sp);
  1488.     }
  1489.     free_p(data);
  1490. }
  1491.  
  1492. /****************************************************************************/
  1493.  
  1494. /* Timeout while waiting for reply from remote host */
  1495. static void
  1496. ipcp_timeout(vp)
  1497. void *vp;
  1498. {
  1499.     struct slip *sp;
  1500.     struct pppctl *pppiop;
  1501.     struct ipcpctl *ipcpiop;
  1502.  
  1503.     if (Ppptrace > 1)
  1504.         log(-1, "ipcp_timeout()");
  1505.  
  1506.     /* Load pointers to interface that timed-out */
  1507.     sp = (struct slip *)vp;
  1508.     pppiop = sp->pppio;
  1509.     ipcpiop = &(pppiop->ipcpio);
  1510.  
  1511.     /* Attempt to get things going again */
  1512.     switch(ipcpiop->ipcp_state) {
  1513.     case IPCP_ACK_SENT:
  1514.         /* Remote host isnt listening to our request */
  1515.         ipcp_reset(sp);
  1516.     case IPCP_REQ_SENT:
  1517.     case IPCP_ACK_RCVD:
  1518.         if (!ipcpiop->active) {
  1519.             /* If passive open, we got a CONFIG_REQ from remote */
  1520.             /* host but no ACK in response to our CONFIG_REQ    */
  1521.             if (++ipcpiop->ack_retry > IPCP_RETRY_MAX) {
  1522.                 /* Remote host doesnt seem to be listening */
  1523.                 ipcp_shutdown(sp);
  1524.                 break;
  1525.             }
  1526.         }
  1527.         /* Timeout waiting for ACK to our request,         */
  1528.         /* or timeout waiting for request from remote host */
  1529.         ipcp_sendreq(sp);
  1530.         break;
  1531.  
  1532.     case IPCP_TERMINATE:
  1533.         /* Timeout waiting for terminate ACK; send another request */
  1534.         if (++ipcpiop->ack_retry > IPCP_TERM_RETRY) {
  1535.             /* No response to our polite request; give it up */
  1536.             if (Ppptrace)
  1537.                 log(-1,"%s: PPP/IPCP IP Closed without reply from remote peer",sp->iface->name);
  1538.             if (ipcpiop->active)
  1539.                 ipcpiop->ipcp_state = IPCP_CLOSED;
  1540.             else
  1541.                 ipcpiop->ipcp_state = IPCP_LISTEN;
  1542.  
  1543.             ipcp_sendreply(sp,TERMINATE_ACK,0,NULLBUF);
  1544.             ipcp_reset(sp);
  1545.             tprintf("Still no response; marking IPCP layer as closed\n");
  1546.             psignal(ipcpiop,0);
  1547.         } else {
  1548.             /* Request remote host to close IP */
  1549.             tprintf("Timeout waiting for response to our IPCP terminate request\n");
  1550.             ipcp_timer(sp);
  1551.             ipcp_sendreply(sp, TERMINATE_REQ, 0, NULLBUF);
  1552.         }
  1553.         break;
  1554.  
  1555.     case IPCP_CLOSED:
  1556.     case IPCP_LISTEN:
  1557.     case IPCP_OPEN:
  1558.     default:
  1559.         /* Confusion; shutdown the connection */
  1560.         ipcp_shutdown(sp);
  1561.         break;
  1562.     }
  1563. }
  1564.  
  1565. /* Set a timer in case an expected event does not occur */
  1566. static void
  1567. ipcp_timer(sp)
  1568. struct slip *sp;
  1569. {
  1570.     struct pppctl *pppiop;
  1571.     struct ipcpctl *ipcpiop;
  1572.     struct timer *t;
  1573.  
  1574.     if (Ppptrace > 5)
  1575.         log(-1,"ipcp_timer()");
  1576.  
  1577.     pppiop = sp->pppio;
  1578.     ipcpiop = &(pppiop->ipcpio);
  1579.     t = &(ipcpiop->ipcp_tm);
  1580.     t->func = (void (*)())ipcp_timeout;
  1581.     t->arg = (void *)sp;
  1582.     start_timer(t);
  1583. }
  1584.  
  1585. /****************************************************************************/
  1586.  
  1587. /* Send an IPCP packet to the remote host */
  1588. static int
  1589. ipcp_sendreply(sp,code,id,data)
  1590. struct slip *sp;
  1591. char code;
  1592. unsigned char id;
  1593. struct mbuf *data;
  1594. {
  1595.     struct iface *iface;
  1596.     struct cnfhdr hdr;
  1597.  
  1598.     /* Load IPCP header values */
  1599.     hdr.code = code;
  1600.     switch(code) {
  1601.     case CONFIG_REQ:
  1602.     case TERMINATE_REQ:
  1603.         /* Save ID field for match aginst replies from remote host */
  1604.         sp->pppio->ipcpio.lastid = Pppid;
  1605.         /* Use a unique ID field value */
  1606.         hdr.id = Pppid++;
  1607.         break;
  1608.  
  1609.     case CONFIG_ACK:
  1610.     case CONFIG_NAK:
  1611.     case CONFIG_REJ:
  1612.     case TERMINATE_ACK:
  1613.     case CODE_REJ:
  1614.         /* Use ID sent by remote host */
  1615.         hdr.id = id;
  1616.         break;
  1617.  
  1618.     default:
  1619.         /* Shouldnt happen */
  1620.         if (Ppptrace)
  1621.             log(-1, "bogus code: %x\n", code);
  1622.         return -1;
  1623.     }
  1624.     hdr.len = len_p(data) + CNF_HDRLEN;
  1625.  
  1626.     /* Prepend IPCP header to packet data */
  1627.     if ((data = htoncnf(&hdr,data)) == NULLBUF)
  1628.         return -1;
  1629.  
  1630.     if (Ppptrace > 1)
  1631.         log(-1, "%s: PPP/IPCP Send: current state: %s   IPCP option: %s  id: %d  len: %d",
  1632.             sp->iface->name,
  1633.             LCPStates[sp->pppio->ipcpio.ipcp_state],
  1634.             LCPCodes[code],hdr.id,hdr.len);
  1635.  
  1636.     /* Send IPCP packet to remote host */
  1637.     sp->pppio->sndipcp++;
  1638.     iface = sp->iface;
  1639.     return( (*iface->output)
  1640.         (iface, NULLCHAR, NULLCHAR, PPP_IPCP_TYPE, data) );
  1641. }
  1642.  
  1643. /* Process incoming IPCP packet */
  1644. void
  1645. ipcpproc(iface,bp)
  1646. struct iface *iface;
  1647. struct mbuf *bp;
  1648. {
  1649.     struct slip *sp;
  1650.     struct cnfhdr hdr;
  1651.  
  1652.     sp = &Slip[iface->xdev];
  1653.  
  1654.     /* Extract IPCP header */
  1655.     ntohcnf(&hdr, &bp);
  1656.     hdr.len -= CNF_HDRLEN;            /* Length includes envelope */
  1657.     trim_mbuf(&bp, hdr.len);        /* Trim off FCS bytes */
  1658.  
  1659.     if (Ppptrace > 1)
  1660.         log(-1,    "%s: PPP/IPCP Recv: current state: %s   IPCP option: %s    id: %d   len: %d",
  1661.             iface->name,
  1662.             LCPStates[sp->pppio->ipcpio.ipcp_state],
  1663.             LCPCodes[hdr.code], hdr.id, hdr.len);
  1664.  
  1665.     /* Process IPCP packet data */
  1666.     switch(hdr.code) {
  1667.     case CONFIG_REQ:            /* Request of remote host */
  1668.         ipcp_rcvreq(sp, &hdr, bp);
  1669.         break;
  1670.     case CONFIG_ACK:            /* Remote accepted our req */
  1671.         ipcp_rcvack(sp, &hdr, bp);
  1672.         break;
  1673.     case CONFIG_NAK:            /* Remote adjusted our req */
  1674.         ipcp_rcvnak(sp, &hdr, bp);
  1675.         break;
  1676.     case CONFIG_REJ:            /* Remote rejected our req */
  1677.         ipcp_rcvrej(sp, &hdr, bp);
  1678.         break;
  1679.     case TERMINATE_REQ:            /* Remote request to close */
  1680.         ipcp_rcvtermreq(sp, &hdr);
  1681.         break;
  1682.     case TERMINATE_ACK:            /* Remote closed on request */
  1683.         ipcp_rcvtermack(sp);
  1684.         break;
  1685.  
  1686.     case CODE_REJ:
  1687.         if (Ppptrace)
  1688.             log(-1,"Unimplemented IPCP packet type: %x; dropping packet",hdr.code);
  1689.         free_p(bp);
  1690.         break;
  1691.     default:
  1692.         if (Ppptrace)
  1693.             log(-1,"Unknown IPCP packet type: %x; dropping packet",hdr.code);
  1694.         free_p(bp);
  1695.         break;
  1696.     }
  1697. }
  1698.