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>