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