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(¬ify, 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, ¬ify);
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>