Annotation of embedaddon/mpd/src/pptp_ctrl.c, revision 1.1.1.3

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

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