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