Annotation of embedaddon/libpdel/ppp/ppp_pptp_ctrl.c, revision 1.1.1.1

1.1       misho       1: 
                      2: /*
                      3:  * Copyright (c) 1995-1999 Whistle Communications, Inc.
                      4:  * All rights reserved.
                      5:  * 
                      6:  * Subject to the following obligations and disclaimer of warranty,
                      7:  * use and redistribution of this software, in source or object code
                      8:  * forms, with or without modifications are expressly permitted by
                      9:  * Whistle Communications; provided, however, that:   (i) any and
                     10:  * all reproductions of the source or object code must include the
                     11:  * copyright notice above and the following disclaimer of warranties;
                     12:  * and (ii) no rights are granted, in any manner or form, to use
                     13:  * Whistle Communications, Inc. trademarks, including the mark "WHISTLE
                     14:  * COMMUNICATIONS" on advertising, endorsements, or otherwise except
                     15:  * as such appears in the above copyright notice or in the software.
                     16:  * 
                     17:  * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS",
                     18:  * AND TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS
                     19:  * MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED,
                     20:  * REGARDING THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND
                     21:  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
                     22:  * PURPOSE, OR NON-INFRINGEMENT.  WHISTLE COMMUNICATIONS DOES NOT
                     23:  * WARRANT, GUARANTEE, OR MAKE ANY REPRESENTATIONS REGARDING THE USE
                     24:  * OF, OR THE RESULTS OF THE USE OF THIS SOFTWARE IN TERMS OF ITS
                     25:  * CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.  IN NO EVENT
                     26:  * SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES RESULTING
                     27:  * FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING WITHOUT
                     28:  * LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
                     29:  * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE
                     30:  * GOODS OR SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED
                     31:  * AND UNDER ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
                     33:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS
                     34:  * IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     35:  *
                     36:  * Author: <archie@freebsd.org>
                     37:  */
                     38: 
                     39: #include "ppp/ppp_defs.h"
                     40: #include "ppp/ppp_log.h"
                     41: #include "ppp/ppp_pptp_ctrl.h"
                     42: #include "ppp/ppp_pptp_ctrl_defs.h"
                     43: #include <netinet/tcp.h>
                     44: 
                     45: /*
                     46:  * DEFINITIONS
                     47:  */
                     48: 
                     49:   #define RANDOMIZE_CID                        1
                     50:   #define CHECK_RESERVED_FIELDS                0
                     51:   #define LOGNAME_MAX                  32
                     52: 
                     53: #ifndef FALSE
                     54:   #define FALSE                                0
                     55:   #define TRUE                         1
                     56: #endif
                     57: 
                     58:   #define PPTP_MTYPE                   "ppp_pptp_ctrl"
                     59:   #define PPTP_CTRL_MTYPE              "ppp_pptp_ctrl.ctrl"
                     60:   #define PPTP_CHAN_MTYPE              "ppp_pptp_ctrl.chan"
                     61:   #define PPTP_PREP_MTYPE              "ppp_pptp_ctrl.prep"
                     62: 
                     63:   #define PPTP_FIRMWARE_REV            0x0101
                     64: 
                     65:   #define PPTP_STR_INTERNAL_CALLING    "Internally originated VPN call"
                     66: 
                     67:   /* Limits on how long we wait for replies to things */
                     68:   #define PPTP_DFL_REPLY_TIME          PPTP_IDLE_TIMEOUT
                     69:   #define PPTP_OUTCALLREQ_REPLY_TIME   60
                     70:   #define PPTP_INCALLREP_REPLY_TIME    60
                     71:   #define PPTP_STOPCCR_REPLY_TIME      3
                     72: 
                     73:   /* Logging */
                     74:   #define PLOG(sev, fmt, args...)      \
                     75:              ppp_log_put(pptp->log, sev, fmt , ## args)
                     76:   #define CLOG(sev, fmt, args...)      \
                     77:              ppp_log_put(c->log, sev, fmt , ## args)
                     78:   #define CHLOG(sev, fmt, args...)     \
                     79:              ppp_log_put(ch->log, sev, fmt , ## args)
                     80: 
                     81:   struct pptp_engine;
                     82: 
                     83:   /* This describes how/if a reply is required */
                     84:   struct pptpreqrep {
                     85:     u_char     reply;                  /* required reply (or zero) */
                     86:     u_char     killCtrl;               /* fatal to ctrl or just to channel */
                     87:     u_short    timeout;                /* max time to wait for reply */
                     88:   };
                     89:   typedef struct pptpreqrep    *PptpReqRep;
                     90: 
                     91:   /* This represents a pending reply we're waiting for */
                     92:   struct pptppendrep {
                     93:     const struct pptpmsginfo   *request;       /* original message info */
                     94:     struct pptpctrl            *ctrl;          /* control channel */
                     95:     struct pptpchan            *chan;          /* channel (NULL if none) */
                     96:     struct pevent              *timer;         /* reply timeout timer */
                     97:     struct pptppendrep         *next;          /* next in list */
                     98:   };
                     99:   typedef struct pptppendrep   *PptpPendRep;
                    100: 
                    101:   /* This describes how to match a message to the corresponding channel */
                    102:   struct pptpchanid {
                    103:     u_char             findIn;         /* how to find channel (incoming) */
                    104:     u_char             findOut;        /* how to find channel (outgoing) */
                    105:     const char         *inField;       /* field used to find channel (in) */
                    106:     const char         *outField;      /* field used to find channel (out) */
                    107:   };
                    108:   typedef struct pptpchanid    *PptpChanId;
                    109: 
                    110:   #define PPTP_FIND_CHAN_MY_CID                1       /* match field vs. my cid */
                    111:   #define PPTP_FIND_CHAN_PEER_CID      2       /* match field vs. peer cid */
                    112:   #define PPTP_FIND_CHAN_PNS_CID       3       /* match field vs. PNS cid */
                    113:   #define PPTP_FIND_CHAN_PAC_CID       4       /* match field vs. PAC cid */
                    114: 
                    115:   /* Message handler function type */
                    116:   typedef void pptpmsghandler_t(void *, void *);
                    117: 
                    118:   /* Total info about a message type (except field layout) */
                    119:   struct pptpmsginfo {
                    120:     const char         *name;          /* name for this message type */
                    121:     pptpmsghandler_t   *handler;       /* message handler function */
                    122:     u_char             isReply;        /* this is always a reply message */
                    123:     u_char             length;         /* length of message (sans header) */
                    124:     u_short            states;         /* states which admit this message */
                    125:     struct pptpchanid  match;          /* how to find corresponding channel */
                    126:     struct pptpreqrep  reqrep;         /* what kind of reply we expect */
                    127:   };
                    128:   typedef const struct pptpmsginfo     *PptpMsgInfo;
                    129: 
                    130:   /* Receive window size XXX */
                    131:   #define PPTP_RECV_WIN                        16
                    132: 
                    133:   /* Packet processing delay XXX */
                    134:   #define PPTP_PPD                     1
                    135: 
                    136:   /* Channel state */
                    137:   struct pptpchan {
                    138:     u_char             state;          /* channel state */
                    139:     u_char             id;             /* channel index */
                    140:     u_char             orig:1;         /* call originated from us */
                    141:     u_char             incoming:1;     /* call is incoming, not outgoing */
                    142:     u_char             killing:1;      /* channel is being killed */
                    143:     u_int16_t          cid;            /* my call id */
                    144:     u_int16_t          serno;          /* call serial number */
                    145:     u_int16_t          peerCid;        /* peer call id */
                    146:     u_int16_t          peerPpd;        /* peer's packet processing delay */
                    147:     u_int16_t          recvWin;        /* peer's recv window size */
                    148:     u_int32_t          recvSeq;        /* last seq # we rcv'd */
                    149:     u_int32_t          xmitSeq;        /* last seq # we sent */
                    150:     u_int32_t          recvAck;        /* last seq # peer acknowledged */
                    151:     u_int32_t          xmitAck;        /* last seq # we acknowledged */
                    152:     u_int32_t          bearType;       /* call bearer type */
                    153:     u_int32_t          frameType;      /* call framing type */
                    154:     u_int32_t          minBps;         /* minimum acceptable speed */
                    155:     u_int32_t          maxBps;         /* maximum acceptable speed */
                    156:     struct pptplinkinfo        linfo;          /* info about corresponding link */
                    157:     struct pptpctrl    *ctrl;          /* my control channel */
                    158:     struct ppp_log     *log;           /* log */
                    159:     char               callingNum[PPTP_PHONE_LEN + 1]; /* calling number */
                    160:     char               calledNum[PPTP_PHONE_LEN + 1];  /* called number */
                    161:     char               subAddress[PPTP_SUBADDR_LEN + 1];/* sub-address */
                    162:   };
                    163:   typedef struct pptpchan      *PptpChan;
                    164: 
                    165:   #define PPTP_CHAN_IS_PNS(ch)         (!(ch)->orig ^ !(ch)->incoming)
                    166: 
                    167:   /* Control channel state */
                    168:   struct pptpctrl {
                    169:     u_char             frame[PPTP_CTRL_MAX_FRAME];
                    170:     u_char             state;          /* state */
                    171:     u_char             id;             /* channel index */
                    172:     u_char             orig:1;         /* we originated connection */
                    173:     u_char             killing:1;      /* connection is being killed */
                    174:     u_int16_t          flen;           /* length of partial frame */
                    175:     int                        csock;          /* peer control messages */
                    176:     struct in_addr     self_addr;      /* local IP address */
                    177:     struct in_addr     peer_addr;      /* peer we're talking to */
                    178:     u_int16_t          self_port;
                    179:     u_int16_t          peer_port;
                    180:     struct pptp_engine *pptp;          /* engine that owns me */
                    181:     struct pevent      *connEvent;     /* connection event */
                    182:     struct pevent      *ctrlEvent;     /* control connection input */
                    183:     struct pevent      *killEvent;     /* kill this ctrl in separate thread */
                    184:     struct pevent      *idleTimer;     /* idle timer */
                    185:     struct ppp_log     *log;           /* log */
                    186:     u_int32_t          echoId;         /* last echo id # sent */
                    187:     PptpPendRep                reps;           /* pending replies to msgs */
                    188:     PptpChan           *channels;      /* array of channels */
                    189:     int                        numChannels;    /* length of channels array */
                    190:     char               logname[LOGNAME_MAX];   /* name for logging */
                    191:   };
                    192:   typedef struct pptpctrl      *PptpCtrl;
                    193: 
                    194:   #define MAX_IOVEC    32
                    195: 
                    196:   /* Our physical channel ID */
                    197:   #define PHYS_CHAN(ch)                (((ch)->ctrl->id << 16) | (ch)->id)
                    198: 
                    199: /*
                    200:  * INTERNAL FUNCTIONS
                    201:  */
                    202: 
                    203:   /* Methods for each control message type */
                    204:   static void  PptpStartCtrlConnRequest(PptpCtrl c,
                    205:                        struct pptpStartCtrlConnRequest *m);
                    206:   static void  PptpStartCtrlConnReply(PptpCtrl c,
                    207:                        struct pptpStartCtrlConnReply *m);
                    208:   static void  PptpStopCtrlConnRequest(PptpCtrl c,
                    209:                        struct pptpStopCtrlConnRequest *m);
                    210:   static void  PptpStopCtrlConnReply(PptpCtrl c,
                    211:                        struct pptpStopCtrlConnReply *m);
                    212:   static void  PptpEchoRequest(PptpCtrl c, struct pptpEchoRequest *m);
                    213:   static void  PptpEchoReply(PptpCtrl c, struct pptpEchoReply *m);
                    214:   static void  PptpOutCallRequest(PptpCtrl c, struct pptpOutCallRequest *m);
                    215:   static void  PptpOutCallReply(PptpChan ch, struct pptpOutCallReply *m);
                    216:   static void  PptpInCallRequest(PptpCtrl c, struct pptpInCallRequest *m);
                    217:   static void  PptpInCallReply(PptpChan ch, struct pptpInCallReply *m);
                    218:   static void  PptpInCallConn(PptpChan ch, struct pptpInCallConn *m);
                    219:   static void  PptpCallClearRequest(PptpChan ch,
                    220:                        struct pptpCallClearRequest *m);
                    221:   static void  PptpCallDiscNotify(PptpChan ch, struct pptpCallDiscNotify *m);
                    222:   static void  PptpWanErrorNotify(PptpChan ch, struct pptpWanErrorNotify *m);
                    223:   static void  PptpSetLinkInfo(PptpChan ch, struct pptpSetLinkInfo *m);
                    224: 
                    225:   /* Link layer callbacks */
                    226:   static void  PptpCtrlCloseChan(PptpChan ch,
                    227:                  int result, int error, int cause);
                    228:   static void  PptpCtrlKillChan(PptpChan ch, const char *errmsg);
                    229:   static void  PptpCtrlDialResult(void *cookie,
                    230:                  int result, int error, int cause, int speed);
                    231: 
                    232:   /* Internal event handlers */
                    233:   static pevent_handler_t      PptpCtrlListenEvent;
                    234:   static pevent_handler_t      PptpCtrlConnEvent;
                    235:   static pevent_handler_t      PptpCtrlReadCtrl;
                    236: 
                    237:   /* Shutdown routines */
                    238:   static void  PptpCtrlCloseCtrl(PptpCtrl c);
                    239:   static void  PptpCtrlKillCtrl(PptpCtrl c);
                    240: 
                    241:   /* Timer routines */
                    242:   static void  PptpCtrlResetIdleTimer(PptpCtrl c);
                    243:   static void  PptpCtrlIdleTimeout(void *arg);
                    244:   static void  PptpCtrlReplyTimeout(void *arg);
                    245: 
                    246:   /* Misc routines */
                    247:   static void  PptpCtrlInitCtrl(PptpCtrl c, int orig);
                    248:   static void  PptpCtrlMsg(PptpCtrl c, int type, void *msg);
                    249:   static void  PptpCtrlWriteMsg(PptpCtrl c, int type, void *msg);
                    250:   static int   PptpCtrlGetSocket(struct in_addr ip,
                    251:                  u_int16_t port, char *ebuf, size_t elen);
                    252: 
                    253:   static void  PptpCtrlSwap(int type, void *buf);
                    254:   static void  PptpCtrlDump(int sev, PptpCtrl c, int type, void *msg);
                    255:   static void  PptpCtrlDumpBuf(int sev, PptpCtrl c,
                    256:                  const void *data, size_t len, const char *fmt, ...);
                    257:   static int   PptpCtrlFindField(int type, const char *name, u_int *offset);
                    258:   static void  PptpCtrlInitCinfo(PptpChan ch, PptpCtrlInfo ci);
                    259: 
                    260:   static void  PptpCtrlNewCtrlState(PptpCtrl c, int new);
                    261:   static void  PptpCtrlNewChanState(PptpChan ch, int new);
                    262: 
                    263:   static int   PptpCtrlExtendArray(const char *mtype,
                    264:                        void *arrayp, int esize, int *alenp);
                    265: 
                    266:   static struct pptpctrlinfo
                    267:                        PptpCtrlOrigCall(struct pptp_engine *pptp, int incmg,
                    268:                          struct pptplinkinfo linfo, struct in_addr ip,
                    269:                          u_int16_t port, const char *logname,
                    270:                          int bearType, int frameType, int minBps, int maxBps,
                    271:                          const char *callingNum, const char *calledNum,
                    272:                          const char *subAddress);
                    273: 
                    274:   static PptpCtrl      PptpCtrlGetCtrl(struct pptp_engine *pptp,
                    275:                          int orig, struct in_addr peer_addr,
                    276:                          u_int16_t peer_port, const char *logname,
                    277:                          char *buf, int bsiz);
                    278:   static PptpChan      PptpCtrlGetChan(PptpCtrl c, int chanState, int orig,
                    279:                          int incoming, int bearType, int frameType, int minBps,
                    280:                          int maxBps, const char *callingNum,
                    281:                          const char *calledNum, const char *subAddress);
                    282:   static PptpChan      PptpCtrlFindChan(PptpCtrl c, int type,
                    283:                          void *msg, int incoming);
                    284:   static void          PptpCtrlCheckConn(PptpCtrl c);
                    285: 
                    286: /*
                    287:  * PPTP ENGINE STATE
                    288:  */
                    289: 
                    290:   /* PPTP engine structure */
                    291:   struct pptp_engine {
                    292:          int                   listen_sock;    /* listening socket */
                    293:          struct in_addr        listen_addr;    /* listen ip address */
                    294:          u_int16_t             listen_port;    /* listen port */
                    295:          u_char                nocd;           /* no collision detection */
                    296:          struct pevent_ctx     *ev_ctx;        /* event context */
                    297:          pthread_mutex_t       *mutex;         /* mutex */
                    298:          struct pevent         *listen_event;  /* incoming connection event */
                    299:          PptpCheckNewConn_t    *check_new_conn;/* callback for new connectn. */
                    300:          PptpGetInLink_t       *get_in_link;   /* callback for incoming call */
                    301:          PptpGetOutLink_t      *get_out_link;  /* callback for outgoing call */
                    302:          struct ppp_log        *log;           /* log */
                    303:          void                  *arg;           /* client arg */
                    304:          u_int16_t             last_call_id;   /* last used call id */
                    305:          PptpCtrl              *ctrl;          /* array of control channels */
                    306:          int                   nctrl;          /* length of ctrl array */
                    307:          char                  vendor[PPTP_VENDOR_LEN];    /* vendor name */
                    308:   };
                    309: 
                    310: /*
                    311:  * INTERNAL VARIABLES
                    312:  */
                    313: 
                    314:   /* Control message field layout */
                    315:   static const struct pptpfield
                    316:     gPptpMsgLayout[PPTP_MAX_CTRL_TYPE][PPTP_CTRL_MAX_FIELDS] =
                    317:   {
                    318: #define _WANT_PPTP_FIELDS
                    319: #include "ppp/ppp_pptp_ctrl_defs.h"
                    320:   };
                    321: 
                    322:   /* Control channel and call state names */
                    323:   static const char            *gPptpCtrlStates[] = {
                    324: #define PPTP_CTRL_ST_FREE              0
                    325:                    "FREE",
                    326: #define PPTP_CTRL_ST_IDLE              1
                    327:                    "IDLE",
                    328: #define PPTP_CTRL_ST_WAIT_CTL_REPLY    2
                    329:                    "WAIT_CTL_REPLY",
                    330: #define PPTP_CTRL_ST_WAIT_STOP_REPLY   3
                    331:                    "WAIT_STOP_REPLY",
                    332: #define PPTP_CTRL_ST_ESTABLISHED       4
                    333:                    "ESTABLISHED",
                    334:   };
                    335: 
                    336:   static const char            *gPptpChanStates[] = {
                    337: #define PPTP_CHAN_ST_FREE              0
                    338:                    "FREE",
                    339: #define PPTP_CHAN_ST_WAIT_IN_REPLY     1
                    340:                    "WAIT_IN_REPLY",
                    341: #define PPTP_CHAN_ST_WAIT_OUT_REPLY    2
                    342:                    "WAIT_OUT_REPLY",
                    343: #define PPTP_CHAN_ST_WAIT_CONNECT      3
                    344:                    "WAIT_CONNECT",
                    345: #define PPTP_CHAN_ST_WAIT_DISCONNECT   4
                    346:                    "WAIT_DISCONNECT",
                    347: #define PPTP_CHAN_ST_WAIT_ANSWER       5
                    348:                    "WAIT_ANSWER",
                    349: #define PPTP_CHAN_ST_ESTABLISHED       6
                    350:                    "ESTABLISHED",
                    351: #define PPTP_CHAN_ST_WAIT_CTRL         7
                    352:                    "WAIT_CTRL",
                    353:   };
                    354: 
                    355:   /* Control message descriptors */
                    356: #define CL(s)  (1 << (PPTP_CTRL_ST_ ## s))
                    357: #define CH(s)  ((1 << (PPTP_CHAN_ST_ ## s)) | 0x8000)
                    358: 
                    359:   static const struct pptpmsginfo      gPptpMsgInfo[PPTP_MAX_CTRL_TYPE] = {
                    360:     { "PptpMsgHead", NULL,                     /* placeholder */
                    361:       FALSE, sizeof(struct pptpMsgHead),
                    362:     },
                    363:     { "StartCtrlConnRequest", (pptpmsghandler_t *)PptpStartCtrlConnRequest,
                    364:       FALSE, sizeof(struct pptpStartCtrlConnRequest),
                    365:       CL(IDLE),
                    366:       { 0, 0 },                                        /* no associated channel */
                    367:       { PPTP_StartCtrlConnReply, TRUE, PPTP_DFL_REPLY_TIME },
                    368:     },
                    369:     { "StartCtrlConnReply", (pptpmsghandler_t *)PptpStartCtrlConnReply,
                    370:       TRUE, sizeof(struct pptpStartCtrlConnReply),
                    371:       CL(WAIT_CTL_REPLY),
                    372:       { 0, 0 },                                        /* no associated channel */
                    373:       { 0 },                                   /* no reply expected */
                    374:     },
                    375:     { "StopCtrlConnRequest", (pptpmsghandler_t *)PptpStopCtrlConnRequest,
                    376:       FALSE, sizeof(struct pptpStopCtrlConnRequest),
                    377:       CL(WAIT_CTL_REPLY)|CL(WAIT_STOP_REPLY)|CL(ESTABLISHED),
                    378:       { 0, 0 },                                        /* no associated channel */
                    379:       { PPTP_StopCtrlConnReply, TRUE, PPTP_STOPCCR_REPLY_TIME },
                    380:     },
                    381:     { "StopCtrlConnReply", (pptpmsghandler_t *)PptpStopCtrlConnReply,
                    382:       TRUE, sizeof(struct pptpStopCtrlConnReply),
                    383:       CL(WAIT_STOP_REPLY),
                    384:       { 0, 0 },                                        /* no associated channel */
                    385:       { 0 },                                   /* no reply expected */
                    386:     },
                    387:     { "EchoRequest", (pptpmsghandler_t *)PptpEchoRequest,
                    388:       FALSE, sizeof(struct pptpEchoRequest),
                    389:       CL(ESTABLISHED),
                    390:       { 0, 0 },                                        /* no associated channel */
                    391:       { PPTP_EchoReply, TRUE, PPTP_DFL_REPLY_TIME },
                    392:     },
                    393:     { "EchoReply", (pptpmsghandler_t *)PptpEchoReply,
                    394:       TRUE, sizeof(struct pptpEchoReply),
                    395:       CL(ESTABLISHED),
                    396:       { 0, 0 },                                        /* no associated channel */
                    397:       { 0 },                                   /* no reply expected */
                    398:     },
                    399:     { "OutCallRequest", (pptpmsghandler_t *)PptpOutCallRequest,
                    400:       FALSE, sizeof(struct pptpOutCallRequest),
                    401:       CL(ESTABLISHED),
                    402:       { 0, PPTP_FIND_CHAN_MY_CID, NULL, "cid" },
                    403:       { PPTP_OutCallReply, TRUE, PPTP_OUTCALLREQ_REPLY_TIME },
                    404:     },
                    405:     { "OutCallReply", (pptpmsghandler_t *)PptpOutCallReply,
                    406:       TRUE, sizeof(struct pptpOutCallReply),
                    407:       CH(WAIT_OUT_REPLY),
                    408:       { PPTP_FIND_CHAN_MY_CID, PPTP_FIND_CHAN_MY_CID, "peerCid", "cid" },
                    409:       { 0 },                                   /* no reply expected */
                    410:     },
                    411:     { "InCallRequest", (pptpmsghandler_t *)PptpInCallRequest,
                    412:       FALSE, sizeof(struct pptpInCallRequest),
                    413:       CL(ESTABLISHED),
                    414:       { 0, PPTP_FIND_CHAN_MY_CID, NULL, "cid" },
                    415:       { PPTP_InCallReply, FALSE, PPTP_DFL_REPLY_TIME },
                    416:     },
                    417:     { "InCallReply", (pptpmsghandler_t *)PptpInCallReply,
                    418:       TRUE, sizeof(struct pptpInCallReply),
                    419:       CH(WAIT_IN_REPLY),
                    420:       { PPTP_FIND_CHAN_MY_CID, PPTP_FIND_CHAN_MY_CID, "peerCid", "cid" },
                    421:       { PPTP_InCallConn, FALSE, PPTP_INCALLREP_REPLY_TIME },
                    422:     },
                    423:     { "InCallConn", (pptpmsghandler_t *)PptpInCallConn,
                    424:       TRUE, sizeof(struct pptpInCallConn),
                    425:       CH(WAIT_CONNECT),
                    426:       { PPTP_FIND_CHAN_MY_CID, PPTP_FIND_CHAN_PEER_CID, "peerCid", "peerCid" },
                    427:       { 0 },                                   /* no reply expected */
                    428:     },
                    429:     { "CallClearRequest", (pptpmsghandler_t *)PptpCallClearRequest,
                    430:       FALSE, sizeof(struct pptpCallClearRequest),
                    431:       CH(WAIT_IN_REPLY)|CH(WAIT_ANSWER)|CH(ESTABLISHED),
                    432:       { PPTP_FIND_CHAN_PNS_CID, PPTP_FIND_CHAN_PNS_CID, "cid", "cid" },
                    433:       { PPTP_CallDiscNotify, TRUE, PPTP_DFL_REPLY_TIME },
                    434:     },
                    435:     { "CallDiscNotify", (pptpmsghandler_t *)PptpCallDiscNotify,
                    436:       FALSE, sizeof(struct pptpCallDiscNotify),
                    437:       CH(WAIT_OUT_REPLY)|CH(WAIT_CONNECT)|CH(WAIT_DISCONNECT)|CH(ESTABLISHED),
                    438:       { PPTP_FIND_CHAN_PAC_CID, PPTP_FIND_CHAN_PAC_CID, "cid", "cid" },
                    439:       { 0 },                                   /* no reply expected */
                    440:     },
                    441:     { "WanErrorNotify", (pptpmsghandler_t *)PptpWanErrorNotify,
                    442:       FALSE, sizeof(struct pptpWanErrorNotify),
                    443:       CH(ESTABLISHED),
                    444:       { PPTP_FIND_CHAN_PNS_CID, PPTP_FIND_CHAN_PNS_CID, "cid", "cid" },
                    445:       { 0 },                                   /* no reply expected */
                    446:     },
                    447:     { "SetLinkInfo", (pptpmsghandler_t *)PptpSetLinkInfo,
                    448:       FALSE, sizeof(struct pptpSetLinkInfo),
                    449:       CH(ESTABLISHED),
                    450:       { PPTP_FIND_CHAN_PAC_CID, PPTP_FIND_CHAN_PAC_CID, "cid", "cid" },
                    451:       { 0 },                                   /* no reply expected */
                    452:     },
                    453:   };
                    454: 
                    455: #undef CL
                    456: #undef CH
                    457: 
                    458:   /* Error code to string converters */
                    459:   #define DECODE(a, n) ((u_int)(n) < (sizeof(a) / sizeof(*(a))) ? \
                    460:                            (a)[(u_int)(n)] : "[out of range]")
                    461: 
                    462:   static const char    *const gPptpErrorCodes[] = {
                    463:     "none",
                    464:     "not connected",
                    465:     "bad format",
                    466:     "bad value",
                    467:     "no resource",
                    468:     "bad call ID",
                    469:     "pac error",
                    470:   };
                    471:   #define PPTP_ERROR_CODE(n)           DECODE(gPptpErrorCodes, (n))
                    472: 
                    473:   static const char    *const gPptpSccrReslCodes[] = {
                    474:     "zero?",
                    475:     "OK",
                    476:     "general error",
                    477:     "channel exists",
                    478:     "not authorized",
                    479:     "bad protocol version",
                    480:   };
                    481:   #define PPTP_SCCR_RESL_CODE(n)       DECODE(gPptpSccrReslCodes, (n))
                    482: 
                    483:   static const char    *const gPptpSccrReasCodes[] = {
                    484:     "zero?",
                    485:     "none",
                    486:     "bad protocol version",
                    487:     "local shutdown",
                    488:   };
                    489:   #define PPTP_SCCR_REAS_CODE(n)       DECODE(gPptpSccrReasCodes, (n))
                    490: 
                    491:   static const char    *const gPptpEchoReslCodes[] = {
                    492:     "zero?",
                    493:     "OK",
                    494:     "general error",
                    495:   };
                    496:   #define PPTP_ECHO_RESL_CODE(n)       DECODE(gPptpEchoReslCodes, (n))
                    497: 
                    498:   static const char    *const gPptpOcrReslCodes[] = {
                    499:     "zero?",
                    500:     "OK",
                    501:     "general error",
                    502:     "no carrier",
                    503:     "busy",
                    504:     "no dialtone",
                    505:     "timed out",
                    506:     "admin prohib",
                    507:   };
                    508:   #define PPTP_OCR_RESL_CODE(n)                DECODE(gPptpOcrReslCodes, (n))
                    509: 
                    510:   static const char    *const gPptpIcrReslCodes[] = {
                    511:     "zero?",
                    512:     "OK",
                    513:     "general error",
                    514:     "not accepted",
                    515:   };
                    516:   #define PPTP_ICR_RESL_CODE(n)                DECODE(gPptpIcrReslCodes, (n))
                    517: 
                    518:   static const char    *const gPptpCdnReslCodes[] = {
                    519:     "zero?",
                    520:     "lost carrier",
                    521:     "general error",
                    522:     "admin action",
                    523:     "disconnect request",
                    524:   };
                    525:   #define PPTP_CDN_RESL_CODE(n)                DECODE(gPptpCdnReslCodes, (n))
                    526: 
                    527: /*************************************************************************
                    528:                        EXPORTED FUNCTIONS
                    529: *************************************************************************/
                    530: 
                    531: /*
                    532:  * PptpCtrlInit()
                    533:  *
                    534:  * Initialize PPTP state and set up callbacks. This must be called
                    535:  * first, and any calls after the first will ignore the ip parameter.
                    536:  * Returns 0 if successful, -1 otherwise.
                    537:  *
                    538:  * Parameters:
                    539:  *   arg       Client opaque argument.
                    540:  *   getInLink Function to call when a peer has requested to establish
                    541:  *             an incoming call. If returned cookie is NULL, call failed.
                    542:  *             This pointer may be NULL to deny all incoming calls.
                    543:  *   getOutLink        Function to call when a peer has requested to establish
                    544:  *             an outgoming call. If returned cookie is NULL, call failed.
                    545:  *             This pointer may be NULL to deny all outgoing calls.
                    546:  *   ip                The IP address for my server to use (cannot be zero).
                    547:  *   port      The TCP port for my server to use (zero for default).
                    548:  *   log       The log to use. Note: the log is consumed.
                    549:  */
                    550: 
                    551: struct pptp_engine *
                    552: PptpCtrlInit(void *arg, struct pevent_ctx *ev_ctx, pthread_mutex_t *mutex,
                    553:   PptpCheckNewConn_t *checkNewConn, PptpGetInLink_t *getInLink,
                    554:   PptpGetOutLink_t *getOutLink, struct in_addr ip, u_int16_t port,
                    555:   const char *vendor, struct ppp_log *log, int nocd)
                    556: {
                    557:   struct pptp_engine   *pptp;
                    558:   int                  type;
                    559: 
                    560:   /* Sanity check structure lengths and valid state bits */
                    561:   for (type = 0; type < PPTP_MAX_CTRL_TYPE; type++) {
                    562:     PptpField  field = gPptpMsgLayout[type];
                    563:     int                total;
                    564: 
                    565:     assert((gPptpMsgInfo[type].match.inField != NULL)
                    566:       ^ !(gPptpMsgInfo[type].states & 0x8000));
                    567:     for (total = 0; field->name; field++)
                    568:       total += field->length;
                    569:     assert(total == gPptpMsgInfo[type].length);
                    570:   }
                    571: 
                    572:   /* Create new pptp object */
                    573:   if ((pptp = MALLOC(PPTP_MTYPE, sizeof(*pptp))) == NULL)
                    574:     return(NULL);
                    575:   memset(pptp, 0, sizeof(*pptp));
                    576:   pptp->ev_ctx = ev_ctx;
                    577:   pptp->mutex = mutex;
                    578:   pptp->log = log;
                    579:   pptp->nocd = nocd;
                    580:   pptp->arg = arg;
                    581:   pptp->listen_sock = -1;
                    582:   pptp->check_new_conn = checkNewConn;
                    583:   pptp->get_in_link = getInLink;
                    584:   pptp->get_out_link = getOutLink;
                    585:   pptp->listen_addr = ip;
                    586:   pptp->listen_port = port ? port : PPTP_PORT;
                    587:   if (vendor != NULL)
                    588:        strlcpy(pptp->vendor, vendor, sizeof(pptp->vendor));
                    589: #if RANDOMIZE_CID
                    590:   pptp->last_call_id = time(NULL) ^ (getpid() << 5);
                    591: #endif
                    592: 
                    593:   /* Done */
                    594:   return(pptp);
                    595: }
                    596: 
                    597: /*
                    598:  * PptpCtrlShutdown()
                    599:  *
                    600:  * Destroy a PPTP engine
                    601:  */
                    602: 
                    603: void
                    604: PptpCtrlShutdown(struct pptp_engine **enginep)
                    605: {
                    606:        struct pptp_engine *const pptp = *enginep;
                    607:        int i;
                    608: 
                    609:        if (pptp == NULL)
                    610:                return;
                    611:        *enginep = NULL;
                    612:        if (pptp->listen_sock != -1)
                    613:            (void)close(pptp->listen_sock);
                    614:        for (i = 0; i < pptp->nctrl; i++) {
                    615:                if (pptp->ctrl[i] == NULL)
                    616:                        continue;
                    617:                PptpCtrlKillCtrl(pptp->ctrl[i]);
                    618:        }
                    619:        pevent_unregister(&pptp->listen_event);
                    620:        ppp_log_close(&pptp->log);
                    621:        FREE(PPTP_MTYPE, pptp->ctrl);
                    622:        FREE(PPTP_MTYPE, pptp);
                    623: }
                    624: 
                    625: /*
                    626:  * PptpCtrlListen()
                    627:  *
                    628:  * Enable or disable incoming PPTP TCP connections.
                    629:  * Returns 0 if successful, -1 otherwise.
                    630:  */
                    631: 
                    632: int
                    633: PptpCtrlListen(struct pptp_engine *pptp, int enable)
                    634: {
                    635:   char ebuf[128];
                    636: 
                    637:   /* Enable or disable */
                    638:   if (enable) {
                    639: 
                    640:     /* Already enabled? */
                    641:     if (pptp->listen_sock != -1)
                    642:       return(0);
                    643: 
                    644:     /* We must have a callback for incoming connections */
                    645:     if (pptp->check_new_conn == NULL) {
                    646:       errno = ENXIO;
                    647:       return(-1);
                    648:     }
                    649: 
                    650:     /* Create listening socket */
                    651:     if ((pptp->listen_sock = PptpCtrlGetSocket(pptp->listen_addr,
                    652:        pptp->listen_port, ebuf, sizeof(ebuf))) == -1) {
                    653:       PLOG(LOG_ERR, "pptp: can't get listen socket: %s", ebuf);
                    654:       return(-1);
                    655:     }
                    656: 
                    657:     /* Listen for connections */
                    658:     if (listen(pptp->listen_sock, 10) == -1) {
                    659:        PLOG(LOG_ERR, "pptp: %s: %s", "listen", strerror(errno));
                    660:        goto sock_fail;
                    661:     }
                    662: 
                    663:     /* Wait for incoming connections */
                    664:     if (pevent_register(pptp->ev_ctx, &pptp->listen_event, PEVENT_RECURRING,
                    665:        pptp->mutex, PptpCtrlListenEvent, pptp, PEVENT_READ,
                    666:        pptp->listen_sock) == -1) {
                    667:       PLOG(LOG_ERR, "pptp: %s: %s", "pevent_register", strerror(errno));
                    668: sock_fail:
                    669:       (void)close(pptp->listen_sock);
                    670:       pptp->listen_sock = -1;
                    671:       return(-1);
                    672:     }
                    673:   } else {
                    674: 
                    675:     /* Already disabled? */
                    676:     if (pptp->listen_sock == -1)
                    677:       return(0);
                    678: 
                    679:     /* Stop listening */
                    680:     (void)close(pptp->listen_sock);
                    681:     pptp->listen_sock = -1;
                    682:     pevent_unregister(&pptp->listen_event);
                    683:   }
                    684: 
                    685:   /* Done */
                    686:   return(0);
                    687: }
                    688: 
                    689: /*
                    690:  * PptpCtrlInCall()
                    691:  *
                    692:  * Initiate an incoming call
                    693:  */
                    694: 
                    695: struct pptpctrlinfo
                    696: PptpCtrlInCall(struct pptp_engine *engine,
                    697:        struct pptplinkinfo linfo, struct in_addr ip, u_int16_t port,
                    698:        const char *logname, int bearType, int frameType, int minBps,
                    699:        int maxBps, const char *callingNum, const char *calledNum,
                    700:        const char *subAddress)
                    701: {
                    702:   return(PptpCtrlOrigCall(engine, TRUE, linfo, ip, port, logname,
                    703:     bearType, frameType, minBps, maxBps, callingNum, calledNum, subAddress));
                    704: }
                    705: 
                    706: /*
                    707:  * PptpCtrlOutCall()
                    708:  *
                    709:  * Initiate an outgoing call
                    710:  */
                    711: 
                    712: struct pptpctrlinfo
                    713: PptpCtrlOutCall(struct pptp_engine *engine,
                    714:        struct pptplinkinfo linfo,
                    715:        struct in_addr ip, u_int16_t port, const char *logname,
                    716:        int bearType, int frameType, int minBps, int maxBps,
                    717:        const char *calledNum, const char *subAddress)
                    718: {
                    719:   return(PptpCtrlOrigCall(engine, FALSE, linfo, ip, port, logname,
                    720:     bearType, frameType, minBps, maxBps, PPTP_STR_INTERNAL_CALLING,
                    721:     calledNum, subAddress));
                    722: }
                    723: 
                    724: /*
                    725:  * PptpCtrlOrigCall()
                    726:  *
                    727:  * Request from the PPTP peer at ip:port the establishment of an
                    728:  * incoming or outgoing call (as viewed by the peer). The "result"
                    729:  * callback will be called when the connection has been established
                    730:  * or failed to do so. This initiates a TCP control connection if
                    731:  * needed; otherwise it uses the existing connection. If port is
                    732:  * zero, then use the normal PPTP port.
                    733:  */
                    734: 
                    735: static struct pptpctrlinfo
                    736: PptpCtrlOrigCall(struct pptp_engine *pptp, int incoming,
                    737:        struct pptplinkinfo linfo, struct in_addr ip, u_int16_t port,
                    738:        const char *logname, int bearType, int frameType, int minBps,
                    739:        int maxBps, const char *callingNum, const char *calledNum,
                    740:        const char *subAddress)
                    741: {
                    742:   PptpCtrl             c;
                    743:   PptpChan             ch;
                    744:   struct pptpctrlinfo  cinfo;
                    745:   char                 ebuf[100];
                    746: 
                    747:   /* Init */
                    748:   port = port ? port : PPTP_PORT;
                    749:   memset(&cinfo, 0, sizeof(cinfo));
                    750: 
                    751:   /* Sanity check */
                    752:   if (linfo.result == NULL) {
                    753:     PLOG(LOG_ERR, "pptp: can't originate call without 'result' callback");
                    754:     errno = EINVAL;
                    755:     return(cinfo);
                    756:   }
                    757: 
                    758:   /* Find/create control block */
                    759:   if ((c = PptpCtrlGetCtrl(pptp, TRUE, ip, port,
                    760:       logname, ebuf, sizeof(ebuf))) == NULL) {
                    761:     PLOG(LOG_INFO, "pptp: %s", ebuf);
                    762:     return(cinfo);
                    763:   }
                    764: 
                    765:   /* Get new channel */
                    766:   if ((ch = PptpCtrlGetChan(c, PPTP_CHAN_ST_WAIT_CTRL, TRUE, incoming,
                    767:       bearType, frameType, minBps, maxBps,
                    768:       callingNum, calledNum, subAddress)) == NULL) {
                    769:     PptpCtrlKillCtrl(c);
                    770:     return(cinfo);
                    771:   }
                    772:   ch->linfo = linfo;
                    773: 
                    774:   /* Control channel may be ready already; start channel if so */
                    775:   PptpCtrlCheckConn(c);
                    776: 
                    777:   /* Return OK */
                    778:   PptpCtrlInitCinfo(ch, &cinfo);
                    779:   return(cinfo);
                    780: }
                    781: 
                    782: /*
                    783:  * PptpCtrlGetSessionInfo()
                    784:  *
                    785:  * Returns information associated with a call.
                    786:  */
                    787: 
                    788: int
                    789: PptpCtrlGetSessionInfo(const struct pptpctrlinfo *cp,
                    790:        struct in_addr *selfAddr, struct in_addr *peerAddr,
                    791:        u_int16_t *selfCid, u_int16_t *peerCid,
                    792:        u_int16_t *peerWin, u_int16_t *peerPpd)
                    793: {
                    794:   PptpChan     const ch = (PptpChan)cp->cookie;
                    795: 
                    796:   switch (ch->state) {
                    797:     case PPTP_CHAN_ST_WAIT_IN_REPLY:
                    798:     case PPTP_CHAN_ST_WAIT_OUT_REPLY:
                    799:     case PPTP_CHAN_ST_WAIT_CONNECT:
                    800:     case PPTP_CHAN_ST_WAIT_DISCONNECT:
                    801:     case PPTP_CHAN_ST_WAIT_ANSWER:
                    802:     case PPTP_CHAN_ST_ESTABLISHED:
                    803:     case PPTP_CHAN_ST_WAIT_CTRL:
                    804:       {
                    805:        PptpCtrl        const c = ch->ctrl;
                    806: 
                    807:        if (selfAddr != NULL)
                    808:          *selfAddr = c->self_addr;
                    809:        if (peerAddr != NULL)
                    810:          *peerAddr = c->peer_addr;
                    811:        if (selfCid != NULL)
                    812:          *selfCid = ch->cid;
                    813:        if (peerCid != NULL)
                    814:          *peerCid = ch->peerCid;
                    815:        if (peerWin != NULL)
                    816:          *peerWin = ch->recvWin;
                    817:        if (peerPpd != NULL)
                    818:          *peerPpd = ch->peerPpd;
                    819:        return(0);
                    820:      }
                    821:     case PPTP_CHAN_ST_FREE:
                    822:       errno = ENXIO;
                    823:       return(-1);
                    824:       break;
                    825:     default:
                    826:       assert(0);
                    827:   }
                    828:   return(-1);  /* NOTREACHED */
                    829: }
                    830: 
                    831: /*************************************************************************
                    832:                        CONTROL CONNECTION SETUP
                    833: *************************************************************************/
                    834: 
                    835: /*
                    836:  * PptpCtrlListenEvent()
                    837:  *
                    838:  * Someone has connected to our TCP socket on which we were listening.
                    839:  */
                    840: 
                    841: static void
                    842: PptpCtrlListenEvent(void *cookie)
                    843: {
                    844:   struct pptp_engine   *const pptp = cookie;
                    845:   struct sockaddr_in   peer;
                    846:   int                  psize = sizeof(peer);
                    847:   char                 logname[LOGNAME_MAX];
                    848:   char                 ebuf[100];
                    849:   PptpCtrl             c;
                    850:   int                  sock;
                    851: 
                    852:   /* Accept connection */
                    853:   if ((sock = accept(pptp->listen_sock,
                    854:       (struct sockaddr *)&peer, &psize)) == -1)
                    855:     return;
                    856:   (void)fcntl(sock, F_SETFD, 1);
                    857: 
                    858:   /* See if accepting connection is ok */
                    859:   snprintf(logname, sizeof(logname), "%s:%u",
                    860:     inet_ntoa(peer.sin_addr), ntohs(peer.sin_port));
                    861:   if ((*pptp->check_new_conn)(pptp->arg, peer.sin_addr,
                    862:       ntohs(peer.sin_port), logname, sizeof(logname)) != 0) {
                    863:     PLOG(LOG_INFO, "pptp connection from %s rejected", logname);
                    864:     (void)close(sock);
                    865:     return;
                    866:   }
                    867: 
                    868:   /* Initialize a new control block */
                    869:   PLOG(LOG_INFO, "pptp connection from %s", logname);
                    870:   if ((c = PptpCtrlGetCtrl(pptp, FALSE, peer.sin_addr,
                    871:       ntohs(peer.sin_port), logname, ebuf, sizeof(ebuf))) == NULL) {
                    872:     PLOG(LOG_ERR, "pptp connection failed: %s", ebuf);
                    873:     (void)close(sock);
                    874:     return;
                    875:   }
                    876:   c->csock = sock;
                    877: 
                    878:   /* Initialize the session */
                    879:   PptpCtrlInitCtrl(c, FALSE);
                    880: }
                    881: 
                    882: /*
                    883:  * PptpCtrlConnEvent()
                    884:  *
                    885:  * We are trying to make a TCP connection to the peer. When this
                    886:  * either succeeds or fails, we jump to here.
                    887:  */
                    888: 
                    889: static void
                    890: PptpCtrlConnEvent(void *cookie)
                    891: {
                    892:   PptpCtrl             const c = (PptpCtrl) cookie;
                    893:   struct sockaddr_in   addr;
                    894:   int                  addrLen = sizeof(addr);
                    895: 
                    896:   /* Unregister event */
                    897:   assert(c->state == PPTP_CTRL_ST_IDLE);
                    898:   pevent_unregister(&c->connEvent);
                    899: 
                    900:   /* Check whether the connection was successful or not */
                    901:   if (getpeername(c->csock, (struct sockaddr *) &addr, &addrLen) < 0) {
                    902:     CLOG(LOG_INFO, "connection to peer failed");
                    903:     PptpCtrlKillCtrl(c);
                    904:     return;
                    905:   }
                    906: 
                    907:   /* Initialize the session */
                    908:   CLOG(LOG_INFO, "successfully connected to peer");
                    909:   PptpCtrlInitCtrl(c, TRUE);
                    910: }
                    911: 
                    912: /*
                    913:  * PptpCtrlInitCtrl()
                    914:  *
                    915:  * A TCP connection has just been established. Initialize the
                    916:  * control block for this connection and initiate the session.
                    917:  */
                    918: 
                    919: static void
                    920: PptpCtrlInitCtrl(PptpCtrl c, int orig)
                    921: {
                    922:   struct pptp_engine   *const pptp = c->pptp;
                    923:   struct sockaddr_in   self, peer;
                    924:   static const int     one = 1;
                    925:   int                  k, addrLen;
                    926: 
                    927:   /* Good time for a sanity check */
                    928:   assert(c->state == PPTP_CTRL_ST_IDLE);
                    929:   assert(c->connEvent == NULL);
                    930:   assert(c->ctrlEvent == NULL);
                    931:   assert(c->reps == NULL);
                    932:   for (k = 0; k < c->numChannels; k++) {
                    933:     assert(c->channels[k] == NULL
                    934:       || c->channels[k]->state == PPTP_CHAN_ST_WAIT_CTRL);
                    935:   }
                    936: 
                    937:   /* Initialize control state */
                    938:   c->orig = orig;
                    939:   c->echoId = 0;
                    940:   c->flen = 0;
                    941: 
                    942:   /* Get local IP address */
                    943:   addrLen = sizeof(self);
                    944:   if (getsockname(c->csock, (struct sockaddr *) &self, &addrLen) < 0) {
                    945:     CLOG(LOG_ERR, "%s: %s", "getsockname", strerror(errno));
                    946: abort:
                    947:     PptpCtrlKillCtrl(c);
                    948:     return;
                    949:   }
                    950:   c->self_addr = self.sin_addr;
                    951:   c->self_port = ntohs(self.sin_port);
                    952: 
                    953:   /* Get remote IP address */
                    954:   addrLen = sizeof(peer);
                    955:   if (getpeername(c->csock, (struct sockaddr *) &peer, &addrLen) < 0) {
                    956:     CLOG(LOG_ERR, "%s: %s", "getpeername", strerror(errno));
                    957:     goto abort;
                    958:   }
                    959:   c->peer_addr = peer.sin_addr;
                    960:   c->peer_port = ntohs(peer.sin_port);
                    961: 
                    962:   /* Turn of Nagle algorithm on the TCP socket, since we are going to
                    963:      be writing complete control frames one at a time */
                    964:   if (setsockopt(c->csock, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)) < 0)
                    965:     CLOG(LOG_ERR, "%s: %s", "setsockopt", strerror(errno));
                    966: 
                    967:   /* Register for events on control and data sockets */
                    968:   if (pevent_register(pptp->ev_ctx, &c->ctrlEvent, PEVENT_RECURRING,
                    969:       pptp->mutex, PptpCtrlReadCtrl, c, PEVENT_READ, c->csock) == -1) {
                    970:     CLOG(LOG_ERR, "%s: %s", "pevent_register", strerror(errno));
                    971:     goto abort;
                    972:   }
                    973: 
                    974:   /* Start echo keep-alive timer */
                    975:   PptpCtrlResetIdleTimer(c);
                    976: 
                    977:   /* If we originated the call, we start the conversation */
                    978:   if (c->orig) {
                    979:     struct pptpStartCtrlConnRequest    msg;
                    980: 
                    981:     memset(&msg, 0, sizeof(msg));
                    982:     msg.vers = PPTP_PROTO_VERS;
                    983:     msg.frameCap = PPTP_FRAMECAP_SYNC;
                    984:     msg.bearCap = PPTP_BEARCAP_ANY;
                    985:     msg.firmware = PPTP_FIRMWARE_REV;
                    986:     gethostname(msg.host, sizeof(msg.host));
                    987:     strncpy(msg.vendor, pptp->vendor, sizeof(msg.vendor));
                    988:     PptpCtrlNewCtrlState(c, PPTP_CTRL_ST_WAIT_CTL_REPLY);
                    989:     PptpCtrlWriteMsg(c, PPTP_StartCtrlConnRequest, &msg);
                    990:   }
                    991: }
                    992: 
                    993: /*************************************************************************
                    994:                CONTROL CONNECTION MESSAGE HANDLING
                    995: *************************************************************************/
                    996: 
                    997: /*
                    998:  * PptpCtrlReadCtrl()
                    999:  */
                   1000: 
                   1001: static void
                   1002: PptpCtrlReadCtrl(void *cookie)
                   1003: {
                   1004:   PptpCtrl     const c = (PptpCtrl) cookie;
                   1005:   PptpMsgHead  const hdr = (PptpMsgHead) c->frame;
                   1006:   int          nread;
                   1007: 
                   1008:   /* Figure how much to read and read it */
                   1009:   nread = (c->flen < sizeof(*hdr) ? sizeof(*hdr) : hdr->length) - c->flen;
                   1010:   if ((nread = read(c->csock, c->frame + c->flen, nread)) <= 0) {
                   1011:     if (nread < 0)
                   1012:       CLOG(LOG_ERR, "%s: %s", "read", strerror(errno));
                   1013:     else
                   1014:       CLOG(LOG_INFO, "control connection closed by peer");
                   1015:     goto abort;
                   1016:   }
                   1017:   PptpCtrlDumpBuf(LOG_DEBUG + 1, c,
                   1018:     c->frame + c->flen, nread, "read ctrl data");
                   1019:   c->flen += nread;
                   1020: 
                   1021:   /* Do whatever with what we got */
                   1022:   if (c->flen < sizeof(*hdr))                  /* incomplete header */
                   1023:     return;
                   1024:   if (c->flen == sizeof(*hdr)) {               /* complete header */
                   1025:     PptpCtrlSwap(0, hdr);              /* byte swap header */
                   1026:     CLOG(LOG_DEBUG + 1, "rec'd hdr");
                   1027:     PptpCtrlDump(LOG_DEBUG + 1, c, 0, hdr);
                   1028:     if (hdr->msgType != PPTP_CTRL_MSG_TYPE) {
                   1029:       CLOG(LOG_NOTICE, "rec'd invalid msg type %d", hdr->msgType);
                   1030:       goto abort;
                   1031:     }
                   1032:     if (hdr->magic != PPTP_MAGIC) {
                   1033:       CLOG(LOG_NOTICE, "rec'd invalid magic 0x%08x", hdr->type);
                   1034:       goto abort;
                   1035:     }
                   1036:     if (!PPTP_VALID_CTRL_TYPE(hdr->type)) {
                   1037:       CLOG(LOG_NOTICE, "rec'd invalid ctrl type %d", hdr->type);
                   1038:       goto abort;
                   1039:     }
                   1040: #if CHECK_RESERVED_FIELDS
                   1041:     if (hdr->resv0 != 0) {
                   1042:       CLOG(LOG_NOTICE, "rec'd non-zero reserved field in header");
                   1043:       goto abort;
                   1044:     }
                   1045: #endif
                   1046:     if (hdr->length != sizeof(*hdr) + gPptpMsgInfo[hdr->type].length) {
                   1047:       CLOG(LOG_NOTICE, "rec'd invalid length %u for type %s",
                   1048:        hdr->length, gPptpMsgInfo[hdr->type].name);
                   1049: abort:
                   1050:       PptpCtrlKillCtrl(c);
                   1051:       return;
                   1052:     }
                   1053:     return;
                   1054:   }
                   1055:   if (c->flen == hdr->length) {                        /* complete message */
                   1056:     void       *const msg = ((u_char *) hdr) + sizeof(*hdr);
                   1057: 
                   1058:     PptpCtrlSwap(hdr->type, msg);              /* byte swap message */
                   1059:     CLOG(LOG_DEBUG, "recv %s", gPptpMsgInfo[hdr->type].name);
                   1060:     PptpCtrlDump(LOG_DEBUG, c, hdr->type, msg);
                   1061:     c->flen = 0;
                   1062:     PptpCtrlResetIdleTimer(c);
                   1063:     PptpCtrlMsg(c, hdr->type, msg);
                   1064:   }
                   1065: }
                   1066: 
                   1067: /*
                   1068:  * PptpCtrlMsg()
                   1069:  *
                   1070:  * We read a complete control message. Sanity check it and handle it.
                   1071:  */
                   1072: 
                   1073: static void
                   1074: PptpCtrlMsg(PptpCtrl c, int type, void *msg)
                   1075: {
                   1076:   PptpMsgInfo          const mi = &gPptpMsgInfo[type];
                   1077:   PptpChan             ch = NULL;
                   1078:   PptpPendRep          *pp;
                   1079: 
                   1080: #if CHECK_RESERVED_FIELDS
                   1081:   {
                   1082:     PptpField          field = gPptpMsgLayout[type];
                   1083:     u_int              off;
                   1084:     static u_char      zeros[4];
                   1085: 
                   1086:     /* Make sure all reserved fields are zero */
                   1087:     for (off = 0; field->name; off += field->length, field++) {
                   1088:       if (!strncmp(field->name, PPTP_RESV_PREF, strlen(PPTP_RESV_PREF))
                   1089:          && memcmp((u_char *) msg + off, zeros, field->length)) {
                   1090:        CLOG(LOG_INFO, "rec'd non-zero reserved field %s in %s",
                   1091:          field->name, mi->name);
                   1092:        PptpCtrlKillCtrl(c);
                   1093:        return;
                   1094:       }
                   1095:     }
                   1096:   }
                   1097: #endif
                   1098: 
                   1099:   /* Find channel this message corresponds to (if any) */
                   1100:   if (mi->match.inField && !(ch = PptpCtrlFindChan(c, type, msg, TRUE)))
                   1101:     return;
                   1102: 
                   1103:   /* See if this message qualifies as the reply to a previously sent message */
                   1104:   for (pp = &c->reps; *pp; pp = &(*pp)->next) {
                   1105:     if ((*pp)->request->reqrep.reply == type && (*pp)->chan == ch)
                   1106:       break;
                   1107:   }
                   1108: 
                   1109:   /* If not, and this message is *always* a reply, ignore it */
                   1110:   if (*pp == NULL && mi->isReply) {
                   1111:     CLOG(LOG_NOTICE, "rec'd spurious %s", mi->name);
                   1112:     return;
                   1113:   }
                   1114: 
                   1115:   /* If so, cancel the matching pending reply */
                   1116:   if (*pp) {
                   1117:     PptpPendRep        const prep = *pp;
                   1118: 
                   1119:     pevent_unregister(&prep->timer);
                   1120:     *pp = prep->next;
                   1121:     FREE(PPTP_PREP_MTYPE, prep);
                   1122:   }
                   1123: 
                   1124:   /* Check for invalid message and call or control state combinations */
                   1125:   if (!ch && ((1 << c->state) & mi->states) == 0) {
                   1126:     CLOG(LOG_NOTICE, "rec'd %s in %s state %s (not valid)",
                   1127:       gPptpMsgInfo[type].name, "control channel", gPptpCtrlStates[c->state]);
                   1128:     PptpCtrlKillCtrl(c);
                   1129:     return;
                   1130:   }
                   1131:   if (ch && ((1 << ch->state) & mi->states) == 0) {
                   1132:     CHLOG(LOG_NOTICE, "rec'd %s in %s state %s (not valid)",
                   1133:       gPptpMsgInfo[type].name, "channel", gPptpChanStates[ch->state]);
                   1134:     PptpCtrlKillCtrl(c);
                   1135:     return;
                   1136:   }
                   1137: 
                   1138:   /* Things look OK; process message */
                   1139:   (*mi->handler)(ch ? (void *) ch : (void *) c, msg);
                   1140: }
                   1141: 
                   1142: /*
                   1143:  * PptpCtrlWriteMsg()
                   1144:  *
                   1145:  * Write out a control message. If we should expect a reply,
                   1146:  * register a matching pending reply for it.
                   1147:  */
                   1148: 
                   1149: static void
                   1150: PptpCtrlWriteMsg(PptpCtrl c, int type, void *msg)
                   1151: {
                   1152:   struct pptp_engine   *const pptp = c->pptp;
                   1153:   PptpMsgInfo          const mi = &gPptpMsgInfo[type];
                   1154:   u_char               buf[PPTP_CTRL_MAX_FRAME];
                   1155:   PptpMsgHead          const hdr = (PptpMsgHead) buf;
                   1156:   u_char               *const payload = (u_char *) (hdr + 1);
                   1157:   const int            totlen = sizeof(*hdr) + gPptpMsgInfo[type].length;
                   1158:   int                  nwrote;
                   1159: 
                   1160:   /* Build message */
                   1161:   assert(PPTP_VALID_CTRL_TYPE(type));
                   1162:   memset(hdr, 0, sizeof(*hdr));
                   1163:   hdr->length = totlen;
                   1164:   hdr->msgType = PPTP_CTRL_MSG_TYPE;
                   1165:   hdr->magic = PPTP_MAGIC;
                   1166:   hdr->type = type;
                   1167:   memcpy(payload, msg, gPptpMsgInfo[type].length);
                   1168:   CLOG(LOG_DEBUG, "send %s msg", gPptpMsgInfo[hdr->type].name);
                   1169:   PptpCtrlDump(LOG_DEBUG, c, 0, hdr);
                   1170:   PptpCtrlDump(LOG_DEBUG, c, type, msg);
                   1171: 
                   1172:   /* Byte swap it */
                   1173:   PptpCtrlSwap(0, hdr);
                   1174:   PptpCtrlSwap(type, payload);
                   1175: 
                   1176:   /* Send it; if TCP buffer is full, we abort the connection */
                   1177:   if ((nwrote = write(c->csock, buf, totlen)) != totlen) {
                   1178:     if (nwrote < 0)
                   1179:       CLOG(LOG_ERR, "%s: %s", "write", strerror(errno));
                   1180:     else
                   1181:       CLOG(LOG_ERR, "only wrote %d/%d", nwrote, totlen);
                   1182:     goto kill;
                   1183:   }
                   1184:   PptpCtrlDumpBuf(LOG_DEBUG + 1, c, buf, totlen, "wrote ctrl data");
                   1185: 
                   1186:   /* If we expect a reply to this message, start expecting it now */
                   1187:   if (PPTP_VALID_CTRL_TYPE(mi->reqrep.reply)) {
                   1188:     PptpPendRep        prep;
                   1189: 
                   1190:     if ((prep = MALLOC(PPTP_PREP_MTYPE, sizeof(*prep))) == NULL) {
                   1191:       CLOG(LOG_ERR, "%s: %s", "malloc", strerror(errno));
                   1192:       goto kill;
                   1193:     }
                   1194:     memset(prep, 0, sizeof(*prep));
                   1195:     prep->ctrl = c;
                   1196:     prep->chan = PptpCtrlFindChan(c, type, msg, FALSE);
                   1197:     prep->request = mi;
                   1198:     if (pevent_register(pptp->ev_ctx, &prep->timer, 0,
                   1199:        pptp->mutex, PptpCtrlReplyTimeout, prep, PEVENT_TIME,
                   1200:        mi->reqrep.timeout * 1000) == -1) {
                   1201:       CLOG(LOG_ERR, "%s: %s", "pevent_register", strerror(errno));
                   1202:       FREE(PPTP_PREP_MTYPE, prep);
                   1203:       goto kill;
                   1204:     }
                   1205:     prep->next = c->reps;
                   1206:     c->reps = prep;
                   1207:   }
                   1208: 
                   1209:   /* Done */
                   1210:   return;
                   1211: 
                   1212: kill:
                   1213:   /* There was an error, kill connection (later) */
                   1214:   pevent_unregister(&c->killEvent);
                   1215:   if (pevent_register(pptp->ev_ctx, &c->killEvent, 0, pptp->mutex,
                   1216:       (pevent_handler_t *)PptpCtrlKillCtrl, c, PEVENT_TIME, 0) == -1)
                   1217:     CLOG(LOG_ERR, "pevent_register: %m");
                   1218: }
                   1219: 
                   1220: /*************************************************************************
                   1221:                CONTROL AND CHANNEL ALLOCATION FUNCTIONS
                   1222: *************************************************************************/
                   1223: 
                   1224: /*
                   1225:  * PptpCtrlGetCtrl()
                   1226:  *
                   1227:  * Get existing or create new control bock for given peer and return it.
                   1228:  * Returns NULL if there was some problem, and puts an error message
                   1229:  * into the buffer.
                   1230:  *
                   1231:  * If "orig" is TRUE, and we currently have no TCP connection to the peer,
                   1232:  * then initiate one. Otherwise, make sure we don't already have one,
                   1233:  * because that would mean we'd have two connections to the same peer.
                   1234:  */
                   1235: 
                   1236: static PptpCtrl
                   1237: PptpCtrlGetCtrl(struct pptp_engine *pptp, int orig, struct in_addr peer_addr,
                   1238:        u_int16_t peer_port, const char *logname, char *buf, int bsiz)
                   1239: {
                   1240:   PptpCtrl                     c;
                   1241:   struct sockaddr_in           peer;
                   1242:   static const struct in_addr  any = { 0 };
                   1243:   int                          flags;
                   1244:   int                          k;
                   1245: 
                   1246:   /* See if we're already have a control block matching this address and port */
                   1247:   for (k = 0; k < pptp->nctrl; k++) {
                   1248:     PptpCtrl   const c = pptp->ctrl[k];
                   1249: 
                   1250:     if (c != NULL
                   1251:        && c->peer_addr.s_addr == peer_addr.s_addr
                   1252:        && c->peer_port == peer_port) {
                   1253:       if (orig)
                   1254:        return(c);
                   1255:       snprintf(buf, bsiz, "connection to %s already exists", logname);
                   1256:       return(NULL);
                   1257:     }
                   1258:   }
                   1259: 
                   1260:   /* Find/create a free one */
                   1261:   for (k = 0; k < pptp->nctrl && pptp->ctrl[k] != NULL; k++);
                   1262:   if (k == pptp->nctrl) {
                   1263:     if (PptpCtrlExtendArray(PPTP_MTYPE, &pptp->ctrl,
                   1264:        sizeof(*pptp->ctrl), &pptp->nctrl) == -1) {
                   1265:       snprintf(buf, bsiz, "%s: %s", "malloc", strerror(errno));
                   1266:       return(NULL);
                   1267:     }
                   1268:   }
                   1269:   if ((c = MALLOC(PPTP_CTRL_MTYPE, sizeof(*c))) == NULL) {
                   1270:     snprintf(buf, bsiz, "%s: %s", "malloc", strerror(errno));
                   1271:     return(NULL);
                   1272:   }
                   1273:   memset(c, 0, sizeof(*c));
                   1274:   pptp->ctrl[k] = c;
                   1275: 
                   1276:   /* Initialize it */
                   1277:   c->id = k;
                   1278:   c->pptp = pptp;
                   1279:   c->orig = orig;
                   1280:   c->csock = -1;
                   1281:   c->peer_addr = peer_addr;
                   1282:   c->peer_port = peer_port;
                   1283:   strlcpy(c->logname, logname, sizeof(c->logname));
                   1284:   if ((c->log = ppp_log_prefix(pptp->log, "%s: ", c->logname)) == NULL) {
                   1285:     snprintf(buf, bsiz, "%s: %s", "ppp_log_prefix", strerror(errno));
                   1286:     pptp->ctrl[k] = NULL;
                   1287:     FREE(PPTP_CTRL_MTYPE, c);
                   1288:     return(NULL);
                   1289:   }
                   1290: 
                   1291:   /* Go to the idle state */
                   1292:   PptpCtrlNewCtrlState(c, PPTP_CTRL_ST_IDLE);
                   1293: 
                   1294:   /* If not doing the connecting, return here */
                   1295:   if (!c->orig)
                   1296:     return(c);
                   1297: 
                   1298:   /* Get socket */
                   1299:   if ((c->csock = PptpCtrlGetSocket(any, 0, buf, bsiz)) < 0) {
                   1300:     PptpCtrlNewCtrlState(c, PPTP_CTRL_ST_FREE);
                   1301:     return(NULL);
                   1302:   }
                   1303: 
                   1304:   /* Put socket in non-blocking mode */
                   1305:   if (fcntl(c->csock, F_GETFL, &flags) == -1
                   1306:       || fcntl(c->csock, F_SETFL, flags | O_NONBLOCK) == -1) {
                   1307:     snprintf(buf, bsiz, "pptp: connect to %s failed: %s: %s",
                   1308:       logname, "fcntl", strerror(errno));
                   1309:     PptpCtrlNewCtrlState(c, PPTP_CTRL_ST_FREE);
                   1310:     return(NULL);
                   1311:   }
                   1312: 
                   1313:   /* Initiate connection to peer */
                   1314:   memset(&peer, 0, sizeof(peer));
                   1315:   peer.sin_family = AF_INET;
                   1316:   peer.sin_addr = c->peer_addr;
                   1317:   peer.sin_port = htons(c->peer_port);
                   1318:   if (connect(c->csock, (struct sockaddr *) &peer, sizeof(peer)) < 0
                   1319:       && errno != EINPROGRESS) {
                   1320:     (void) close(c->csock);
                   1321:     c->csock = -1;
                   1322:     snprintf(buf, bsiz, "pptp: connect to %s failed: %s",
                   1323:       logname, strerror(errno));
                   1324:     PptpCtrlNewCtrlState(c, PPTP_CTRL_ST_FREE);
                   1325:     return(NULL);
                   1326:   }
                   1327: 
                   1328:   /* Put socket back in blocking mode */
                   1329:   if (fcntl(c->csock, F_SETFL, flags) == -1) {
                   1330:     (void) close(c->csock);
                   1331:     c->csock = -1;
                   1332:     snprintf(buf, bsiz, "pptp: connect to %s failed: %s: %s",
                   1333:       logname, "fcntl", strerror(errno));
                   1334:     PptpCtrlNewCtrlState(c, PPTP_CTRL_ST_FREE);
                   1335:     return(NULL);
                   1336:   }
                   1337: 
                   1338:   /* Wait for it to go through */
                   1339:   if (pevent_register(pptp->ev_ctx, &c->connEvent, PEVENT_RECURRING,
                   1340:       pptp->mutex, PptpCtrlConnEvent, c, PEVENT_READ, c->csock) == -1) {
                   1341:     CLOG(LOG_ERR, "%s: %s", "pevent_register", strerror(errno));
                   1342:     PptpCtrlNewCtrlState(c, PPTP_CTRL_ST_FREE);
                   1343:     return(NULL);
                   1344:   }
                   1345: 
                   1346:   /* Done */
                   1347:   CLOG(LOG_INFO, "intiating connection to peer");
                   1348:   return(c);
                   1349: }
                   1350: 
                   1351: /*
                   1352:  * PptpCtrlGetChan()
                   1353:  *
                   1354:  * Find a free data channel and attach it to the control channel.
                   1355:  */
                   1356: 
                   1357: static PptpChan
                   1358: PptpCtrlGetChan(PptpCtrl c, int chanState, int orig, int incoming,
                   1359:        int bearType, int frameType, int minBps, int maxBps,
                   1360:        const char *callingNum, const char *calledNum, const char *subAddress)
                   1361: {
                   1362:   struct pptp_engine   *const pptp = c->pptp;
                   1363:   PptpChan             ch;
                   1364:   int                  k;
                   1365: 
                   1366:   /* Get a free data channel */
                   1367:   for (k = 0; k < c->numChannels && c->channels[k] != NULL; k++);
                   1368:   if (k == c->numChannels) {
                   1369:     if (PptpCtrlExtendArray(PPTP_CTRL_MTYPE, &c->channels,
                   1370:        sizeof(*c->channels), &c->numChannels) == -1) {
                   1371:       CLOG(LOG_ERR, "%s: %s", "malloc", strerror(errno));
                   1372:       return(NULL);
                   1373:     }
                   1374:   }
                   1375:   if ((ch = MALLOC(PPTP_CHAN_MTYPE, sizeof(*ch))) == NULL) {
                   1376:     CLOG(LOG_ERR, "%s: %s", "malloc", strerror(errno));
                   1377:     return(NULL);
                   1378:   }
                   1379:   memset(ch, 0, sizeof(*ch));
                   1380:   c->channels[k] = ch;
                   1381:   ch->id = k;
                   1382:   ch->cid = ++pptp->last_call_id;
                   1383:   ch->ctrl = c;
                   1384:   ch->orig = orig;
                   1385:   ch->incoming = incoming;
                   1386:   ch->minBps = minBps;
                   1387:   ch->maxBps = maxBps;
                   1388:   ch->bearType = bearType;
                   1389:   ch->frameType = frameType;
                   1390:   snprintf(ch->calledNum, sizeof(ch->calledNum), "%s", calledNum);
                   1391:   snprintf(ch->callingNum, sizeof(ch->callingNum), "%s", callingNum);
                   1392:   snprintf(ch->subAddress, sizeof(ch->subAddress), "%s", subAddress);
                   1393: 
                   1394:   /* Get log for this channel */
                   1395:   if ((ch->log = ppp_log_prefix(pptp->log,
                   1396:       "%s[%d]: ", c->logname, ch->id)) == NULL) {
                   1397:     CLOG(LOG_ERR, "%s: %s", "ppp_log_prefix", strerror(errno));
                   1398:     pptp->last_call_id--;
                   1399:     c->channels[k] = NULL;
                   1400:     FREE(PPTP_CHAN_MTYPE, ch);
                   1401:     return(NULL);
                   1402:   }
                   1403: 
                   1404:   /* Go to starting state */
                   1405:   PptpCtrlNewChanState(ch, chanState);
                   1406:   return(ch);
                   1407: }
                   1408: 
                   1409: /*
                   1410:  * PptpCtrlDialResult()
                   1411:  *
                   1412:  * Link layer calls this to let us know whether an outgoing call
                   1413:  * has been successfully completed or has failed.
                   1414:  */
                   1415: 
                   1416: static void
                   1417: PptpCtrlDialResult(void *cookie, int result, int error, int cause, int speed)
                   1418: {
                   1419:   PptpChan                     const ch = (PptpChan) cookie;
                   1420:   PptpCtrl                     const c = ch->ctrl;
                   1421:   struct pptpOutCallReply      rep;
                   1422: 
                   1423:   memset(&rep, 0, sizeof(rep));
                   1424:   rep.cid = ch->cid;
                   1425:   rep.peerCid = ch->peerCid;
                   1426:   rep.result = result;
                   1427:   if (rep.result == PPTP_OCR_RESL_ERR)
                   1428:     rep.err = error;
                   1429:   rep.cause = cause;
                   1430:   rep.speed = speed;
                   1431:   rep.ppd = PPTP_PPD;          /* XXX should get this value from link layer */
                   1432:   rep.recvWin = PPTP_RECV_WIN; /* XXX */
                   1433:   rep.channel = PHYS_CHAN(ch);
                   1434:   PptpCtrlWriteMsg(c, PPTP_OutCallReply, &rep);
                   1435:   if (rep.result == PPTP_OCR_RESL_OK)
                   1436:     PptpCtrlNewChanState(ch, PPTP_CHAN_ST_ESTABLISHED);
                   1437:   else
                   1438:     PptpCtrlKillChan(ch, "local outgoing call failed");
                   1439: }
                   1440: 
                   1441: /*************************************************************************
                   1442:                    SHUTDOWN FUNCTIONS
                   1443: *************************************************************************/
                   1444: 
                   1445: /*
                   1446:  * PptpCtrlCloseCtrl()
                   1447:  */
                   1448: 
                   1449: static void
                   1450: PptpCtrlCloseCtrl(PptpCtrl c)
                   1451: {
                   1452:   CLOG(LOG_INFO, "closing PPTP control connection");
                   1453:   switch (c->state) {
                   1454:     case PPTP_CTRL_ST_IDLE:
                   1455:     case PPTP_CTRL_ST_WAIT_STOP_REPLY:
                   1456:     case PPTP_CTRL_ST_WAIT_CTL_REPLY:
                   1457:       PptpCtrlKillCtrl(c);
                   1458:       return;
                   1459:     case PPTP_CTRL_ST_ESTABLISHED:
                   1460:       {
                   1461:        struct pptpStopCtrlConnRequest  req;
                   1462: 
                   1463:        memset(&req, 0, sizeof(req));
                   1464:        req.reason = PPTP_SCCR_REAS_LOCAL;
                   1465:        PptpCtrlNewCtrlState(c, PPTP_CTRL_ST_WAIT_STOP_REPLY);
                   1466:        PptpCtrlWriteMsg(c, PPTP_StopCtrlConnRequest, &req);
                   1467:        return;
                   1468:       }
                   1469:       break;
                   1470:     default:
                   1471:       assert(0);
                   1472:   }
                   1473: }
                   1474: 
                   1475: /*
                   1476:  * PptpCtrlKillCtrl()
                   1477:  */
                   1478: 
                   1479: static void
                   1480: PptpCtrlKillCtrl(PptpCtrl c)
                   1481: {
                   1482:   PptpPendRep          prep, next;
                   1483:   int                  k;
                   1484: 
                   1485:   /* Cancel kill event */
                   1486:   pevent_unregister(&c->killEvent);
                   1487: 
                   1488:   /* Don't recurse */
                   1489:   assert(c);
                   1490:   if (c->killing || c->state == PPTP_CTRL_ST_FREE)
                   1491:     return;
                   1492:   c->killing = 1;
                   1493: 
                   1494:   /* Do ungraceful shutdown */
                   1495:   CLOG(LOG_DEBUG, "killing control connection");
                   1496:   for (k = 0; k < c->numChannels; k++) {
                   1497:     PptpChan   const ch = c->channels[k];
                   1498: 
                   1499:     if (ch != NULL)
                   1500:       PptpCtrlKillChan(ch, "control channel shutdown");
                   1501:   }
                   1502:   if (c->csock >= 0) {
                   1503:     close(c->csock);
                   1504:     c->csock = -1;
                   1505:   }
                   1506:   pevent_unregister(&c->connEvent);
                   1507:   pevent_unregister(&c->ctrlEvent);
                   1508:   pevent_unregister(&c->idleTimer);
                   1509:   for (prep = c->reps; prep; prep = next) {
                   1510:     next = prep->next;
                   1511:     pevent_unregister(&prep->timer);
                   1512:     FREE(PPTP_PREP_MTYPE, prep);
                   1513:   }
                   1514:   c->reps = NULL;
                   1515:   PptpCtrlNewCtrlState(c, PPTP_CTRL_ST_FREE);
                   1516: }
                   1517: 
                   1518: /*
                   1519:  * PptpCtrlCloseChan()
                   1520:  *
                   1521:  * Gracefully clear a call.
                   1522:  */
                   1523: 
                   1524: static void
                   1525: PptpCtrlCloseChan(PptpChan ch, int result, int error, int cause)
                   1526: {
                   1527:   PptpCtrl     const c = ch->ctrl;
                   1528: 
                   1529:   /* Don't recurse */
                   1530:   if (ch->killing)
                   1531:     return;
                   1532: 
                   1533:   /* Check call state */
                   1534:   switch (ch->state) {
                   1535:     case PPTP_CHAN_ST_ESTABLISHED:
                   1536:       if (PPTP_CHAN_IS_PNS(ch))
                   1537:        goto pnsClear;
                   1538:       else
                   1539:        goto pacClear;
                   1540:       break;
                   1541:     case PPTP_CHAN_ST_WAIT_ANSWER:
                   1542:       {
                   1543:        struct pptpOutCallReply reply;
                   1544: 
                   1545:        memset(&reply, 0, sizeof(reply));
                   1546:        reply.peerCid = ch->peerCid;
                   1547:        reply.result = PPTP_OCR_RESL_ADMIN;
                   1548:        PptpCtrlWriteMsg(c, PPTP_OutCallReply, &reply);
                   1549:        PptpCtrlKillChan(ch, "link layer shutdown");    /* XXX errmsg */
                   1550:        return;
                   1551:       }
                   1552:       break;
                   1553:     case PPTP_CHAN_ST_WAIT_IN_REPLY:           /* we are the PAC */
                   1554: pacClear:
                   1555:       {
                   1556:        struct pptpCallDiscNotify       disc;
                   1557: 
                   1558:        CHLOG(LOG_INFO, "clearing call");
                   1559:        memset(&disc, 0, sizeof(disc));
                   1560:        disc.cid = ch->cid;
                   1561:        disc.result = result;
                   1562:        if (disc.result == PPTP_CDN_RESL_ERR)
                   1563:          disc.err = error;
                   1564:        disc.cause = cause;
                   1565:        /* XXX stats? */
                   1566:        PptpCtrlWriteMsg(c, PPTP_CallDiscNotify, &disc);
                   1567:        PptpCtrlKillChan(ch, "link layer shutdown");    /* XXX errmsg */
                   1568:       }
                   1569:       break;
                   1570:     case PPTP_CHAN_ST_WAIT_OUT_REPLY:          /* we are the PNS */
                   1571:     case PPTP_CHAN_ST_WAIT_CONNECT:            /* we are the PNS */
                   1572: pnsClear:
                   1573:       {
                   1574:        struct pptpCallClearRequest     req;
                   1575: 
                   1576:        CHLOG(LOG_INFO, "clearing call");
                   1577:        memset(&req, 0, sizeof(req));
                   1578:        req.cid = ch->cid;
                   1579:        PptpCtrlNewChanState(ch, PPTP_CHAN_ST_WAIT_DISCONNECT);
                   1580:        PptpCtrlWriteMsg(c, PPTP_CallClearRequest, &req);
                   1581:       }
                   1582:       break;
                   1583:     case PPTP_CHAN_ST_WAIT_DISCONNECT:         /* call was already cleared */
                   1584:       return;
                   1585:     case PPTP_CHAN_ST_WAIT_CTRL:
                   1586:       PptpCtrlKillChan(ch, "link layer shutdown");
                   1587:       return;
                   1588:     default:
                   1589:       assert(0);
                   1590:   }
                   1591: }
                   1592: 
                   1593: /*
                   1594:  * PptpCtrlKillChan()
                   1595:  */
                   1596: 
                   1597: static void
                   1598: PptpCtrlKillChan(PptpChan ch, const char *errmsg)
                   1599: {
                   1600:   PptpCtrl             const c = ch->ctrl;
                   1601:   PptpPendRep          *pp;
                   1602:   int                  k;
                   1603: 
                   1604:   /* Don't recurse */
                   1605:   assert(ch);
                   1606:   if (ch->killing)             /* should never happen anyway */
                   1607:     return;
                   1608:   ch->killing = 1;
                   1609: 
                   1610:   /* If link layer needs notification, tell it */
                   1611:   CHLOG(LOG_DEBUG, "killing channel");
                   1612:   switch (ch->state) {
                   1613:     case PPTP_CHAN_ST_WAIT_IN_REPLY:
                   1614:     case PPTP_CHAN_ST_WAIT_OUT_REPLY:
                   1615:     case PPTP_CHAN_ST_WAIT_CONNECT:
                   1616:     case PPTP_CHAN_ST_ESTABLISHED:
                   1617:     case PPTP_CHAN_ST_WAIT_CTRL:
                   1618:       (*ch->linfo.result)(ch->linfo.cookie, errmsg);
                   1619:       break;
                   1620:     case PPTP_CHAN_ST_WAIT_DISCONNECT:
                   1621:       break;
                   1622:     case PPTP_CHAN_ST_WAIT_ANSWER:
                   1623:       (*ch->linfo.cancel)(ch->linfo.cookie);
                   1624:       break;
                   1625:     default:
                   1626:       assert(0);
                   1627:   }
                   1628: 
                   1629:   /* Nuke any pending replies pertaining to this channel */
                   1630:   for (pp = &c->reps; *pp; ) {
                   1631:     PptpPendRep        const prep = *pp;
                   1632: 
                   1633:     if (prep->chan == ch) {
                   1634:       pevent_unregister(&prep->timer);
                   1635:       *pp = prep->next;
                   1636:       FREE(PPTP_PREP_MTYPE, prep);
                   1637:     } else
                   1638:       pp = &prep->next;
                   1639:   }
                   1640: 
                   1641:   /* Free channel */
                   1642:   PptpCtrlNewChanState(ch, PPTP_CHAN_ST_FREE);
                   1643: 
                   1644:   /* When the last channel is closed, close the control channel too,
                   1645:      unless we're already in the process of killing it. */
                   1646:   for (k = 0; k < c->numChannels; k++) {
                   1647:     PptpChan   const ch2 = c->channels[k];
                   1648: 
                   1649:     if (ch2 != NULL && ch2->ctrl == c)
                   1650:       break;
                   1651:   }
                   1652:   if (k == c->numChannels
                   1653:       && c->state == PPTP_CTRL_ST_ESTABLISHED
                   1654:       && !c->killing)
                   1655:     PptpCtrlCloseCtrl(c);
                   1656: }
                   1657: 
                   1658: /*************************************************************************
                   1659:                    TIMER RELATED FUNCTIONS
                   1660: *************************************************************************/
                   1661: 
                   1662: /*
                   1663:  * PptpCtrlReplyTimeout()
                   1664:  */
                   1665: 
                   1666: static void
                   1667: PptpCtrlReplyTimeout(void *arg)
                   1668: {
                   1669:   PptpPendRep          const prep = (PptpPendRep) arg;
                   1670:   PptpPendRep          *pp;
                   1671:   PptpChan             const ch = prep->chan;
                   1672:   PptpCtrl             const c = prep->ctrl;
                   1673: 
                   1674:   /* Cancel timer event */
                   1675:   pevent_unregister(&prep->timer);
                   1676: 
                   1677:   /* Log it */
                   1678:   if (ch) {
                   1679:     CHLOG(LOG_NOTICE, "no reply to %s after %d sec",
                   1680:       prep->request->name, prep->request->reqrep.timeout);
                   1681:   } else if (prep->request - gPptpMsgInfo != PPTP_StopCtrlConnRequest) {
                   1682:     CLOG(LOG_NOTICE, "no reply to %s after %d sec",
                   1683:       prep->request->name, prep->request->reqrep.timeout);
                   1684:   }
                   1685: 
                   1686:   /* Unlink pending reply */
                   1687:   for (pp = &c->reps; *pp != prep; pp = &(*pp)->next);
                   1688:   assert(*pp);
                   1689:   *pp = prep->next;
                   1690: 
                   1691:   /* Either close this channel or kill entire control connection */
                   1692:   if (prep->request->reqrep.killCtrl)
                   1693:     PptpCtrlKillCtrl(c);
                   1694:   else
                   1695:     PptpCtrlCloseChan(ch, PPTP_CDN_RESL_ERR, PPTP_ERROR_PAC_ERROR, 0);
                   1696: 
                   1697:   /* Done */
                   1698:   FREE(PPTP_PREP_MTYPE, prep);
                   1699: }
                   1700: 
                   1701: /*
                   1702:  * PptpCtrlIdleTimeout()
                   1703:  *
                   1704:  * We've heard PPTP_IDLE_TIMEOUT seconds of silence from the peer.
                   1705:  * Send an echo request to make sure it's alive.
                   1706:  */
                   1707: 
                   1708: static void
                   1709: PptpCtrlIdleTimeout(void *arg)
                   1710: {
                   1711:   PptpCtrl                     const c = (PptpCtrl) arg;
                   1712:   struct pptpEchoRequest       msg;
                   1713:   int                          k;
                   1714: 
                   1715:   /* Cancel timer event */
                   1716:   pevent_unregister(&c->idleTimer);
                   1717: 
                   1718:   /* If no channels are left on this control connection, shut it down */
                   1719:   for (k = 0; k < c->numChannels && c->channels[k] == NULL; k++);
                   1720:   if (k == c->numChannels) {
                   1721:     PptpCtrlCloseCtrl(c);
                   1722:     return;
                   1723:   }
                   1724: 
                   1725:   /* Send echo request */
                   1726:   memset(&msg, 0, sizeof(msg));
                   1727:   msg.id = ++c->echoId;
                   1728:   PptpCtrlWriteMsg(c, PPTP_EchoRequest, &msg);
                   1729: }
                   1730: 
                   1731: /*
                   1732:  * PptpCtrlResetIdleTimer()
                   1733:  *
                   1734:  * Reset the idle timer back up to PPTP_IDLE_TIMEOUT seconds.
                   1735:  */
                   1736: 
                   1737: static void
                   1738: PptpCtrlResetIdleTimer(PptpCtrl c)
                   1739: {
                   1740:   struct pptp_engine   *const pptp = c->pptp;
                   1741: 
                   1742:   pevent_unregister(&c->idleTimer);
                   1743:   if (pevent_register(pptp->ev_ctx, &c->idleTimer, 0, pptp->mutex,
                   1744:       PptpCtrlIdleTimeout, c, PEVENT_TIME, PPTP_IDLE_TIMEOUT * 1000) == -1)
                   1745:     CLOG(LOG_ERR, "%s: %s", "pevent_register", strerror(errno));
                   1746: }
                   1747: 
                   1748: 
                   1749: /*************************************************************************
                   1750:                    CHANNEL MAINTENANCE FUNCTIONS
                   1751: *************************************************************************/
                   1752: 
                   1753: /*
                   1754:  * PptpCtrlCheckConn()
                   1755:  *
                   1756:  * Check whether we have any pending connection requests, and whether
                   1757:  * we can send them yet, or what.
                   1758:  */
                   1759: 
                   1760: static void
                   1761: PptpCtrlCheckConn(PptpCtrl c)
                   1762: {
                   1763:   int  k;
                   1764: 
                   1765:   switch (c->state) {
                   1766:     case PPTP_CTRL_ST_IDLE:
                   1767:     case PPTP_CTRL_ST_WAIT_CTL_REPLY:
                   1768:     case PPTP_CTRL_ST_WAIT_STOP_REPLY:
                   1769:       break;
                   1770:     case PPTP_CTRL_ST_ESTABLISHED:
                   1771:       for (k = 0; k < c->numChannels; k++) {
                   1772:        PptpChan        const ch = c->channels[k];
                   1773: 
                   1774:        if (ch == NULL || ch->state != PPTP_CHAN_ST_WAIT_CTRL)
                   1775:          continue;
                   1776:        if (ch->incoming) {
                   1777:          struct pptpInCallRequest      req;
                   1778: 
                   1779:          memset(&req, 0, sizeof(req));
                   1780:          req.cid = ch->cid;
                   1781:          req.serno = req.cid;
                   1782:          req.bearType = PPTP_BEARCAP_DIGITAL;
                   1783:          req.channel = PHYS_CHAN(ch);
                   1784:          PptpCtrlNewChanState(ch, PPTP_CHAN_ST_WAIT_IN_REPLY);
                   1785:          PptpCtrlWriteMsg(c, PPTP_InCallRequest, &req);
                   1786:        } else {
                   1787:          struct pptpOutCallRequest     req;
                   1788: 
                   1789:          memset(&req, 0, sizeof(req));
                   1790:          req.cid = ch->cid;
                   1791:          req.serno = req.cid;
                   1792:          req.minBps = ch->minBps;
                   1793:          req.maxBps = ch->maxBps;
                   1794:          req.bearType = ch->bearType;
                   1795:          req.frameType = ch->frameType;
                   1796:          req.recvWin = PPTP_RECV_WIN;          /* XXX */
                   1797:          req.ppd = PPTP_PPD;                   /* XXX */
                   1798:          req.numLen = strlen(ch->calledNum);
                   1799:          strncpy(req.phone, ch->calledNum, sizeof(req.phone));
                   1800:          strncpy(req.subaddr, ch->subAddress, sizeof(req.subaddr));
                   1801:          PptpCtrlNewChanState(ch, PPTP_CHAN_ST_WAIT_OUT_REPLY);
                   1802:          PptpCtrlWriteMsg(c, PPTP_OutCallRequest, &req);
                   1803:        }
                   1804:        return;
                   1805:       }
                   1806:       break;
                   1807:     default:
                   1808:       assert(0);
                   1809:   }
                   1810: }
                   1811: 
                   1812: /*
                   1813:  * PptpCtrlFindChan()
                   1814:  *
                   1815:  * Find the channel identified by this message. Returns NULL if
                   1816:  * the message is not channel specific, or the channel was not found.
                   1817:  */
                   1818: 
                   1819: static PptpChan
                   1820: PptpCtrlFindChan(PptpCtrl c, int type, void *msg, int incoming)
                   1821: {
                   1822:   PptpMsgInfo  const mi = &gPptpMsgInfo[type];
                   1823:   const char   *fname = incoming ? mi->match.inField : mi->match.outField;
                   1824:   const int    how = incoming ? mi->match.findIn : mi->match.findOut;
                   1825:   u_int16_t    cid;
                   1826:   int          k, off;
                   1827: 
                   1828:   /* Get the identifying CID field */
                   1829:   if (!fname)
                   1830:     return(NULL);
                   1831:   (void) PptpCtrlFindField(type, fname, &off);         /* we know len == 2 */
                   1832:   cid = *((u_int16_t *) ((u_char *) msg + off));
                   1833: 
                   1834:   /* Match the CID against our list of active channels */
                   1835:   for (k = 0; k < c->numChannels; k++) {
                   1836:     PptpChan   const ch = c->channels[k];
                   1837:     u_int16_t  tryCid = 0;
                   1838: 
                   1839:     if (ch == NULL)
                   1840:       continue;
                   1841:     switch (how) {
                   1842:       case PPTP_FIND_CHAN_MY_CID:
                   1843:        tryCid = ch->cid;
                   1844:        break;
                   1845:       case PPTP_FIND_CHAN_PEER_CID:
                   1846:        tryCid = ch->peerCid;
                   1847:        break;
                   1848:       case PPTP_FIND_CHAN_PNS_CID:
                   1849:        tryCid = PPTP_CHAN_IS_PNS(ch) ? ch->cid : ch->peerCid;
                   1850:        break;
                   1851:       case PPTP_FIND_CHAN_PAC_CID:
                   1852:        tryCid = !PPTP_CHAN_IS_PNS(ch) ? ch->cid : ch->peerCid;
                   1853:        break;
                   1854:       default:
                   1855:        assert(0);
                   1856:     }
                   1857:     if (cid == tryCid)
                   1858:       return(ch);
                   1859:   }
                   1860: 
                   1861:   /* Not found */
                   1862:   CLOG(LOG_INFO, "CID 0x%04x in %s not found", cid, mi->name);
                   1863:   return(NULL);
                   1864: }
                   1865: 
                   1866: /*************************************************************************
                   1867:                          MISC FUNCTIONS
                   1868: *************************************************************************/
                   1869: 
                   1870: /*
                   1871:  * PptpCtrlNewCtrlState()
                   1872:  */
                   1873: 
                   1874: static void
                   1875: PptpCtrlNewCtrlState(PptpCtrl c, int new)
                   1876: {
                   1877:   struct pptp_engine   *const pptp = c->pptp;
                   1878: 
                   1879:   assert(c->state != new);
                   1880:   CLOG(LOG_DEBUG, "ctrl state %s --> %s",
                   1881:     gPptpCtrlStates[c->state], gPptpCtrlStates[new]);
                   1882:   if (new == PPTP_CTRL_ST_FREE) {
                   1883:     pptp->ctrl[c->id] = NULL;
                   1884:     ppp_log_close(&c->log);
                   1885:     FREE(PPTP_CTRL_MTYPE, c->channels);
                   1886:     memset(c, 0, sizeof(*c));
                   1887:     FREE(PPTP_CTRL_MTYPE, c);
                   1888:     return;
                   1889:   }
                   1890:   c->state = new;
                   1891: }
                   1892: 
                   1893: /*
                   1894:  * PptpCtrlNewChanState()
                   1895:  */
                   1896: 
                   1897: static void
                   1898: PptpCtrlNewChanState(PptpChan ch, int new)
                   1899: {
                   1900:   PptpCtrl     const c = ch->ctrl;
                   1901: 
                   1902:   assert(ch->state != new);
                   1903:   CHLOG(LOG_DEBUG, "chan state %s --> %s",
                   1904:     gPptpChanStates[ch->state], gPptpChanStates[new]);
                   1905:   switch (new) {
                   1906:     case PPTP_CHAN_ST_FREE:
                   1907:       c->channels[ch->id] = NULL;
                   1908:       ppp_log_close(&ch->log);
                   1909:       memset(ch, 0, sizeof(*ch));
                   1910:       FREE(PPTP_CHAN_MTYPE, ch);
                   1911:       return;
                   1912:     case PPTP_CHAN_ST_WAIT_IN_REPLY:
                   1913:     case PPTP_CHAN_ST_WAIT_OUT_REPLY:
                   1914:     case PPTP_CHAN_ST_WAIT_CONNECT:
                   1915:     case PPTP_CHAN_ST_WAIT_DISCONNECT:
                   1916:     case PPTP_CHAN_ST_WAIT_ANSWER:
                   1917:     case PPTP_CHAN_ST_ESTABLISHED:
                   1918:     case PPTP_CHAN_ST_WAIT_CTRL:
                   1919:       break;
                   1920:   }
                   1921:   ch->state = new;
                   1922: }
                   1923: 
                   1924: /*
                   1925:  * PptpCtrlSwap()
                   1926:  *
                   1927:  * Byteswap message between host order <--> network order. Note:
                   1928:  * this relies on the fact that ntohs == htons and ntohl == htonl.
                   1929:  */
                   1930: 
                   1931: static void
                   1932: PptpCtrlSwap(int type, void *buf)
                   1933: {
                   1934:   PptpField    field = gPptpMsgLayout[type];
                   1935:   int          off;
                   1936: 
                   1937:   for (off = 0; field->name; off += field->length, field++) {
                   1938:     switch (field->length) {
                   1939:       case 4:
                   1940:        {
                   1941:          u_int32_t     *const valp = (u_int32_t *) ((u_char *) buf + off);
                   1942: 
                   1943:          *valp = ntohl(*valp);
                   1944:        }
                   1945:        break;
                   1946:       case 2:
                   1947:        {
                   1948:          u_int16_t     *const valp = (u_int16_t *) ((u_char *) buf + off);
                   1949: 
                   1950:          *valp = ntohs(*valp);
                   1951:        }
                   1952:        break;
                   1953:     }
                   1954:   }
                   1955: }
                   1956: 
                   1957: /*
                   1958:  * PptpCtrlDump()
                   1959:  *
                   1960:  * Debugging display of a control message.
                   1961:  */
                   1962: 
                   1963: #define DUMP_DING      65
                   1964: #define DUMP_MAX_DEC   100
                   1965: #define DUMP_MAX_BUF   200
                   1966: 
                   1967: static void
                   1968: PptpCtrlDump(int sev, PptpCtrl c, int type, void *msg)
                   1969: {
                   1970:   struct pptp_engine   *const pptp = c->pptp;
                   1971:   PptpField            field = gPptpMsgLayout[type];
                   1972:   char                 line[DUMP_MAX_BUF];
                   1973:   int                  off;
                   1974: 
                   1975:   for (*line = off = 0; field->name; off += field->length, field++) {
                   1976:     u_char     *data = (u_char *) msg + off;
                   1977:     char       buf[DUMP_MAX_BUF];
                   1978:     const char *fmt;
                   1979: 
                   1980:     if (!strncmp(field->name, PPTP_RESV_PREF, strlen(PPTP_RESV_PREF)))
                   1981:       continue;
                   1982:     snprintf(buf, sizeof(buf), " %s=", field->name);
                   1983:     switch (field->length) {
                   1984:       case 4:
                   1985:        fmt = (*((u_int16_t *) data) <= DUMP_MAX_DEC) ? "%d" : "0x%x";
                   1986:        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
                   1987:          fmt, *((u_int32_t *) data));
                   1988:        break;
                   1989:       case 2:
                   1990:        fmt = (*((u_int16_t *) data) <= DUMP_MAX_DEC) ? "%d" : "0x%x";
                   1991:        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
                   1992:          fmt, *((u_int16_t *) data));
                   1993:        break;
                   1994:       case 1:
                   1995:        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
                   1996:          "%d", *((u_int8_t *) data));
                   1997:        break;
                   1998:       default:
                   1999:        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
                   2000:          "\"%s\"", (char *) data);
                   2001:        break;
                   2002:     }
                   2003:     if (*line && strlen(line) + strlen(buf) > DUMP_DING) {
                   2004:       PLOG(sev, " %s", line);
                   2005:       *line = 0;
                   2006:     }
                   2007:     snprintf(line + strlen(line), sizeof(line) - strlen(line), "%s", buf);
                   2008:   }
                   2009:   if (*line)
                   2010:     PLOG(sev, " %s", line);
                   2011: }
                   2012: 
                   2013: /*
                   2014:  * PptpCtrlDumpBuf()
                   2015:  *
                   2016:  * Debugging display of a some bytes with a prefix line.
                   2017:  */
                   2018: 
                   2019: static void
                   2020: PptpCtrlDumpBuf(int sev, PptpCtrl c,
                   2021:   const void *data, size_t len, const char *fmt, ...)
                   2022: {
                   2023:   struct pptp_engine   *const pptp = c->pptp;
                   2024:   va_list args;
                   2025: 
                   2026:   va_start(args, fmt);
                   2027:   ppp_log_vput(pptp->log, sev, fmt, args);
                   2028:   va_end(args);
                   2029:   ppp_log_dump(pptp->log, sev, data, len);
                   2030: }
                   2031: 
                   2032: /*
                   2033:  * PptpCtrlFindField()
                   2034:  *
                   2035:  * Locate a field in a structure, returning length and offset (*offset).
                   2036:  * Die if field was not found.
                   2037:  */
                   2038: 
                   2039: static int
                   2040: PptpCtrlFindField(int type, const char *name, u_int *offp)
                   2041: {
                   2042:   PptpField    field = gPptpMsgLayout[type];
                   2043:   u_int                off;
                   2044: 
                   2045:   for (off = 0; field->name; off += field->length, field++) {
                   2046:     if (!strcmp(field->name, name)) {
                   2047:       *offp = off;
                   2048:       return(field->length);
                   2049:     }
                   2050:   }
                   2051:   assert(0);
                   2052:   return(0);
                   2053: }
                   2054: 
                   2055: /*
                   2056:  * PptpCtrlInitCinfo()
                   2057:  */
                   2058: 
                   2059: static void
                   2060: PptpCtrlInitCinfo(PptpChan ch, PptpCtrlInfo ci)
                   2061: {
                   2062:   PptpCtrl     const c = ch->ctrl;
                   2063: 
                   2064:   memset(ci, 0, sizeof(*ci));
                   2065:   ci->cookie = ch;
                   2066:   ci->peer_addr = c->peer_addr;
                   2067:   ci->peer_port = c->peer_port;
                   2068:   ci->close = (void (*)(void *, int, int, int))PptpCtrlCloseChan;
                   2069:   ci->answer = PptpCtrlDialResult;
                   2070: }
                   2071: 
                   2072: /*
                   2073:  * PptpCtrlExtendArray()
                   2074:  *
                   2075:  * Extend an array
                   2076:  */
                   2077: 
                   2078: static int
                   2079: PptpCtrlExtendArray(const char *mtype, void *array, int esize, int *alenp)
                   2080: {
                   2081:   void **const arrayp = (void **)array;
                   2082:   void *newa;
                   2083: 
                   2084:   if ((newa = REALLOC(mtype, *arrayp, (*alenp + 1) * esize)) == NULL)
                   2085:     return(-1);
                   2086:   *arrayp = newa;
                   2087:   memset((u_char *)*arrayp + (*alenp * esize), 0, esize);
                   2088:   (*alenp)++;
                   2089:   return(0);
                   2090: }
                   2091: 
                   2092: /*
                   2093:  * PptpCtrlGetSocket()
                   2094:  *
                   2095:  * Get and (if port != 0) bind a TCP socket.
                   2096:  */
                   2097: 
                   2098: static int
                   2099: PptpCtrlGetSocket(struct in_addr ip, u_int16_t port, char *ebuf, size_t elen)
                   2100: {
                   2101:   static const int     one = 1;
                   2102:   struct sockaddr_in   addr;
                   2103:   int                  sock;
                   2104:   int                  addr_size = sizeof(addr);
                   2105: 
                   2106:   /* Get socket */
                   2107:   if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
                   2108:     snprintf(ebuf, elen, "socket: %s", strerror(errno));
                   2109:     return(-1);
                   2110:   }
                   2111:   (void)fcntl(sock, F_SETFD, 1);
                   2112: 
                   2113:   /* Set reusable address and port */
                   2114:   if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) {
                   2115:     snprintf(ebuf, elen, "setsockopt: %s", strerror(errno));
                   2116:     (void)close(sock);
                   2117:     return(-1);
                   2118:   }
                   2119:   if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one))) {
                   2120:     snprintf(ebuf, elen, "setsockopt: %s", strerror(errno));
                   2121:     (void)close(sock);
                   2122:     return(-1);
                   2123:   }
                   2124: 
                   2125:   /* Bind socket */
                   2126:   if (port != 0) {
                   2127:     memset(&addr, 0, sizeof(addr));
                   2128:     addr.sin_family = AF_INET;
                   2129:     addr.sin_addr = ip;
                   2130:     addr.sin_port = htons(port);
                   2131:     if (bind(sock, (struct sockaddr *) &addr, addr_size) == -1) {
                   2132:       snprintf(ebuf, elen, "bind: %s", strerror(errno));
                   2133:       (void)close(sock);
                   2134:       return(-1);
                   2135:     }
                   2136:   }
                   2137: 
                   2138:   /* Done */
                   2139:   return(sock);
                   2140: }
                   2141: 
                   2142: /*************************************************************************
                   2143:                      CONTROL MESSAGE FUNCTIONS
                   2144: *************************************************************************/
                   2145: 
                   2146: /*
                   2147:  * PptpStartCtrlConnRequest()
                   2148:  */
                   2149: 
                   2150: static void
                   2151: PptpStartCtrlConnRequest(PptpCtrl c, struct pptpStartCtrlConnRequest *req)
                   2152: {
                   2153:   struct pptp_engine           *const pptp = c->pptp;
                   2154:   struct pptpStartCtrlConnReply        reply;
                   2155:   int                          k;
                   2156: 
                   2157:   /* Check for a collision */
                   2158:   if (!pptp->nocd) {
                   2159:     for (k = 0; k < pptp->nctrl; k++) {
                   2160:       PptpCtrl const c2 = pptp->ctrl[k];
                   2161:       int              iwin;
                   2162: 
                   2163:       if (c2 == NULL
                   2164:          || c2 == c
                   2165:          || c2->peer_addr.s_addr != c->peer_addr.s_addr)
                   2166:        continue;
                   2167:       iwin = (u_int32_t) ntohl(c->self_addr.s_addr)
                   2168:              > (u_int32_t) ntohl(c->peer_addr.s_addr);
                   2169:       CLOG(LOG_INFO, "collision with peer! %s", iwin ? "i win" : "peer wins");
                   2170:       if (iwin)
                   2171:        goto abort;             /* Kill this peer-initiated connection */
                   2172:       else
                   2173:        PptpCtrlKillCtrl(c2);   /* Kill the connection that I initiated */
                   2174:     }
                   2175:   }
                   2176: 
                   2177:   /* Initialize reply */
                   2178:   memset(&reply, 0, sizeof(reply));
                   2179:   reply.vers = PPTP_PROTO_VERS;
                   2180:   reply.frameCap = PPTP_FRAMECAP_SYNC;
                   2181:   reply.bearCap = PPTP_BEARCAP_ANY;
                   2182:   reply.firmware = PPTP_FIRMWARE_REV;
                   2183:   reply.result = PPTP_SCCR_RESL_OK;
                   2184:   gethostname(reply.host, sizeof(reply.host));
                   2185:   strncpy(reply.vendor, pptp->vendor, sizeof(reply.vendor));
                   2186: 
                   2187:   /* Check protocol version */
                   2188:   if (req->vers != PPTP_PROTO_VERS) {
                   2189:     CLOG(LOG_ERR, "incompatible PPTP protocol version 0x%04x", req->vers);
                   2190:     reply.result = PPTP_SCCR_RESL_VERS;
                   2191:     PptpCtrlWriteMsg(c, PPTP_StartCtrlConnReply, &reply);
                   2192: abort:
                   2193:     PptpCtrlKillCtrl(c);
                   2194:     return;
                   2195:   }
                   2196: 
                   2197:   /* OK */
                   2198:   PptpCtrlNewCtrlState(c, PPTP_CTRL_ST_ESTABLISHED);
                   2199:   PptpCtrlWriteMsg(c, PPTP_StartCtrlConnReply, &reply);
                   2200: }
                   2201: 
                   2202: /*
                   2203:  * PptpStartCtrlConnReply()
                   2204:  */
                   2205: 
                   2206: static void
                   2207: PptpStartCtrlConnReply(PptpCtrl c, struct pptpStartCtrlConnReply *rep)
                   2208: {
                   2209: 
                   2210:   /* Is peer happy? */
                   2211:   if (rep->result != PPTP_SCCR_RESL_OK) {
                   2212:     CLOG(LOG_NOTICE, "my %s failed, result=%s err=%s",
                   2213:       gPptpMsgInfo[PPTP_StartCtrlConnRequest].name,
                   2214:       PPTP_SCCR_RESL_CODE(rep->result), PPTP_ERROR_CODE(rep->err));
                   2215:     PptpCtrlKillCtrl(c);
                   2216:     return;
                   2217:   }
                   2218: 
                   2219:   /* Check peer's protocol version */
                   2220:   if (rep->vers != PPTP_PROTO_VERS) {
                   2221:     struct pptpStopCtrlConnRequest     req;
                   2222: 
                   2223:     CLOG(LOG_ERR, "incompatible PPTP protocol version 0x%04x", rep->vers);
                   2224:     memset(&req, 0, sizeof(req));
                   2225:     req.reason = PPTP_SCCR_REAS_PROTO;
                   2226:     PptpCtrlNewCtrlState(c, PPTP_CTRL_ST_WAIT_STOP_REPLY);
                   2227:     PptpCtrlWriteMsg(c, PPTP_StopCtrlConnRequest, &req);
                   2228:     return;
                   2229:   }
                   2230: 
                   2231:   /* OK */
                   2232:   PptpCtrlNewCtrlState(c, PPTP_CTRL_ST_ESTABLISHED);
                   2233:   PptpCtrlCheckConn(c);
                   2234: }
                   2235: 
                   2236: /*
                   2237:  * PptpStopCtrlConnRequest()
                   2238:  */
                   2239: 
                   2240: static void
                   2241: PptpStopCtrlConnRequest(PptpCtrl c, struct pptpStopCtrlConnRequest *req)
                   2242: {
                   2243:   struct pptpStopCtrlConnReply rep;
                   2244: 
                   2245:   CLOG(LOG_INFO, "rec'd %s: reason=%s",
                   2246:     gPptpMsgInfo[PPTP_StopCtrlConnRequest].name,
                   2247:     PPTP_SCCR_REAS_CODE(req->reason));
                   2248:   memset(&rep, 0, sizeof(rep));
                   2249:   rep.result = PPTP_SCCR_RESL_OK;
                   2250:   PptpCtrlNewCtrlState(c, PPTP_CTRL_ST_IDLE);
                   2251:   PptpCtrlWriteMsg(c, PPTP_StopCtrlConnReply, &rep);
                   2252:   PptpCtrlKillCtrl(c);
                   2253: }
                   2254: 
                   2255: /*
                   2256:  * PptpStopCtrlConnReply()
                   2257:  */
                   2258: 
                   2259: static void
                   2260: PptpStopCtrlConnReply(PptpCtrl c, struct pptpStopCtrlConnReply *rep)
                   2261: {
                   2262:   PptpCtrlKillCtrl(c);
                   2263: }
                   2264: 
                   2265: /*
                   2266:  * PptpEchoRequest()
                   2267:  */
                   2268: 
                   2269: static void
                   2270: PptpEchoRequest(PptpCtrl c, struct pptpEchoRequest *req)
                   2271: {
                   2272:   struct pptpEchoReply reply;
                   2273: 
                   2274:   memset(&reply, 0, sizeof(reply));
                   2275:   reply.id = req->id;
                   2276:   reply.result = PPTP_ECHO_RESL_OK;
                   2277:   PptpCtrlWriteMsg(c, PPTP_EchoReply, &reply);
                   2278: }
                   2279: 
                   2280: /*
                   2281:  * PptpEchoReply()
                   2282:  */
                   2283: 
                   2284: static void
                   2285: PptpEchoReply(PptpCtrl c, struct pptpEchoReply *rep)
                   2286: {
                   2287:   if (rep->result != PPTP_ECHO_RESL_OK) {
                   2288:     CLOG(LOG_NOTICE, "echo reply failed: res=%s err=%s",
                   2289:       PPTP_ECHO_RESL_CODE(rep->result), PPTP_ERROR_CODE(rep->err));
                   2290:     PptpCtrlKillCtrl(c);
                   2291:   } else if (rep->id != c->echoId) {
                   2292:     CLOG(LOG_NOTICE, "bogus echo reply: %u != %u", rep->id, c->echoId);
                   2293:     PptpCtrlKillCtrl(c);
                   2294:   }
                   2295: }
                   2296: 
                   2297: /*
                   2298:  * PptpOutCallRequest()
                   2299:  */
                   2300: 
                   2301: static void
                   2302: PptpOutCallRequest(PptpCtrl c, struct pptpOutCallRequest *req)
                   2303: {
                   2304:   struct pptp_engine           *const pptp = c->pptp;
                   2305:   struct pptpOutCallReply      reply;
                   2306:   struct pptpctrlinfo          cinfo;
                   2307:   struct pptplinkinfo          linfo;
                   2308:   PptpChan                     ch = NULL;
                   2309:   char                         calledNum[PPTP_PHONE_LEN + 1];
                   2310:   char                         subAddress[PPTP_SUBADDR_LEN + 1];
                   2311: 
                   2312:   /* Does link allow this? */
                   2313:   if (pptp->get_out_link == NULL)
                   2314:     goto denied;
                   2315: 
                   2316:   /* Copy out fields */
                   2317:   strncpy(calledNum, req->phone, sizeof(calledNum) - 1);
                   2318:   calledNum[sizeof(calledNum) - 1] = 0;
                   2319:   strncpy(subAddress, req->subaddr, sizeof(subAddress) - 1);
                   2320:   subAddress[sizeof(subAddress) - 1] = 0;
                   2321: 
                   2322:   /* Get a data channel */
                   2323:   if ((ch = PptpCtrlGetChan(c, PPTP_CHAN_ST_WAIT_ANSWER, FALSE, FALSE,
                   2324:       req->bearType, req->frameType, req->minBps, req->maxBps,
                   2325:       PPTP_STR_INTERNAL_CALLING, calledNum, subAddress)) == NULL) {
                   2326:     CLOG(LOG_ERR, "can't get channel for %s call", "outgoing");
                   2327:     goto chFail;
                   2328:   }
                   2329: 
                   2330:   /* Fill in details */
                   2331:   ch->serno = req->serno;
                   2332:   ch->peerCid = req->cid;
                   2333:   ch->peerPpd = req->ppd;
                   2334:   ch->recvWin = req->recvWin;
                   2335: 
                   2336:   /* Ask link layer about making the outgoing call */
                   2337:   PptpCtrlInitCinfo(ch, &cinfo);
                   2338:   linfo = (*pptp->get_out_link)(pptp->arg,
                   2339:     cinfo, c->peer_addr, c->peer_port, req->bearType,
                   2340:     req->frameType, req->minBps, req->maxBps, calledNum, subAddress);
                   2341:   if (linfo.cookie == NULL || linfo.cancel == NULL || linfo.result == NULL)
                   2342:     goto denied;
                   2343: 
                   2344:   /* Link layer says it's OK; wait for link layer to report back later */
                   2345:   ch->linfo = linfo;
                   2346:   return;
                   2347: 
                   2348:   /* Failed */
                   2349: denied:
                   2350:   CLOG(LOG_NOTICE, "peer's %s call request was denied", "outgoing");
                   2351:   if (ch)
                   2352:     PptpCtrlNewChanState(ch, PPTP_CHAN_ST_FREE);
                   2353: chFail:
                   2354:   memset(&reply, 0, sizeof(reply));
                   2355:   reply.peerCid = req->cid;
                   2356:   reply.result = PPTP_OCR_RESL_ADMIN;
                   2357:   PptpCtrlWriteMsg(c, PPTP_OutCallReply, &reply);
                   2358: }
                   2359: 
                   2360: /*
                   2361:  * PptpOutCallReply()
                   2362:  */
                   2363: 
                   2364: static void
                   2365: PptpOutCallReply(PptpChan ch, struct pptpOutCallReply *reply)
                   2366: {
                   2367:   /* Did call go through? */
                   2368:   if (reply->result != PPTP_OCR_RESL_OK) {
                   2369:     char       errmsg[100];
                   2370: 
                   2371:     snprintf(errmsg, sizeof(errmsg),
                   2372:       "outgoing call failed: res=%s err=%s",
                   2373:       PPTP_OCR_RESL_CODE(reply->result), PPTP_ERROR_CODE(reply->err));
                   2374:     CHLOG(LOG_NOTICE, "%s", errmsg);
                   2375:     (*ch->linfo.result)(ch->linfo.cookie, errmsg);
                   2376:     PptpCtrlKillChan(ch, "remote outgoing call failed");
                   2377:     return;
                   2378:   }
                   2379: 
                   2380:   /* Call succeeded */
                   2381:   ch->peerPpd = reply->ppd;
                   2382:   ch->recvWin = reply->recvWin;
                   2383:   ch->peerCid = reply->cid;
                   2384:   CHLOG(LOG_INFO, "outgoing call connected at %d bps", reply->speed);
                   2385:   PptpCtrlNewChanState(ch, PPTP_CHAN_ST_ESTABLISHED);
                   2386:   (*ch->linfo.result)(ch->linfo.cookie, NULL);
                   2387: }
                   2388: 
                   2389: /*
                   2390:  * PptpInCallRequest()
                   2391:  */
                   2392: 
                   2393: static void
                   2394: PptpInCallRequest(PptpCtrl c, struct pptpInCallRequest *req)
                   2395: {
                   2396:   struct pptp_engine           *const pptp = c->pptp;
                   2397:   struct pptpInCallReply       reply;
                   2398:   struct pptpctrlinfo          cinfo;
                   2399:   struct pptplinkinfo          linfo;
                   2400:   PptpChan                     ch;
                   2401:   char                         callingNum[PPTP_PHONE_LEN + 1];
                   2402:   char                         calledNum[PPTP_PHONE_LEN + 1];
                   2403:   char                         subAddress[PPTP_SUBADDR_LEN + 1];
                   2404: 
                   2405:   /* Copy out fields */
                   2406:   if (req->dialedLen > PPTP_PHONE_LEN)
                   2407:     req->dialedLen = PPTP_PHONE_LEN;
                   2408:   if (req->dialingLen > PPTP_PHONE_LEN)
                   2409:     req->dialingLen = PPTP_PHONE_LEN;
                   2410:   strncpy(callingNum, req->dialing, sizeof(callingNum) - 1);
                   2411:   callingNum[req->dialingLen] = 0;
                   2412:   strncpy(calledNum, req->dialed, sizeof(calledNum) - 1);
                   2413:   calledNum[req->dialedLen] = 0;
                   2414:   strncpy(subAddress, req->subaddr, sizeof(subAddress) - 1);
                   2415:   subAddress[sizeof(subAddress) - 1] = 0;
                   2416: 
                   2417:   CLOG(LOG_INFO, "peer incoming call to \"%s\" from \"%s\"",
                   2418:     calledNum, callingNum);
                   2419: 
                   2420:   /* Initialize reply */
                   2421:   memset(&reply, 0, sizeof(reply));
                   2422:   reply.peerCid = req->cid;
                   2423:   reply.recvWin = PPTP_RECV_WIN;       /* XXX */
                   2424:   reply.ppd = PPTP_PPD;                        /* XXX */
                   2425: 
                   2426:   /* Get a data channel */
                   2427:   if ((ch = PptpCtrlGetChan(c, PPTP_CHAN_ST_WAIT_CONNECT, FALSE, TRUE,
                   2428:       req->bearType, 0, 0, INT_MAX,
                   2429:       callingNum, calledNum, subAddress)) == NULL) {
                   2430:     CLOG(LOG_ERR, "can't get channel for %s call", "incoming");
                   2431:     reply.result = PPTP_ICR_RESL_ERR;
                   2432:     reply.err = PPTP_ERROR_NO_RESOURCE;
                   2433:     goto done;
                   2434:   }
                   2435:   reply.cid = ch->cid;
                   2436: 
                   2437:   /* Fill in details */
                   2438:   ch->serno = req->serno;
                   2439:   ch->peerCid = req->cid;
                   2440:   ch->bearType = req->bearType;
                   2441: 
                   2442:   /* Ask link layer about accepting the incoming call */
                   2443:   PptpCtrlInitCinfo(ch, &cinfo);
                   2444:   linfo.cookie = NULL;
                   2445:   if (pptp->get_in_link != NULL)
                   2446:     linfo = (*pptp->get_in_link)(pptp->arg, cinfo, c->peer_addr, c->peer_port,
                   2447:       req->bearType, callingNum, calledNum, subAddress);
                   2448:   if (linfo.cookie == NULL) {
                   2449:     CLOG(LOG_NOTICE, "peer's %s call request was denied", "incoming");
                   2450:     reply.result = PPTP_ICR_RESL_NAK;
                   2451:     goto done;
                   2452:   }
                   2453: 
                   2454:   /* Link layer says it's OK */
                   2455:   CHLOG(LOG_INFO, "accepting incoming call to \"%s\" from \"%s\"",
                   2456:     calledNum, callingNum);
                   2457:   reply.result = PPTP_ICR_RESL_OK;
                   2458:   ch->linfo = linfo;
                   2459:   strncpy(ch->callingNum, req->dialing, sizeof(ch->callingNum));
                   2460:   strncpy(ch->calledNum, req->dialed, sizeof(ch->calledNum));
                   2461:   strncpy(ch->subAddress, req->subaddr, sizeof(ch->subAddress));
                   2462: 
                   2463:   /* Return result */
                   2464: done:
                   2465:   PptpCtrlWriteMsg(c, PPTP_InCallReply, &reply);
                   2466:   if (reply.result != PPTP_ICR_RESL_OK)
                   2467:     PptpCtrlKillChan(ch, "peer incoming call failed");
                   2468: }
                   2469: 
                   2470: /*
                   2471:  * PptpInCallReply()
                   2472:  */
                   2473: 
                   2474: static void
                   2475: PptpInCallReply(PptpChan ch, struct pptpInCallReply *reply)
                   2476: {
                   2477:   PptpCtrl             const c = ch->ctrl;
                   2478:   struct pptpInCallConn        con;
                   2479: 
                   2480:   /* Did call go through? */
                   2481:   if (reply->result != PPTP_ICR_RESL_OK) {
                   2482:     char       errmsg[100];
                   2483: 
                   2484:     snprintf(errmsg, sizeof(errmsg),
                   2485:       "peer denied incoming call: res=%s err=%s",
                   2486:       PPTP_ICR_RESL_CODE(reply->result), PPTP_ERROR_CODE(reply->err));
                   2487:     CHLOG(LOG_NOTICE, "%s", errmsg);
                   2488:     (*ch->linfo.result)(ch->linfo.cookie, errmsg);
                   2489:     PptpCtrlKillChan(ch, "peer denied incoming call");
                   2490:     return;
                   2491:   }
                   2492: 
                   2493:   /* Call succeeded */
                   2494:   CHLOG(LOG_INFO, "incoming call accepted by peer");
                   2495:   ch->peerCid = reply->cid;
                   2496:   ch->peerPpd = reply->ppd;
                   2497:   ch->recvWin = reply->recvWin;
                   2498:   PptpCtrlNewChanState(ch, PPTP_CHAN_ST_ESTABLISHED);
                   2499:   (*ch->linfo.result)(ch->linfo.cookie, NULL);
                   2500: 
                   2501:   /* Send back connected message */
                   2502:   memset(&con, 0, sizeof(con));
                   2503:   con.peerCid = reply->cid;
                   2504:   con.speed = 64000;                   /* XXX */
                   2505:   con.recvWin = PPTP_RECV_WIN;         /* XXX */
                   2506:   con.ppd = PPTP_PPD;                  /* XXX */
                   2507:   con.frameType = PPTP_FRAMECAP_SYNC;
                   2508:   PptpCtrlWriteMsg(c, PPTP_InCallConn, &con);
                   2509: }
                   2510: 
                   2511: /*
                   2512:  * PptpInCallConn()
                   2513:  */
                   2514: 
                   2515: static void
                   2516: PptpInCallConn(PptpChan ch, struct pptpInCallConn *con)
                   2517: {
                   2518:   CHLOG(LOG_INFO, "peer incoming call connected at %d bps", con->speed);
                   2519:   ch->peerPpd = con->ppd;
                   2520:   ch->recvWin = con->recvWin;
                   2521:   ch->frameType = con->frameType;
                   2522:   (*ch->linfo.result)(ch->linfo.cookie, NULL);
                   2523:   PptpCtrlNewChanState(ch, PPTP_CHAN_ST_ESTABLISHED);
                   2524: }
                   2525: 
                   2526: /*
                   2527:  * PptpCallClearRequest()
                   2528:  */
                   2529: 
                   2530: static void
                   2531: PptpCallClearRequest(PptpChan ch, struct pptpCallClearRequest *req)
                   2532: {
                   2533:   struct pptpCallDiscNotify    notify;
                   2534:   PptpCtrl                     const c = ch->ctrl;
                   2535: 
                   2536:   if (PPTP_CHAN_IS_PNS(ch)) {
                   2537:     CHLOG(LOG_NOTICE, "rec'd %s, but we are PNS for this call",
                   2538:       gPptpMsgInfo[PPTP_CallClearRequest].name);
                   2539:     PptpCtrlKillCtrl(c);
                   2540:     return;
                   2541:   }
                   2542:   CHLOG(LOG_INFO, "call cleared by peer");
                   2543:   memset(&notify, 0, sizeof(notify));
                   2544:   notify.cid = ch->cid;                        /* we are the PAC, use our CID */
                   2545:   notify.result = PPTP_CDN_RESL_REQ;
                   2546:   /* XXX stats? */
                   2547:   PptpCtrlWriteMsg(c, PPTP_CallDiscNotify, &notify);
                   2548:   PptpCtrlKillChan(ch, "cleared by peer");
                   2549: }
                   2550: 
                   2551: /*
                   2552:  * PptpCallDiscNotify()
                   2553:  */
                   2554: 
                   2555: static void
                   2556: PptpCallDiscNotify(PptpChan ch, struct pptpCallDiscNotify *notify)
                   2557: {
                   2558:   CHLOG(LOG_INFO, "peer call disconnected res=%s err=%s",
                   2559:     PPTP_CDN_RESL_CODE(notify->result), PPTP_ERROR_CODE(notify->err));
                   2560:   PptpCtrlKillChan(ch, "disconnected by peer");
                   2561: }
                   2562: 
                   2563: /*
                   2564:  * PptpWanErrorNotify()
                   2565:  */
                   2566: 
                   2567: static void
                   2568: PptpWanErrorNotify(PptpChan ch, struct pptpWanErrorNotify *notif)
                   2569: {
                   2570:   CHLOG(LOG_DEBUG, "ignoring %s", gPptpMsgInfo[PPTP_WanErrorNotify].name);
                   2571: }
                   2572: 
                   2573: /*
                   2574:  * PptpSetLinkInfo()
                   2575:  */
                   2576: 
                   2577: static void
                   2578: PptpSetLinkInfo(PptpChan ch, struct pptpSetLinkInfo *info)
                   2579: {
                   2580:   if (ch->linfo.setLinkInfo)
                   2581:     (*ch->linfo.setLinkInfo)(ch->linfo.cookie, info->sendAccm, info->recvAccm);
                   2582:   else {
                   2583:     CHLOG(LOG_DEBUG, "ignoring %s", gPptpMsgInfo[PPTP_SetLinkInfo].name);
                   2584:   }
                   2585: }
                   2586: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>