Home | History | Annotate | Download | only in src
      1 /*-
      2  * Copyright (c) 1998 Brian Somers <brian (at) Awfulhak.org>
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  *
     14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     24  * SUCH DAMAGE.
     25  *
     26  * $FreeBSD: src/usr.sbin/ppp/cbcp.c,v 1.26.26.1 2010/12/21 17:10:29 kensmith Exp $
     27  */
     28 
     29 #include <sys/param.h>
     30 
     31 #ifdef __FreeBSD__
     32 #include <netinet/in.h>
     33 #endif
     34 #include <sys/un.h>
     35 
     36 #include <string.h>
     37 #include <termios.h>
     38 
     39 #include "layer.h"
     40 #include "defs.h"
     41 #include "log.h"
     42 #include "timer.h"
     43 #include "descriptor.h"
     44 #include "lqr.h"
     45 #include "mbuf.h"
     46 #include "fsm.h"
     47 #include "throughput.h"
     48 #include "hdlc.h"
     49 #include "lcp.h"
     50 #include "ccp.h"
     51 #include "link.h"
     52 #include "async.h"
     53 #include "physical.h"
     54 #include "proto.h"
     55 #include "cbcp.h"
     56 #include "mp.h"
     57 #include "chat.h"
     58 #include "auth.h"
     59 #include "chap.h"
     60 #include "datalink.h"
     61 
     62 void
     63 cbcp_Init(struct cbcp *cbcp, struct physical *p)
     64 {
     65   cbcp->required = 0;
     66   cbcp->fsm.state = CBCP_CLOSED;
     67   cbcp->fsm.id = 0;
     68   cbcp->fsm.delay = 0;
     69   *cbcp->fsm.phone = '\0';
     70   memset(&cbcp->fsm.timer, '\0', sizeof cbcp->fsm.timer);
     71   cbcp->p = p;
     72 }
     73 
     74 static void cbcp_SendReq(struct cbcp *);
     75 static void cbcp_SendResponse(struct cbcp *);
     76 static void cbcp_SendAck(struct cbcp *);
     77 
     78 static void
     79 cbcp_Timeout(void *v)
     80 {
     81   struct cbcp *cbcp = (struct cbcp *)v;
     82 
     83   timer_Stop(&cbcp->fsm.timer);
     84   if (cbcp->fsm.restart) {
     85     switch (cbcp->fsm.state) {
     86       case CBCP_CLOSED:
     87       case CBCP_STOPPED:
     88         log_Printf(LogCBCP, "%s: Urk - unexpected CBCP timeout !\n",
     89                    cbcp->p->dl->name);
     90         break;
     91 
     92       case CBCP_REQSENT:
     93         cbcp_SendReq(cbcp);
     94         break;
     95       case CBCP_RESPSENT:
     96         cbcp_SendResponse(cbcp);
     97         break;
     98       case CBCP_ACKSENT:
     99         cbcp_SendAck(cbcp);
    100         break;
    101     }
    102   } else {
    103     const char *missed;
    104 
    105     switch (cbcp->fsm.state) {
    106       case CBCP_STOPPED:
    107         missed = "REQ";
    108         break;
    109       case CBCP_REQSENT:
    110         missed = "RESPONSE";
    111         break;
    112       case CBCP_RESPSENT:
    113         missed = "ACK";
    114         break;
    115       case CBCP_ACKSENT:
    116         missed = "Terminate REQ";
    117         break;
    118       default:
    119         log_Printf(LogCBCP, "%s: Urk - unexpected CBCP timeout !\n",
    120                    cbcp->p->dl->name);
    121         missed = NULL;
    122         break;
    123     }
    124     if (missed)
    125       log_Printf(LogCBCP, "%s: Timeout waiting for peer %s\n",
    126                  cbcp->p->dl->name, missed);
    127     datalink_CBCPFailed(cbcp->p->dl);
    128   }
    129 }
    130 
    131 static void
    132 cbcp_StartTimer(struct cbcp *cbcp, int timeout)
    133 {
    134   timer_Stop(&cbcp->fsm.timer);
    135   cbcp->fsm.timer.func = cbcp_Timeout;
    136   cbcp->fsm.timer.name = "cbcp";
    137   cbcp->fsm.timer.load = timeout * SECTICKS;
    138   cbcp->fsm.timer.arg = cbcp;
    139   timer_Start(&cbcp->fsm.timer);
    140 }
    141 
    142 #define CBCP_CLOSED	(0)	/* Not in use */
    143 #define CBCP_STOPPED	(1)	/* Waiting for a REQ */
    144 #define CBCP_REQSENT	(2)	/* Waiting for a RESP */
    145 #define CBCP_RESPSENT	(3)	/* Waiting for an ACK */
    146 #define CBCP_ACKSENT	(4)	/* Waiting for an LCP Term REQ */
    147 
    148 static const char * const cbcpname[] = {
    149   "closed", "stopped", "req-sent", "resp-sent", "ack-sent"
    150 };
    151 
    152 static const char *
    153 cbcpstate(unsigned s)
    154 {
    155   if (s < sizeof cbcpname / sizeof cbcpname[0])
    156     return cbcpname[s];
    157   return HexStr(s, NULL, 0);
    158 }
    159 
    160 static void
    161 cbcp_NewPhase(struct cbcp *cbcp, int new)
    162 {
    163   if (cbcp->fsm.state != new) {
    164     log_Printf(LogCBCP, "%s: State change %s --> %s\n", cbcp->p->dl->name,
    165                cbcpstate(cbcp->fsm.state), cbcpstate(new));
    166     cbcp->fsm.state = new;
    167   }
    168 }
    169 
    170 struct cbcp_header {
    171   u_char code;
    172   u_char id;
    173   u_int16_t length;	/* Network byte order */
    174 };
    175 
    176 
    177 /* cbcp_header::code values */
    178 #define CBCP_REQ	(1)
    179 #define CBCP_RESPONSE	(2)
    180 #define CBCP_ACK	(3)
    181 
    182 struct cbcp_data {
    183   u_char type;
    184   u_char length;
    185   u_char delay;
    186   char addr_start[253];	/* max cbcp_data length 255 + 1 for NULL */
    187 };
    188 
    189 /* cbcp_data::type values */
    190 #define CBCP_NONUM	(1)
    191 #define CBCP_CLIENTNUM	(2)
    192 #define CBCP_SERVERNUM	(3)
    193 #define CBCP_LISTNUM	(4)
    194 
    195 static void
    196 cbcp_Output(struct cbcp *cbcp, u_char code, struct cbcp_data *data)
    197 {
    198   struct cbcp_header *head;
    199   struct mbuf *bp;
    200 
    201   bp = m_get(sizeof *head + data->length, MB_CBCPOUT);
    202   head = (struct cbcp_header *)MBUF_CTOP(bp);
    203   head->code = code;
    204   head->id = cbcp->fsm.id;
    205   head->length = htons(sizeof *head + data->length);
    206   memcpy(MBUF_CTOP(bp) + sizeof *head, data, data->length);
    207   log_DumpBp(LogDEBUG, "cbcp_Output", bp);
    208   link_PushPacket(&cbcp->p->link, bp, cbcp->p->dl->bundle,
    209                   LINK_QUEUES(&cbcp->p->link) - 1, PROTO_CBCP);
    210 }
    211 
    212 static const char *
    213 cbcp_data_Type(unsigned type)
    214 {
    215   static const char * const types[] = {
    216     "No callback", "User-spec", "Server-spec", "list"
    217   };
    218 
    219   if (type < 1 || type > sizeof types / sizeof types[0])
    220     return HexStr(type, NULL, 0);
    221   return types[type-1];
    222 }
    223 
    224 struct cbcp_addr {
    225   u_char type;
    226   char addr[sizeof ((struct cbcp_data *)0)->addr_start - 1];	/* ASCIIZ */
    227 };
    228 
    229 /* cbcp_data::type values */
    230 #define CBCP_ADDR_PSTN	(1)
    231 
    232 static void
    233 cbcp_data_Show(struct cbcp_data *data)
    234 {
    235   struct cbcp_addr *addr;
    236   char *end;
    237 
    238   addr = (struct cbcp_addr *)data->addr_start;
    239   end = (char *)data + data->length;
    240   *end = '\0';
    241 
    242   log_Printf(LogCBCP, " TYPE %s\n", cbcp_data_Type(data->type));
    243   if ((char *)&data->delay < end) {
    244     log_Printf(LogCBCP, " DELAY %d\n", data->delay);
    245     while (addr->addr < end) {
    246       if (addr->type == CBCP_ADDR_PSTN)
    247         log_Printf(LogCBCP, " ADDR %s\n", addr->addr);
    248       else
    249         log_Printf(LogCBCP, " ADDR type %d ??\n", (int)addr->type);
    250       addr = (struct cbcp_addr *)(addr->addr + strlen(addr->addr) + 1);
    251     }
    252   }
    253 }
    254 
    255 static void
    256 cbcp_SendReq(struct cbcp *cbcp)
    257 {
    258   struct cbcp_data data;
    259   struct cbcp_addr *addr;
    260   char list[sizeof cbcp->fsm.phone], *next;
    261   int len, max;
    262 
    263   /* Only callees send REQs */
    264 
    265   log_Printf(LogCBCP, "%s: SendReq(%d) state = %s\n", cbcp->p->dl->name,
    266              cbcp->fsm.id, cbcpstate(cbcp->fsm.state));
    267   data.type = cbcp->fsm.type;
    268   data.delay = 0;
    269   strncpy(list, cbcp->fsm.phone, sizeof list - 1);
    270   list[sizeof list - 1] = '\0';
    271 
    272   switch (data.type) {
    273     case CBCP_CLIENTNUM:
    274       addr = (struct cbcp_addr *)data.addr_start;
    275       addr->type = CBCP_ADDR_PSTN;
    276       *addr->addr = '\0';
    277       data.length = addr->addr - (char *)&data;
    278       break;
    279 
    280     case CBCP_LISTNUM:
    281       addr = (struct cbcp_addr *)data.addr_start;
    282       for (next = strtok(list, ","); next; next = strtok(NULL, ",")) {
    283         len = strlen(next);
    284         max = data.addr_start + sizeof data.addr_start - addr->addr - 1;
    285         if (len <= max) {
    286           addr->type = CBCP_ADDR_PSTN;
    287           strncpy(addr->addr, next, sizeof addr->addr - 1);
    288           addr->addr[sizeof addr->addr - 1] = '\0';
    289           addr = (struct cbcp_addr *)((char *)addr + len + 2);
    290         } else
    291           log_Printf(LogWARN, "CBCP ADDR \"%s\" skipped - packet too large\n",
    292                      next);
    293       }
    294       data.length = (char *)addr - (char *)&data;
    295       break;
    296 
    297     case CBCP_SERVERNUM:
    298       data.length = data.addr_start - (char *)&data;
    299       break;
    300 
    301     default:
    302       data.length = (char *)&data.delay - (char *)&data;
    303       break;
    304   }
    305 
    306   cbcp_data_Show(&data);
    307   cbcp_Output(cbcp, CBCP_REQ, &data);
    308   cbcp->fsm.restart--;
    309   cbcp_StartTimer(cbcp, cbcp->fsm.delay);
    310   cbcp_NewPhase(cbcp, CBCP_REQSENT);		/* Wait for a RESPONSE */
    311 }
    312 
    313 void
    314 cbcp_Up(struct cbcp *cbcp)
    315 {
    316   struct lcp *lcp = &cbcp->p->link.lcp;
    317 
    318   cbcp->fsm.delay = cbcp->p->dl->cfg.cbcp.delay;
    319   if (*cbcp->p->dl->peer.authname == '\0' ||
    320       !auth_SetPhoneList(cbcp->p->dl->peer.authname, cbcp->fsm.phone,
    321                          sizeof cbcp->fsm.phone)) {
    322     strncpy(cbcp->fsm.phone, cbcp->p->dl->cfg.cbcp.phone,
    323             sizeof cbcp->fsm.phone - 1);
    324     cbcp->fsm.phone[sizeof cbcp->fsm.phone - 1] = '\0';
    325   }
    326 
    327   if (lcp->want_callback.opmask) {
    328     if (*cbcp->fsm.phone == '\0')
    329       cbcp->fsm.type = CBCP_NONUM;
    330     else if (!strcmp(cbcp->fsm.phone, "*")) {
    331       cbcp->fsm.type = CBCP_SERVERNUM;
    332       *cbcp->fsm.phone = '\0';
    333     } else
    334       cbcp->fsm.type = CBCP_CLIENTNUM;
    335     cbcp_NewPhase(cbcp, CBCP_STOPPED);		/* Wait for a REQ */
    336     cbcp_StartTimer(cbcp, cbcp->fsm.delay * DEF_FSMTRIES);
    337   } else {
    338     if (*cbcp->fsm.phone == '\0')
    339       cbcp->fsm.type = CBCP_NONUM;
    340     else if (!strcmp(cbcp->fsm.phone, "*")) {
    341       cbcp->fsm.type = CBCP_CLIENTNUM;
    342       *cbcp->fsm.phone = '\0';
    343     } else if (strchr(cbcp->fsm.phone, ','))
    344       cbcp->fsm.type = CBCP_LISTNUM;
    345     else
    346       cbcp->fsm.type = CBCP_SERVERNUM;
    347     cbcp->fsm.restart = DEF_FSMTRIES;
    348     cbcp_SendReq(cbcp);
    349   }
    350 }
    351 
    352 static int
    353 cbcp_AdjustResponse(struct cbcp *cbcp, struct cbcp_data *data)
    354 {
    355   /*
    356    * We've received a REQ (data).  Adjust our reponse (cbcp->fsm.*)
    357    * so that we (hopefully) agree with the peer
    358    */
    359   struct cbcp_addr *addr;
    360 
    361   switch (data->type) {
    362     case CBCP_NONUM:
    363       if (cbcp->p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_NONE))
    364         /*
    365          * if ``none'' is a configured callback possibility
    366          * (ie, ``set callback cbcp none''), go along with the callees
    367          * request
    368          */
    369         cbcp->fsm.type = CBCP_NONUM;
    370 
    371       /*
    372        * Otherwise, we send our desired response anyway.  This seems to be
    373        * what Win95 does - although I can't find this behaviour documented
    374        * in the CBCP spec....
    375        */
    376 
    377       return 1;
    378 
    379     case CBCP_CLIENTNUM:
    380       if (cbcp->fsm.type == CBCP_CLIENTNUM) {
    381         char *ptr;
    382 
    383         if (data->length > data->addr_start - (char *)data) {
    384           /*
    385            * The peer has given us an address type spec - make sure we
    386            * understand !
    387            */
    388           addr = (struct cbcp_addr *)data->addr_start;
    389           if (addr->type != CBCP_ADDR_PSTN) {
    390             log_Printf(LogPHASE, "CBCP: Unrecognised address type %d !\n",
    391                        (int)addr->type);
    392             return 0;
    393           }
    394         }
    395         /* we accept the REQ even if the peer didn't specify an addr->type */
    396         ptr = strchr(cbcp->fsm.phone, ',');
    397         if (ptr)
    398           *ptr = '\0';		/* Just use the first number in our list */
    399         return 1;
    400       }
    401       log_Printf(LogPHASE, "CBCP: no number to pass to the peer !\n");
    402       return 0;
    403 
    404     case CBCP_SERVERNUM:
    405       if (cbcp->fsm.type == CBCP_SERVERNUM) {
    406         *cbcp->fsm.phone = '\0';
    407         return 1;
    408       }
    409       if (data->length > data->addr_start - (char *)data) {
    410         /*
    411          * This violates the spec, but if the peer has told us the
    412          * number it wants to call back, take advantage of this fact
    413          * and allow things to proceed if we've specified the same
    414          * number
    415          */
    416         addr = (struct cbcp_addr *)data->addr_start;
    417         if (addr->type != CBCP_ADDR_PSTN) {
    418           log_Printf(LogPHASE, "CBCP: Unrecognised address type %d !\n",
    419                      (int)addr->type);
    420           return 0;
    421         } else if (cbcp->fsm.type == CBCP_CLIENTNUM) {
    422           /*
    423            * If the peer's insisting on deciding the number, make sure
    424            * it's one of the ones in our list.  If it is, let the peer
    425            * think it's in control :-)
    426            */
    427           char list[sizeof cbcp->fsm.phone], *next;
    428 
    429           strncpy(list, cbcp->fsm.phone, sizeof list - 1);
    430           list[sizeof list - 1] = '\0';
    431           for (next = strtok(list, ","); next; next = strtok(NULL, ","))
    432             if (!strcmp(next, addr->addr)) {
    433               cbcp->fsm.type = CBCP_SERVERNUM;
    434               strcpy(cbcp->fsm.phone, next);
    435               return 1;
    436             }
    437         }
    438       }
    439       log_Printf(LogPHASE, "CBCP: Peer won't allow local decision !\n");
    440       return 0;
    441 
    442     case CBCP_LISTNUM:
    443       if (cbcp->fsm.type == CBCP_CLIENTNUM || cbcp->fsm.type == CBCP_LISTNUM) {
    444         /*
    445          * Search through ``data''s addresses and see if cbcp->fsm.phone
    446          * contains any of them
    447          */
    448         char list[sizeof cbcp->fsm.phone], *next, *end;
    449 
    450         addr = (struct cbcp_addr *)data->addr_start;
    451         end = (char *)data + data->length;
    452 
    453         while (addr->addr < end) {
    454           if (addr->type == CBCP_ADDR_PSTN) {
    455             strncpy(list, cbcp->fsm.phone, sizeof list - 1);
    456             list[sizeof list - 1] = '\0';
    457             for (next = strtok(list, ","); next; next = strtok(NULL, ","))
    458               if (!strcmp(next, addr->addr)) {
    459                 cbcp->fsm.type = CBCP_LISTNUM;
    460                 strcpy(cbcp->fsm.phone, next);
    461                 return 1;
    462               }
    463           } else
    464             log_Printf(LogCBCP, "Warning: Unrecognised address type %d !\n",
    465                        (int)addr->type);
    466           addr = (struct cbcp_addr *)(addr->addr + strlen(addr->addr) + 1);
    467         }
    468       }
    469       log_Printf(LogPHASE, "CBCP: no good number to pass to the peer !\n");
    470       return 0;
    471   }
    472 
    473   log_Printf(LogCBCP, "Unrecognised REQ type %d !\n", (int)data->type);
    474   return 0;
    475 }
    476 
    477 static void
    478 cbcp_SendResponse(struct cbcp *cbcp)
    479 {
    480   struct cbcp_data data;
    481   struct cbcp_addr *addr;
    482 
    483   /* Only callers send RESPONSEs */
    484 
    485   log_Printf(LogCBCP, "%s: SendResponse(%d) state = %s\n", cbcp->p->dl->name,
    486              cbcp->fsm.id, cbcpstate(cbcp->fsm.state));
    487 
    488   data.type = cbcp->fsm.type;
    489   data.delay = cbcp->fsm.delay;
    490   addr = (struct cbcp_addr *)data.addr_start;
    491   if (data.type == CBCP_NONUM)
    492     data.length = (char *)&data.delay - (char *)&data;
    493   else if (*cbcp->fsm.phone) {
    494     addr->type = CBCP_ADDR_PSTN;
    495     strncpy(addr->addr, cbcp->fsm.phone, sizeof addr->addr - 1);
    496     addr->addr[sizeof addr->addr - 1] = '\0';
    497     data.length = (addr->addr + strlen(addr->addr) + 1) - (char *)&data;
    498   } else
    499     data.length = data.addr_start - (char *)&data;
    500 
    501   cbcp_data_Show(&data);
    502   cbcp_Output(cbcp, CBCP_RESPONSE, &data);
    503   cbcp->fsm.restart--;
    504   cbcp_StartTimer(cbcp, cbcp->fsm.delay);
    505   cbcp_NewPhase(cbcp, CBCP_RESPSENT);	/* Wait for an ACK */
    506 }
    507 
    508 /* What to do after checking an incoming response */
    509 #define CBCP_ACTION_DOWN (0)
    510 #define CBCP_ACTION_REQ (1)
    511 #define CBCP_ACTION_ACK (2)
    512 
    513 static int
    514 cbcp_CheckResponse(struct cbcp *cbcp, struct cbcp_data *data)
    515 {
    516   /*
    517    * We've received a RESPONSE (data).  Check if it agrees with
    518    * our REQ (cbcp->fsm)
    519    */
    520   struct cbcp_addr *addr;
    521 
    522   addr = (struct cbcp_addr *)data->addr_start;
    523 
    524   if (data->type == cbcp->fsm.type) {
    525     switch (cbcp->fsm.type) {
    526       case CBCP_NONUM:
    527         return CBCP_ACTION_ACK;
    528 
    529       case CBCP_CLIENTNUM:
    530         if ((char *)data + data->length <= addr->addr)
    531           log_Printf(LogPHASE, "CBCP: peer didn't respond with a number !\n");
    532         else if (addr->type != CBCP_ADDR_PSTN)
    533           log_Printf(LogPHASE, "CBCP: Unrecognised address type %d !\n",
    534                      addr->type);
    535         else {
    536           strncpy(cbcp->fsm.phone, addr->addr, sizeof cbcp->fsm.phone - 1);
    537           cbcp->fsm.phone[sizeof cbcp->fsm.phone - 1] = '\0';
    538           cbcp->fsm.delay = data->delay;
    539           return CBCP_ACTION_ACK;
    540         }
    541         return CBCP_ACTION_DOWN;
    542 
    543       case CBCP_SERVERNUM:
    544         cbcp->fsm.delay = data->delay;
    545         return CBCP_ACTION_ACK;
    546 
    547       case CBCP_LISTNUM:
    548         if ((char *)data + data->length <= addr->addr)
    549           log_Printf(LogPHASE, "CBCP: peer didn't respond with a number !\n");
    550         else if (addr->type != CBCP_ADDR_PSTN)
    551           log_Printf(LogPHASE, "CBCP: Unrecognised address type %d !\n",
    552                      addr->type);
    553         else {
    554           char list[sizeof cbcp->fsm.phone], *next;
    555 
    556           strncpy(list, cbcp->fsm.phone, sizeof list - 1);
    557           list[sizeof list - 1] = '\0';
    558           for (next = strtok(list, ","); next; next = strtok(NULL, ","))
    559             if (!strcmp(addr->addr, next)) {
    560               strcpy(cbcp->fsm.phone, next);
    561               cbcp->fsm.delay = data->delay;
    562               return CBCP_ACTION_ACK;
    563             }
    564           log_Printf(LogPHASE, "CBCP: peer didn't respond with a "
    565                      "valid number !\n");
    566         }
    567         return CBCP_ACTION_DOWN;
    568     }
    569     log_Printf(LogPHASE, "Internal CBCP error - agreed on %d !\n",
    570                (int)cbcp->fsm.type);
    571     return CBCP_ACTION_DOWN;
    572   } else if (data->type == CBCP_NONUM && cbcp->fsm.type == CBCP_CLIENTNUM) {
    573     /*
    574      * Client doesn't want CBCP after all....
    575      * We only allow this when ``set cbcp *'' has been specified.
    576      */
    577     cbcp->fsm.type = CBCP_NONUM;
    578     return CBCP_ACTION_ACK;
    579   }
    580   log_Printf(LogCBCP, "Invalid peer RESPONSE\n");
    581   return CBCP_ACTION_REQ;
    582 }
    583 
    584 static void
    585 cbcp_SendAck(struct cbcp *cbcp)
    586 {
    587   struct cbcp_data data;
    588   struct cbcp_addr *addr;
    589 
    590   /* Only callees send ACKs */
    591 
    592   log_Printf(LogCBCP, "%s: SendAck(%d) state = %s\n", cbcp->p->dl->name,
    593              cbcp->fsm.id, cbcpstate(cbcp->fsm.state));
    594 
    595   data.type = cbcp->fsm.type;
    596   switch (data.type) {
    597     case CBCP_NONUM:
    598       data.length = (char *)&data.delay - (char *)&data;
    599       break;
    600     case CBCP_CLIENTNUM:
    601       addr = (struct cbcp_addr *)data.addr_start;
    602       addr->type = CBCP_ADDR_PSTN;
    603       strncpy(addr->addr, cbcp->fsm.phone, sizeof addr->addr - 1);
    604       addr->addr[sizeof addr->addr - 1] = '\0';
    605       data.delay = cbcp->fsm.delay;
    606       data.length = addr->addr + strlen(addr->addr) + 1 - (char *)&data;
    607       break;
    608     default:
    609       data.delay = cbcp->fsm.delay;
    610       data.length = data.addr_start - (char *)&data;
    611       break;
    612   }
    613 
    614   cbcp_data_Show(&data);
    615   cbcp_Output(cbcp, CBCP_ACK, &data);
    616   cbcp->fsm.restart--;
    617   cbcp_StartTimer(cbcp, cbcp->fsm.delay);
    618   cbcp_NewPhase(cbcp, CBCP_ACKSENT);	/* Wait for an ACK */
    619 }
    620 
    621 extern struct mbuf *
    622 cbcp_Input(struct bundle *bundle __unused, struct link *l, struct mbuf *bp)
    623 {
    624   struct physical *p = link2physical(l);
    625   struct cbcp_header *head;
    626   struct cbcp_data *data;
    627   struct cbcp *cbcp = &p->dl->cbcp;
    628   size_t len;
    629 
    630   if (p == NULL) {
    631     log_Printf(LogERROR, "cbcp_Input: Not a physical link - dropped\n");
    632     m_freem(bp);
    633     return NULL;
    634   }
    635 
    636   bp = m_pullup(bp);
    637   len = m_length(bp);
    638   if (len < sizeof(struct cbcp_header)) {
    639     m_freem(bp);
    640     return NULL;
    641   }
    642   head = (struct cbcp_header *)MBUF_CTOP(bp);
    643   if (ntohs(head->length) != len) {
    644     log_Printf(LogWARN, "Corrupt CBCP packet (code %d, length %u not %zu)"
    645                " - ignored\n", head->code, ntohs(head->length), len);
    646     m_freem(bp);
    647     return NULL;
    648   }
    649   m_settype(bp, MB_CBCPIN);
    650 
    651   /* XXX check the id */
    652 
    653   bp->m_offset += sizeof(struct cbcp_header);
    654   bp->m_len -= sizeof(struct cbcp_header);
    655   data = (struct cbcp_data *)MBUF_CTOP(bp);
    656 
    657   switch (head->code) {
    658     case CBCP_REQ:
    659       log_Printf(LogCBCP, "%s: RecvReq(%d) state = %s\n",
    660                  p->dl->name, head->id, cbcpstate(cbcp->fsm.state));
    661       cbcp_data_Show(data);
    662       if (cbcp->fsm.state == CBCP_STOPPED || cbcp->fsm.state == CBCP_RESPSENT) {
    663         timer_Stop(&cbcp->fsm.timer);
    664         if (cbcp_AdjustResponse(cbcp, data)) {
    665           cbcp->fsm.restart = DEF_FSMTRIES;
    666           cbcp->fsm.id = head->id;
    667           cbcp_SendResponse(cbcp);
    668         } else
    669           datalink_CBCPFailed(cbcp->p->dl);
    670       } else
    671         log_Printf(LogCBCP, "%s: unexpected REQ dropped\n", p->dl->name);
    672       break;
    673 
    674     case CBCP_RESPONSE:
    675       log_Printf(LogCBCP, "%s: RecvResponse(%d) state = %s\n",
    676 	         p->dl->name, head->id, cbcpstate(cbcp->fsm.state));
    677       cbcp_data_Show(data);
    678       if (cbcp->fsm.id != head->id) {
    679         log_Printf(LogCBCP, "Warning: Expected id was %d, not %d\n",
    680                    cbcp->fsm.id, head->id);
    681         cbcp->fsm.id = head->id;
    682       }
    683       if (cbcp->fsm.state == CBCP_REQSENT || cbcp->fsm.state == CBCP_ACKSENT) {
    684         timer_Stop(&cbcp->fsm.timer);
    685         switch (cbcp_CheckResponse(cbcp, data)) {
    686           case CBCP_ACTION_REQ:
    687             cbcp_SendReq(cbcp);
    688             break;
    689 
    690           case CBCP_ACTION_ACK:
    691             cbcp->fsm.restart = DEF_FSMTRIES;
    692             cbcp_SendAck(cbcp);
    693             if (cbcp->fsm.type == CBCP_NONUM) {
    694               /*
    695                * Don't change state in case the peer doesn't get our ACK,
    696                * just bring the layer up.
    697                */
    698               timer_Stop(&cbcp->fsm.timer);
    699               datalink_NCPUp(cbcp->p->dl);
    700             }
    701             break;
    702 
    703           default:
    704             datalink_CBCPFailed(cbcp->p->dl);
    705             break;
    706         }
    707       } else
    708         log_Printf(LogCBCP, "%s: unexpected RESPONSE dropped\n", p->dl->name);
    709       break;
    710 
    711     case CBCP_ACK:
    712       log_Printf(LogCBCP, "%s: RecvAck(%d) state = %s\n",
    713 	         p->dl->name, head->id, cbcpstate(cbcp->fsm.state));
    714       cbcp_data_Show(data);
    715       if (cbcp->fsm.id != head->id) {
    716         log_Printf(LogCBCP, "Warning: Expected id was %d, not %d\n",
    717                    cbcp->fsm.id, head->id);
    718         cbcp->fsm.id = head->id;
    719       }
    720       if (cbcp->fsm.type == CBCP_NONUM) {
    721         /*
    722          * Don't change state in case the peer doesn't get our ACK,
    723          * just bring the layer up.
    724          */
    725         timer_Stop(&cbcp->fsm.timer);
    726         datalink_NCPUp(cbcp->p->dl);
    727       } else if (cbcp->fsm.state == CBCP_RESPSENT) {
    728         timer_Stop(&cbcp->fsm.timer);
    729         datalink_CBCPComplete(cbcp->p->dl);
    730         log_Printf(LogPHASE, "%s: CBCP: Peer will dial back\n", p->dl->name);
    731       } else
    732         log_Printf(LogCBCP, "%s: unexpected ACK dropped\n", p->dl->name);
    733       break;
    734 
    735     default:
    736       log_Printf(LogWARN, "Unrecognised CBCP packet (code %d, length %zd)\n",
    737                head->code, len);
    738       break;
    739   }
    740 
    741   m_freem(bp);
    742   return NULL;
    743 }
    744 
    745 void
    746 cbcp_Down(struct cbcp *cbcp)
    747 {
    748   timer_Stop(&cbcp->fsm.timer);
    749   cbcp_NewPhase(cbcp, CBCP_CLOSED);
    750   cbcp->required = 0;
    751 }
    752 
    753 void
    754 cbcp_ReceiveTerminateReq(struct physical *p)
    755 {
    756   if (p->dl->cbcp.fsm.state == CBCP_ACKSENT) {
    757     /* Don't change our state in case the peer doesn't get the ACK */
    758     p->dl->cbcp.required = 1;
    759     log_Printf(LogPHASE, "%s: CBCP: Will dial back on %s\n", p->dl->name,
    760                p->dl->cbcp.fsm.phone);
    761   } else
    762     cbcp_NewPhase(&p->dl->cbcp, CBCP_CLOSED);
    763 }
    764