Annotation of embedaddon/libpdel/ppp/ppp_pptp_server.c, revision 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>