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>