Annotation of embedaddon/libpdel/ppp/ppp_pptp_server.c, revision 1.1.1.1
1.1 misho 1:
2: /*
3: * Copyright (c) 2001-2002 Packet Design, LLC.
4: * All rights reserved.
5: *
6: * Subject to the following obligations and disclaimer of warranty,
7: * use and redistribution of this software, in source or object code
8: * forms, with or without modifications are expressly permitted by
9: * Packet Design; provided, however, that:
10: *
11: * (i) Any and all reproductions of the source or object code
12: * must include the copyright notice above and the following
13: * disclaimer of warranties; and
14: * (ii) No rights are granted, in any manner or form, to use
15: * Packet Design trademarks, including the mark "PACKET DESIGN"
16: * on advertising, endorsements, or otherwise except as such
17: * appears in the above copyright notice or in the software.
18: *
19: * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
20: * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
21: * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
22: * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
23: * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
24: * OR NON-INFRINGEMENT. PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
25: * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
26: * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
27: * RELIABILITY OR OTHERWISE. IN NO EVENT SHALL PACKET DESIGN BE
28: * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
29: * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
30: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
31: * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
32: * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
33: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
35: * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
36: * THE POSSIBILITY OF SUCH DAMAGE.
37: *
38: * Author: Archie Cobbs <archie@freebsd.org>
39: */
40:
41: #include "ppp/ppp_defs.h"
42: #include "ppp/ppp_log.h"
43: #include "ppp/ppp_engine.h"
44: #include "ppp/ppp_fsm_option.h"
45: #include "ppp/ppp_auth.h"
46: #include "ppp/ppp_lcp.h"
47: #include "ppp/ppp_link.h"
48: #include "ppp/ppp_channel.h"
49: #include "ppp/ppp_pptp_server.h"
50: #include "ppp/ppp_pptp_ctrl.h"
51: #include "ppp/ppp_pptp_ctrl_defs.h"
52:
53: #include <net/ethernet.h>
54: #include <netgraph/ng_pptpgre.h>
55: #include <netinet/in_systm.h>
56: #include <netinet/ip.h>
57:
58: #define PPTP_MTYPE "ppp_pptp"
59: #define PPTP_OUTPUT_MTYPE "ppp_pptp.output"
60: #define PPTP_DEVICE_MTYPE "ppp_pptp.device"
61: #define PPTP_PEER_MTYPE "ppp_pptp.peer"
62:
63: #if 0 /* win2k seems to require at least 1500 */
64: #define PPTP_MRU \
65: (ETHER_MAX_LEN /* standard ethernet frame */ \
66: - ETHER_CRC_LEN /* ethernet crc */ \
67: - ETHER_HDR_LEN /* ethernet header */ \
68: - sizeof(struct ip) /* ip header */ \
69: - 16 /* gre header */ \
70: - 2) /* ppp address & control fields */
71: #else
72: #define PPTP_MRU LCP_DEFAULT_MRU
73: #endif
74:
75: #define PPTP_MRRU LCP_DEFAULT_MRRU
76:
77: #define PPTPGRE_ALWAYS_ACK 1
78:
79: /* PPTP server info */
80: struct pptp_server {
81: struct ppp_pptp_server_info info; /* client info */
82: struct ppp_log *log; /* log */
83: struct ppp_engine *engine;/* associated ppp engine */
84: struct pptp_engine *pptp; /* pptp control engine */
85: struct pevent_ctx *ev_ctx;/* event context */
86: pthread_mutex_t *mutex; /* mutex */
87: struct in_addr ip; /* my ip address */
88: u_int16_t port; /* my port */
89: u_char shutdown;/* server is shutdown */
90: u_int npeers; /* number of extant devices */
91: };
92:
93: /* Remote peer info */
94: struct ppp_pptp_peer {
95: struct pptp_server *s; /* back pointer to server */
96: struct ppp_channel *chan; /* back pointer to channel */
97: struct pptpctrlinfo cinfo; /* pptp control channel info */
98: struct nodeinfo ninfo; /* ng_pptpgre(4) node info */
99: struct pevent *answer; /* pptp answer event */
100: char path[32]; /* pptpgre node path */
101: char logname[32]; /* peer logname */
102: void *carg; /* client callback arg */
103: struct in_addr ip; /* peer remote ip address */
104: u_int16_t port; /* peer remote port */
105: u_char closed; /* closed by client side */
106: };
107:
108: /* PPTP control callbacks */
109: static PptpCheckNewConn_t ppp_pptp_server_check_new_conn;
110: static PptpGetInLink_t ppp_pptp_server_get_in_link;
111: static PptpGetOutLink_t ppp_pptp_server_get_out_link;
112:
113: /* Device methods */
114: static ppp_channel_open_t ppp_pptp_server_device_open;
115: static ppp_channel_close_t ppp_pptp_server_device_close;
116: static ppp_channel_destroy_t ppp_pptp_server_device_destroy;
117: static ppp_channel_free_output_t ppp_pptp_server_device_free_output;
118: static ppp_channel_set_link_info_t ppp_pptp_server_device_set_link_info;
119: static ppp_channel_get_origination_t ppp_pptp_server_device_get_origination;
120: static ppp_channel_get_node_t ppp_pptp_server_device_get_node;
121: static ppp_channel_get_hook_t ppp_pptp_server_device_get_hook;
122: static ppp_channel_is_async_t ppp_pptp_server_device_is_async;
123: static ppp_channel_get_mtu_t ppp_pptp_server_device_get_mtu;
124: static ppp_channel_get_acfcomp_t ppp_pptp_server_device_get_acfcomp;
125: static ppp_channel_get_pfcomp_t ppp_pptp_server_device_get_pfcomp;
126:
127: static struct ppp_channel_meth ppp_pptp_server_device_meth = {
128: ppp_pptp_server_device_open,
129: ppp_pptp_server_device_close,
130: ppp_pptp_server_device_destroy,
131: ppp_pptp_server_device_free_output,
132: ppp_pptp_server_device_set_link_info,
133: ppp_pptp_server_device_get_origination,
134: ppp_pptp_server_device_get_node,
135: ppp_pptp_server_device_get_hook,
136: ppp_pptp_server_device_is_async,
137: ppp_pptp_server_device_get_mtu,
138: ppp_pptp_server_device_get_acfcomp,
139: ppp_pptp_server_device_get_pfcomp,
140: };
141:
142: /* Other internal functions */
143: static struct ppp_pptp_peer *ppp_pptp_server_new_peer(struct pptp_server *s,
144: struct in_addr ip, u_int16_t port,
145: const struct pptpctrlinfo *cinfo);
146: static void ppp_pptp_server_device_output(struct ppp_pptp_peer *peer,
147: enum ppp_channeloutput type, ...);
148:
149: static void ppp_pptp_server_cancel(void *cookie);
150: static void ppp_pptp_server_result(void *cookie, const char *errmsg);
151:
152: static pevent_handler_t ppp_pptp_server_answer;
153:
154: /* Macro for logging */
155: #define LOG(sev, fmt, args...) PPP_LOG(s->log, sev, fmt , ## args)
156:
157: /***********************************************************************
158: PUBLIC FUNCTIONS
159: ***********************************************************************/
160:
161: /*
162: * Start the PPTP server associated with a ppp engine.
163: */
164: int
165: ppp_pptp_server_start(struct ppp_engine *engine,
166: const struct ppp_pptp_server_info *info,
167: struct in_addr ip, u_int16_t port, u_int max_conn)
168: {
169: struct ppp_log *const elog = ppp_engine_get_log(engine);
170: struct pptp_server *s;
171:
172: /* Sanity */
173: if (engine == NULL || info->arg == NULL) {
174: errno = EINVAL;
175: return (-1);
176: }
177:
178: /* See if server already exists */
179: if ((s = ppp_engine_get_pptp_server(engine)) != NULL) {
180: errno = EALREADY;
181: return (-1);
182: }
183:
184: /* Create new server */
185: if ((s = MALLOC(PPTP_MTYPE, sizeof(*s))) == NULL)
186: return (-1);
187: memset(s, 0, sizeof(*s));
188: s->engine = engine;
189: s->ev_ctx = ppp_engine_get_ev_ctx(engine);
190: s->mutex = ppp_engine_get_mutex(engine);
191: s->log = ppp_log_dup(elog);
192: s->info = *info;
193: s->ip = ip;
194: s->port = port;
195:
196: /* Start PPTP */
197: if ((s->pptp = PptpCtrlInit(s, s->ev_ctx, s->mutex,
198: ppp_pptp_server_check_new_conn, ppp_pptp_server_get_in_link,
199: ppp_pptp_server_get_out_link, ip, port, info->vendor,
200: ppp_log_dup(elog), 1)) == NULL) {
201: ppp_log_put(elog, LOG_ERR, "failed to initialize pptp");
202: FREE(PPTP_MTYPE, s);
203: return (-1);
204: }
205:
206: /* Enable incoming connections */
207: if (PptpCtrlListen(s->pptp, 1) == -1) {
208: ppp_log_put(elog, LOG_ERR, "failed start pptp server");
209: PptpCtrlShutdown(&s->pptp);
210: FREE(PPTP_MTYPE, s);
211: return (-1);
212: }
213:
214: /* Done */
215: ppp_engine_set_pptp_server(engine, s);
216: return (0);
217: }
218:
219: /*
220: * Stop the PPTP server associated with a ppp engine.
221: *
222: * We can't completely destroy it, because there may be PPTP devices
223: * in use by ppp_link's that still exist. The ppp_link's are responsible
224: * for destroying their devices, not us.
225: */
226: void
227: ppp_pptp_server_stop(struct ppp_engine *engine)
228: {
229: struct pptp_server *s;
230:
231: if ((s = ppp_engine_get_pptp_server(engine)) == NULL)
232: return;
233: ppp_engine_set_pptp_server(s->engine, NULL);
234: PptpCtrlShutdown(&s->pptp);
235: if (s->npeers == 0) {
236: ppp_log_close(&s->log);
237: FREE(PPTP_MTYPE, s);
238: return;
239: }
240:
241: /* Wait for all devices to be destroyed */
242: s->shutdown = 1;
243: }
244:
245: /*
246: * Close a PPTP connection.
247: */
248: void
249: ppp_pptp_server_close(struct ppp_engine *engine, struct ppp_pptp_peer **peerp)
250: {
251: struct ppp_pptp_peer *const peer = *peerp;
252:
253: if (peer == NULL)
254: return;
255: *peerp = NULL;
256: peer->carg = NULL; /* don't call client 'destroy' method */
257: ppp_pptp_server_device_close(peer->chan);
258: }
259:
260: /*
261: * Get the client handle for the PPTP channel associated with a device.
262: */
263: void *
264: ppp_pptp_server_get_client_info(struct ppp_channel *chan)
265: {
266: struct ppp_pptp_peer *const peer = chan->priv;
267:
268: if (chan->meth != &ppp_pptp_server_device_meth) {
269: errno = EINVAL;
270: return (NULL);
271: }
272: if (peer->carg == NULL)
273: errno = ENXIO;
274: return (peer->carg);
275: }
276:
277: /***********************************************************************
278: PPTP CONTROL CALLBACKS
279: ***********************************************************************/
280:
281: static int
282: ppp_pptp_server_check_new_conn(void *arg, struct in_addr ip,
283: u_int16_t port, char *logname, size_t max)
284: {
285: struct pptp_server *const s = arg;
286:
287: if (s->info.getlogname != NULL)
288: (*s->info.getlogname)(s->info.arg, ip, port, logname, max);
289: return (0);
290: }
291:
292: static struct pptplinkinfo
293: ppp_pptp_server_get_in_link(void *arg, struct pptpctrlinfo cinfo,
294: struct in_addr ip, u_int16_t port, int bearType,
295: const char *callingNum, const char *calledNum, const char *subAddress)
296: {
297: struct pptp_server *const s = arg;
298: struct pptplinkinfo info;
299: struct ppp_pptp_peer *peer;
300:
301: /* Create new peer */
302: memset(&info, 0, sizeof(info));
303: if ((peer = ppp_pptp_server_new_peer(s, ip, port, &cinfo)) == NULL)
304: return (info);
305:
306: /* Fill in response */
307: info.cookie = peer;
308: info.cancel = ppp_pptp_server_cancel;
309: info.result = ppp_pptp_server_result;
310:
311: /* Output 'up' message */
312: ppp_pptp_server_device_output(peer, PPP_CHANNEL_OUTPUT_UP);
313:
314: /* Done */
315: return (info);
316: }
317:
318: static struct pptplinkinfo
319: ppp_pptp_server_get_out_link(void *arg, struct pptpctrlinfo cinfo,
320: struct in_addr ip, u_int16_t port, int bearType, int frameType,
321: int minBps, int maxBps, const char *calledNum, const char *subAddress)
322: {
323: struct pptp_server *const s = arg;
324: struct pptplinkinfo info;
325: struct ppp_pptp_peer *peer;
326:
327: /* Create new peer */
328: memset(&info, 0, sizeof(info));
329: if ((peer = ppp_pptp_server_new_peer(s, ip, port, &cinfo)) == NULL)
330: return (info);
331:
332: /* Set up to 'answer' the outgoing call (but not reentrantly) */
333: pevent_unregister(&peer->answer);
334: if (pevent_register(s->ev_ctx, &peer->answer, 0, s->mutex,
335: ppp_pptp_server_answer, peer, PEVENT_TIME, 0) == -1) {
336: LOG(LOG_ERR, "pevent_register: %m");
337: return (info);
338: }
339:
340: /* Fill in response */
341: info.cookie = peer;
342: info.cancel = ppp_pptp_server_cancel;
343: info.result = ppp_pptp_server_result;
344:
345: /* Done */
346: return (info);
347: }
348:
349: static void
350: ppp_pptp_server_result(void *cookie, const char *errmsg)
351: {
352: struct ppp_pptp_peer *const peer = cookie;
353: struct pptp_server *const s = peer->s;
354:
355: LOG(LOG_INFO, "call from %s terminated: %s", peer->logname, errmsg);
356: peer->cinfo.cookie = NULL; /* don't call cinfo close() method */
357: ppp_pptp_server_device_close(peer->chan);
358: }
359:
360: static void
361: ppp_pptp_server_cancel(void *cookie)
362: {
363: struct ppp_pptp_peer *const peer = cookie;
364:
365: (void)peer;
366: assert(0);
367: }
368:
369: /***********************************************************************
370: INTERNAL FUNCTIONS
371: ***********************************************************************/
372:
373: /*
374: * Create a new PPTP peer object corresponding to a PPTP channel
375: * and start up a new PPP link/bundle.
376: */
377: static struct ppp_pptp_peer *
378: ppp_pptp_server_new_peer(struct pptp_server *s, struct in_addr ip,
379: u_int16_t port, const struct pptpctrlinfo *cinfo)
380: {
381: union {
382: u_char repbuf[sizeof(struct ng_mesg) + sizeof(struct nodeinfo)];
383: struct ng_mesg reply;
384: } repbuf;
385: struct ng_mesg *reply = &repbuf.reply;
386: struct ppp_link_config link_config;
387: struct ng_pptpgre_conf greconf;
388: struct ppp_pptp_peer *peer = NULL;
389: struct ppp_auth_config auth;
390: struct ppp_log *log = NULL;
391: struct in_addr pptp_ip[2];
392: struct ngm_mkpeer mkpeer;
393: struct ngm_rmhook rmhook;
394: int csock = -1;
395: int esave;
396:
397: /* Create peer info structure */
398: if ((peer = MALLOC(PPTP_PEER_MTYPE, sizeof(*peer))) == NULL) {
399: LOG(LOG_ERR, "can't allocate new device: %m");
400: goto fail;
401: }
402: memset(peer, 0, sizeof(*peer));
403: peer->s = s;
404: peer->cinfo = *cinfo;
405: peer->ip = ip;
406: peer->port = port;
407:
408: /* Create ng_pptpgre(4) node */
409: if (NgMkSockNode(NULL, &csock, NULL) == -1) {
410: LOG(LOG_ERR, "can't create socket node: %m");
411: goto fail;
412: }
413: memset(&mkpeer, 0, sizeof(mkpeer));
414: strlcpy(mkpeer.type, NG_PPTPGRE_NODE_TYPE, sizeof(mkpeer.type));
415: strlcpy(mkpeer.ourhook, NG_PPTPGRE_HOOK_UPPER, sizeof(mkpeer.ourhook));
416: strlcpy(mkpeer.peerhook,
417: NG_PPTPGRE_HOOK_UPPER, sizeof(mkpeer.peerhook));
418: if (NgSendMsg(csock, ".",
419: NGM_GENERIC_COOKIE, NGM_MKPEER, &mkpeer, sizeof(mkpeer)) == -1) {
420: LOG(LOG_ERR, "can't create pptpgre node: %m");
421: goto fail;
422: }
423: snprintf(peer->path, sizeof(peer->path), "%s", NG_PPTPGRE_HOOK_UPPER);
424:
425: /* Get node info including 'id' and create absolute path for node */
426: if (NgSendMsg(csock, NG_PPTPGRE_HOOK_UPPER,
427: NGM_GENERIC_COOKIE, NGM_NODEINFO, NULL, 0) == -1) {
428: LOG(LOG_ERR, "can't get node info: %m");
429: goto fail;
430: }
431: memset(&repbuf, 0, sizeof(repbuf));
432: if (NgRecvMsg(csock, reply, sizeof(repbuf), NULL) == -1) {
433: LOG(LOG_ERR, "can't read node info: %m");
434: goto fail;
435: }
436: memcpy(&peer->ninfo, reply->data, sizeof(peer->ninfo));
437: snprintf(peer->path, sizeof(peer->path),
438: "[%lx]:", (long)peer->ninfo.id);
439:
440: /* Check with client library */
441: strlcpy(peer->logname, inet_ntoa(ip), sizeof(peer->logname));
442: memset(&auth, 0, sizeof(auth));
443: if ((peer->carg = (*s->info.admit)(s->info.arg, peer, ip, port,
444: &auth, peer->logname, sizeof(peer->logname))) == NULL)
445: goto fail;
446:
447: /* Get PPTP session info */
448: memset(&greconf, 0, sizeof(greconf));
449: if (PptpCtrlGetSessionInfo(cinfo, &pptp_ip[PPP_SELF],
450: &pptp_ip[PPP_PEER], &greconf.cid, &greconf.peerCid,
451: &greconf.recvWin, &greconf.peerPpd) == -1) {
452: LOG(LOG_ERR, "can't get pptp session info: %m");
453: goto fail;
454: }
455:
456: /* Configure pptpgre node */
457: greconf.enabled = 1;
458: greconf.enableDelayedAck = 1;
459: #if PPTPGRE_ALWAYS_ACK
460: greconf.enableAlwaysAck = 1;
461: #endif
462: if (NgSendMsg(csock, peer->path, NGM_PPTPGRE_COOKIE,
463: NGM_PPTPGRE_SET_CONFIG, &greconf, sizeof(greconf)) == -1) {
464: LOG(LOG_ERR, "can't configure pptpgre node: %m");
465: goto fail;
466: }
467:
468: /* Plumb the 'lower' side of the ng_pptpgre(4) node */
469: if ((*s->info.plumb)(s->info.arg,
470: peer->carg, peer->path, NG_PPTPGRE_HOOK_LOWER, pptp_ip) == -1) {
471: LOG(LOG_ERR, "error plumbing node: %m");
472: goto fail;
473: }
474:
475: /* Disconnect from the node so the link can connect to it */
476: memset(&rmhook, 0, sizeof(rmhook));
477: strlcpy(rmhook.ourhook, NG_PPTPGRE_HOOK_UPPER, sizeof(rmhook.ourhook));
478: if (NgSendMsg(csock, ".", NGM_GENERIC_COOKIE,
479: NGM_RMHOOK, &rmhook, sizeof(rmhook)) == -1) {
480: LOG(LOG_ERR, "can't unhook from node: %m");
481: goto fail;
482: }
483:
484: /* Create a new PPP device for this pptp connection */
485: if ((peer->chan = MALLOC(PPTP_DEVICE_MTYPE,
486: sizeof(*peer->chan))) == NULL) {
487: LOG(LOG_ERR, "can't allocate new channel: %m");
488: goto fail;
489: }
490: memset(peer->chan, 0, sizeof(*peer->chan));
491: peer->chan->meth = &ppp_pptp_server_device_meth;
492: peer->chan->priv = peer;
493:
494: /* Create device output message port */
495: if ((peer->chan->outport
496: = mesg_port_create("ppp_pptp_server")) == NULL) {
497: LOG(LOG_ERR, "can't create mesg_port: %m");
498: goto fail;
499: }
500:
501: /* Create log for the new link by prefixing the engine's log */
502: if ((log = ppp_engine_get_log(s->engine)) != NULL
503: && (log = ppp_log_prefix(log, "%s: ", peer->logname)) == NULL) {
504: LOG(LOG_ERR, "can't create link log: %m");
505: goto fail;
506: }
507:
508: /* Configure new link */
509: memset(&link_config, 0, sizeof(link_config));
510: link_config.auth = auth;
511: link_config.max_self_mru = PPTP_MRU;
512: link_config.max_self_mrru = PPTP_MRRU;
513: link_config.multilink = 1;
514: link_config.eid.class = PPP_EID_CLASS_IP;
515: link_config.eid.length = sizeof(s->ip);
516: memcpy(link_config.eid.value, &s->ip, sizeof(s->ip));
517:
518: /* Add new link to the PPP engine */
519: if (ppp_link_create(s->engine, peer->chan, &link_config, log) == -1) {
520: LOG(LOG_ERR, "can't create link: %m");
521: goto fail;
522: }
523: log = NULL;
524:
525: /* Done */
526: (void)close(csock);
527: s->npeers++;
528: return (peer);
529:
530: fail:
531: /* Clean up after failure */
532: esave = errno;
533: ppp_log_close(&log);
534: if (peer != NULL) {
535: if (peer->carg != NULL)
536: (*s->info.destroy)(s->info.arg, peer->carg, peer->path);
537: if (peer->chan != NULL) {
538: if (peer->chan->outport != NULL)
539: mesg_port_destroy(&peer->chan->outport);
540: FREE(PPTP_DEVICE_MTYPE, peer->chan);
541: }
542: if (csock != -1) {
543: (void)NgSendMsg(csock, peer->path,
544: NGM_GENERIC_COOKIE, NGM_SHUTDOWN, NULL, 0);
545: }
546: FREE(PPTP_PEER_MTYPE, peer);
547: }
548: if (csock != -1)
549: (void)close(csock);
550: errno = esave;
551: return (NULL);
552: }
553:
554: /*
555: * "Answer" peer's outgoing call.
556: */
557: static void
558: ppp_pptp_server_answer(void *arg)
559: {
560: struct ppp_pptp_peer *const peer = arg;
561:
562: pevent_unregister(&peer->answer);
563: (*peer->cinfo.answer)(peer->cinfo.cookie, PPTP_OCR_RESL_OK,
564: 0, 0, 10000000 /* XXX */);
565: ppp_pptp_server_device_output(peer, PPP_CHANNEL_OUTPUT_UP);
566: }
567:
568: /*
569: * Output indication from the device.
570: */
571: static void
572: ppp_pptp_server_device_output(struct ppp_pptp_peer *peer,
573: enum ppp_channeloutput type, ...)
574: {
575: struct pptp_server *const s = peer->s;
576: struct ppp_channel_output *output;
577:
578: /* Get output object */
579: if ((output = MALLOC(PPTP_OUTPUT_MTYPE, sizeof(*output))) == NULL) {
580: LOG(LOG_ERR, "can't create pptp output: %m");
581: return;
582: }
583: memset(output, 0, sizeof(*output));
584: output->type = type;
585:
586: /* Get extra args */
587: switch (output->type) {
588: case PPP_CHANNEL_OUTPUT_DOWN_FATAL:
589: case PPP_CHANNEL_OUTPUT_DOWN_NONFATAL:
590: {
591: const char *msg;
592: va_list args;
593:
594: /* Get string message */
595: va_start(args, type);
596: msg = va_arg(args, const char *);
597: va_end(args);
598: if ((output->info = STRDUP(PPTP_OUTPUT_MTYPE, msg)) == NULL) {
599: LOG(LOG_ERR, "can't create pptp output: %m");
600: FREE(PPTP_OUTPUT_MTYPE, output);
601: return;
602: }
603: break;
604: }
605: case PPP_CHANNEL_OUTPUT_UP:
606: break;
607: }
608:
609: /* Send message */
610: if (mesg_port_put(peer->chan->outport, output) == -1) {
611: LOG(LOG_ERR, "can't send pptp output: %m");
612: ppp_pptp_server_device_free_output(peer->chan, output);
613: return;
614: }
615: }
616:
617: /***********************************************************************
618: PPTP DEVICE METHODS
619: ***********************************************************************/
620:
621: static void
622: ppp_pptp_server_device_open(struct ppp_channel *chan)
623: {
624: return;
625: }
626:
627: static void
628: ppp_pptp_server_device_close(struct ppp_channel *chan)
629: {
630: struct ppp_pptp_peer *const peer = chan->priv;
631: struct pptp_server *const s = peer->s;
632: struct ng_pptpgre_conf greconf;
633: int csock;
634:
635: /* Logging */
636: if (!peer->closed) {
637: LOG(LOG_INFO, "closing PPTP connection with %s", peer->logname);
638: peer->closed = 1;
639: }
640:
641: /* Disable the pptpgre device */
642: if (NgMkSockNode(NULL, &csock, NULL) == -1)
643: LOG(LOG_ERR, "can't create socket node: %m");
644: else {
645: memset(&greconf, 0, sizeof(greconf));
646: (void)NgSendMsg(csock, peer->path, NGM_PPTPGRE_COOKIE,
647: NGM_PPTPGRE_SET_CONFIG, &greconf, sizeof(greconf));
648: (void)close(csock);
649: }
650:
651: /* Output 'down' message from the device */
652: ppp_pptp_server_device_output(peer,
653: PPP_CHANNEL_OUTPUT_DOWN_FATAL, "administratively closed");
654: }
655:
656: static void
657: ppp_pptp_server_device_destroy(struct ppp_channel **chanp)
658: {
659: struct ppp_channel *const chan = *chanp;
660: struct ppp_channel_output *output;
661: struct ppp_pptp_peer *peer;
662: struct pptp_server *s;
663: int csock;
664:
665: /* Sanity */
666: if (chan == NULL)
667: return;
668: *chanp = NULL;
669: peer = chan->priv;
670: s = peer->s;
671:
672: /* Close client code's side of the device */
673: if (peer->carg != NULL) {
674: (*s->info.destroy)(s->info.arg, peer->carg, peer->path);
675: peer->carg = NULL;
676: }
677:
678: /* Close the PPTP channel */
679: pevent_unregister(&peer->answer);
680: if (peer->cinfo.cookie != NULL) {
681: (*peer->cinfo.close)(peer->cinfo.cookie,
682: PPTP_CDN_RESL_ADMIN, 0, 0);
683: peer->cinfo.cookie = NULL;
684: }
685:
686: /* Destroy the ng_pptpgre(4) node */
687: if (NgMkSockNode(NULL, &csock, NULL) == -1)
688: LOG(LOG_ERR, "can't create socket node: %m");
689: else {
690: (void)NgSendMsg(csock, peer->path,
691: NGM_GENERIC_COOKIE, NGM_SHUTDOWN, NULL, 0);
692: (void)close(csock);
693: }
694:
695: /* Destroy the 'peer' object */
696: FREE(PPTP_PEER_MTYPE, peer);
697:
698: /* Destroy the device object */
699: while ((output = mesg_port_get(chan->outport, 0)) != NULL)
700: ppp_pptp_server_device_free_output(chan, output);
701: mesg_port_destroy(&chan->outport);
702: FREE(PPTP_DEVICE_MTYPE, chan);
703: s->npeers--;
704:
705: /* Check if shutting down PPTP server */
706: if (s->npeers == 0 && s->shutdown) {
707: ppp_log_close(&s->log);
708: FREE(PPTP_MTYPE, s);
709: }
710: }
711:
712: static void
713: ppp_pptp_server_device_free_output(struct ppp_channel *chan,
714: struct ppp_channel_output *output)
715: {
716: FREE(PPTP_OUTPUT_MTYPE, output->info);
717: FREE(PPTP_OUTPUT_MTYPE, output);
718: }
719:
720: static void
721: ppp_pptp_server_device_set_link_info(struct ppp_channel *chan, u_int32_t accm)
722: {
723: /* XXX implement me? */
724: }
725:
726: static int
727: ppp_pptp_server_device_get_origination(struct ppp_channel *chan)
728: {
729: return (PPP_PEER); /* we don't initiate any calls ourself */
730: }
731:
732: static const char *
733: ppp_pptp_server_device_get_node(struct ppp_channel *chan)
734: {
735: struct ppp_pptp_peer *const peer = chan->priv;
736:
737: return (peer->path);
738: }
739:
740: static const char *
741: ppp_pptp_server_device_get_hook(struct ppp_channel *chan)
742: {
743: return (NG_PPTPGRE_HOOK_UPPER);
744: }
745:
746: static int
747: ppp_pptp_server_device_is_async(struct ppp_channel *chan)
748: {
749: return (0);
750: }
751:
752: static u_int
753: ppp_pptp_server_device_get_mtu(struct ppp_channel *chan)
754: {
755: return (PPTP_MRU);
756: }
757:
758: static int
759: ppp_pptp_server_device_get_acfcomp(struct ppp_channel *chan)
760: {
761: return (1);
762: }
763:
764: static int
765: ppp_pptp_server_device_get_pfcomp(struct ppp_channel *chan)
766: {
767: return (1);
768: }
769:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>