Annotation of embedaddon/libpdel/ppp/ppp_link.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_fsm_option.h"
                     44: #include "ppp/ppp_fsm.h"
                     45: #include "ppp/ppp_auth.h"
                     46: #include "ppp/ppp_lcp.h"
                     47: #include "ppp/ppp_node.h"
                     48: #include "ppp/ppp_engine.h"
                     49: #include "ppp/ppp_bundle.h"
                     50: #include "ppp/ppp_channel.h"
                     51: #include "ppp/ppp_link.h"
                     52: 
                     53: #define LINK_MTYPE             "ppp_link"
                     54: #define PKTBUFLEN              4096
                     55: #define LINK_LATENCY           100             /* arbitrary fixed value */
                     56: #define LINK_BANDWIDTH         100             /* arbitrary fixed value */
                     57: 
                     58: #define AUTH_TIMEOUT           20              /* time limit for auth phase */
                     59: 
                     60: #define WINXP_PPTP_HACK(x)     ((x) - 20)      /* winxp pptp stupidity hack */
                     61: 
                     62: /*
                     63:  * Authorization info for one direction
                     64:  */
                     65: struct ppp_link_auth {
                     66:        struct ppp_link                 *link;  /* back pointer */
                     67:        u_int16_t                       proto;  /* auth protocol number */
                     68:        const struct ppp_auth_type      *type;  /* auth type negotiated */
                     69:        void                            *arg;   /* auth object in progress */
                     70:        struct ppp_auth_cred            cred;   /* auth credentials */
                     71:        struct ppp_auth_resp            resp;   /* auth response */
                     72:        union ppp_auth_mppe             mppe;   /* mppe keys from ms-chap */
                     73:        struct paction                  *action;/* auth acquire/check action */
                     74: };
                     75: 
                     76: /*
                     77:  * PPP link structure
                     78:  */
                     79: struct ppp_link {
                     80:        enum ppp_link_state     state;          /* link state */
                     81:        struct ppp_log          *log;           /* log */
                     82:        struct ppp_link_config  conf;           /* link configuration */
                     83:        struct ppp_engine       *engine;        /* ppp engine */
                     84:        struct ppp_channel      *device;        /* underlying device */
                     85:        struct ppp_node         *node;          /* ng_ppp(4) node */
                     86:        struct ppp_fsm          *lcp;           /* lcp fsm */
                     87:        struct ppp_lcp_req      lcp_req;        /* lcp negotiation result */
                     88:        struct ppp_bundle       *bundle;        /* bundle, if joined */
                     89:        struct pevent_ctx       *ev_ctx;        /* event context */
                     90:        pthread_mutex_t         *mutex;         /* mutex */
                     91:        struct pevent           *lcp_event;     /* lcp fsm event */
                     92:        struct pevent           *dev_event;     /* device event */
                     93:        struct pevent           *auth_timer;    /* timer for auth phase */
                     94:        u_char                  device_up;      /* device is up */
                     95:        struct ppp_link_auth    auth[2];        /* authorization info */
                     96:        u_int16_t               link_num;       /* ppp node link number */
                     97:        u_char                  shutdown;       /* normal shutdown */
                     98: };
                     99: 
                    100: /* Internal functions */
                    101: static void    ppp_link_join(struct ppp_link *link);
                    102: static void    ppp_link_unjoin(struct ppp_link *link);
                    103: static int     ppp_link_get_node(struct ppp_link *link);
                    104: static void    ppp_link_auth_start(struct ppp_link *link);
                    105: static void    ppp_link_auth_stop(struct ppp_link *link);
                    106: 
                    107: static ppp_node_recv_t ppp_link_node_recv;
                    108: 
                    109: static pevent_handler_t        ppp_link_device_event;
                    110: static pevent_handler_t        ppp_link_lcp_event;
                    111: static pevent_handler_t        ppp_link_auth_timeout;
                    112: 
                    113: /* Macro for logging */
                    114: #define LOG(sev, fmt, args...) PPP_LOG(link->log, sev, fmt , ## args)
                    115: 
                    116: /***********************************************************************
                    117:                        PUBLIC FUNCTIONS
                    118: ***********************************************************************/
                    119: 
                    120: /*
                    121:  * Create a new PPP link.
                    122:  *
                    123:  * The link is not returned. Instead it disappears into the PPP engine.
                    124:  * The "device" and "log" are destroyed when the link is destroyed.
                    125:  */
                    126: int
                    127: ppp_link_create(struct ppp_engine *engine, struct ppp_channel *device,
                    128:        struct ppp_link_config *conf, struct ppp_log *log)
                    129: {
                    130:        struct ppp_fsm_instance *inst = NULL;
                    131:        struct ppp_lcp_config lcp_conf;
                    132:        struct ppp_fsm *lcp = NULL;
                    133:        struct ppp_link *link;
                    134:        int esave;
                    135:        int i;
                    136:        int j;
                    137: 
                    138:        /* Create new link structure */
                    139:        if ((link = MALLOC(LINK_MTYPE, sizeof(*link))) == NULL)
                    140:                return (-1);
                    141:        memset(link, 0, sizeof(*link));
                    142:        link->state = PPP_LINK_DOWN;
                    143:        link->engine = engine;
                    144:        link->ev_ctx = ppp_engine_get_ev_ctx(engine);
                    145:        link->mutex = ppp_engine_get_mutex(engine);
                    146:        link->device = device;
                    147:        link->conf = *conf;
                    148:        link->log = log;
                    149:        for (i = 0; i < 2; i++)
                    150:                link->auth[i].link = link;
                    151: 
                    152:        /* Derive LCP configuration from link configuration and device info */
                    153:        memset(&lcp_conf, 0, sizeof(lcp_conf));
                    154:        lcp_conf.max_mru[PPP_SELF] = conf->max_self_mru;
                    155:        lcp_conf.min_mru[PPP_PEER] = conf->min_peer_mru;
                    156:        lcp_conf.accm = ppp_channel_is_async(device) ? 0x0a000000 : ~0;
                    157:        if (ppp_channel_get_acfcomp(device)) {
                    158:                lcp_conf.acfcomp[PPP_SELF] = 1;
                    159:                lcp_conf.acfcomp[PPP_PEER] = 1;
                    160:        }
                    161:        if (ppp_channel_get_pfcomp(device)) {
                    162:                lcp_conf.pfcomp[PPP_SELF] = 1;
                    163:                lcp_conf.pfcomp[PPP_PEER] = 1;
                    164:        }
                    165:        for (i = 0; i < PPP_AUTH_MAX; i++) {
                    166:                for (j = 0; j < 2; j++) {
                    167:                        if ((conf->auth.allow[j] & (1 << i)) != 0)
                    168:                                lcp_conf.auth[j][i] = 1;
                    169:                }
                    170:        }
                    171:        lcp_conf.eid = conf->eid;
                    172:        if (conf->multilink) {
                    173:                lcp_conf.max_mrru[PPP_SELF] = conf->max_self_mrru;
                    174:                lcp_conf.min_mrru[PPP_PEER] = conf->min_peer_mrru;
                    175:                lcp_conf.multilink[PPP_SELF] = 1;
                    176:                lcp_conf.multilink[PPP_PEER] = 1;
                    177:                lcp_conf.shortseq[PPP_SELF] = 1;
                    178:                lcp_conf.shortseq[PPP_PEER] = 1;
                    179:        }
                    180: 
                    181:        /* Create ppp node object */
                    182:        if (ppp_link_get_node(link) == -1)
                    183:                goto fail;
                    184: 
                    185:        /* Create a new LCP FSM for this link */
                    186:        if ((inst = ppp_lcp_create(&lcp_conf)) == NULL) {
                    187:                LOG(LOG_ERR, "failed to create LCP: %m");
                    188:                goto fail;
                    189:        }
                    190:        if ((link->lcp = ppp_fsm_create(link->ev_ctx,
                    191:            link->mutex, inst, link->log)) == NULL) {
                    192:                LOG(LOG_ERR, "failed to create LCP: %m");
                    193:                goto fail;
                    194:        }
                    195:        inst = NULL;
                    196: 
                    197:        /* Listen for device events */
                    198:        if (pevent_register(link->ev_ctx, &link->dev_event, PEVENT_RECURRING,
                    199:            link->mutex, ppp_link_device_event, link, PEVENT_MESG_PORT,
                    200:            ppp_channel_get_outport(link->device)) == -1) {
                    201:                LOG(LOG_ERR, "%s: %m", "adding read event");
                    202:                goto fail;
                    203:        }
                    204: 
                    205:        /* Listen for LCP events */
                    206:        if (pevent_register(link->ev_ctx, &link->lcp_event, PEVENT_RECURRING,
                    207:            link->mutex, ppp_link_lcp_event, link, PEVENT_MESG_PORT,
                    208:            ppp_fsm_get_outport(link->lcp)) == -1) {
                    209:                LOG(LOG_ERR, "%s: %m", "adding read event");
                    210:                goto fail;
                    211:        }
                    212: 
                    213:        /* Notify engine of new link */
                    214:        if (ppp_engine_add_link(engine, link) == -1) {
                    215:                LOG(LOG_ERR, "failed to add link: %m");
                    216:                goto fail;
                    217:        }
                    218: 
                    219:        /* Start LCP negotiations (whenver link comes up) */
                    220:        ppp_fsm_input(link->lcp, FSM_INPUT_OPEN);
                    221: 
                    222:        /* Done */
                    223:        return (0);
                    224: 
                    225: fail:
                    226:        /* Clean up after failure */
                    227:        esave = errno;
                    228:        pevent_unregister(&link->dev_event);
                    229:        pevent_unregister(&link->lcp_event);
                    230:        ppp_node_destroy(&link->node);
                    231:        ppp_node_destroy(&link->node);
                    232:        ppp_fsm_destroy(&lcp);
                    233:        if (inst != NULL)
                    234:                (*inst->type->destroy)(inst);
                    235:        FREE(LINK_MTYPE, link);
                    236:        errno = esave;
                    237:        return (-1);
                    238: }
                    239: 
                    240: /*
                    241:  * Destroy a link.
                    242:  */
                    243: void
                    244: ppp_link_destroy(struct ppp_link **linkp)
                    245: {
                    246:        struct ppp_link *const link = *linkp;
                    247:        int r;
                    248: 
                    249:        /* Sanity check */
                    250:        if (link == NULL)
                    251:                return;
                    252:        *linkp = NULL;
                    253: 
                    254:        /* Avoid recursion */
                    255:        if (link->shutdown)
                    256:                return;
                    257:        link->shutdown = 1;
                    258: 
                    259:        /* Acquire lock */
                    260:        r = pthread_mutex_lock(link->mutex);
                    261:        assert(r == 0);
                    262: 
                    263:        /* Stop authentication (if any) */
                    264:        ppp_link_auth_stop(link);
                    265: 
                    266:        /* Disconnect from bundle or engine */
                    267:        ppp_bundle_unjoin(&link->bundle, link);
                    268:        ppp_engine_del_link(link->engine, link);
                    269: 
                    270:        /* Destroy link */
                    271:        r = pthread_mutex_unlock(link->mutex);
                    272:        assert(r == 0);
                    273:        ppp_fsm_destroy(&link->lcp);
                    274:        pevent_unregister(&link->dev_event);
                    275:        pevent_unregister(&link->lcp_event);
                    276:        ppp_node_destroy(&link->node);
                    277:        ppp_channel_destroy(&link->device);
                    278:        ppp_log_close(&link->log);
                    279:        FREE(LINK_MTYPE, link);
                    280: }
                    281: 
                    282: /*
                    283:  * Close a link.
                    284:  */
                    285: void
                    286: ppp_link_close(struct ppp_link *link)
                    287: {
                    288:        ppp_link_auth_stop(link);
                    289:        ppp_fsm_input(link->lcp, FSM_INPUT_CLOSE);
                    290: }
                    291: 
                    292: /*
                    293:  * Get the device associated with a link.
                    294:  */
                    295: struct ppp_channel *
                    296: ppp_link_get_device(struct ppp_link *link)
                    297: {
                    298:        return (link->device);
                    299: }
                    300: 
                    301: /*
                    302:  * Get the link's origination (PPP_SELF or PPP_PEER) which
                    303:  * is simply inherited from the underlying device.
                    304:  */
                    305: int
                    306: ppp_link_get_origination(struct ppp_link *link)
                    307: {
                    308:        return (ppp_channel_get_origination(link->device));
                    309: }
                    310: 
                    311: /*
                    312:  * Get link state.
                    313:  */
                    314: enum ppp_link_state
                    315: ppp_link_get_state(struct ppp_link *link)
                    316: {
                    317:        return (link->state);
                    318: }
                    319: 
                    320: /*
                    321:  * Get bundle associated with link, if any.
                    322:  */
                    323: struct ppp_bundle *
                    324: ppp_link_get_bundle(struct ppp_link *link)
                    325: {
                    326:        if (link->bundle == NULL)
                    327:                errno = ENXIO;
                    328:        return (link->bundle);
                    329: }
                    330: 
                    331: /*
                    332:  * Get LCP request state.
                    333:  */
                    334: void
                    335: ppp_link_get_lcp_req(struct ppp_link *link, struct ppp_lcp_req *req)
                    336: {
                    337:        ppp_lcp_get_req(link->lcp, req);
                    338: }
                    339: 
                    340: /*
                    341:  * Get link authorization name.
                    342:  *
                    343:  * Note: we reverse the sense of 'dir' because we want PPP_SELF to
                    344:  * mean my authname to peer, which is the opposite of the way that
                    345:  * authorization is negotiated, i.e., PPP_SELF is peer's auth to me.
                    346:  */
                    347: const char *
                    348: ppp_link_get_authname(struct ppp_link *link, int dir)
                    349: {
                    350:        struct ppp_link_auth *const auth = &link->auth[!dir];
                    351: 
                    352:        if (auth->type == NULL)
                    353:                return ("");
                    354:        switch (auth->type->index) {
                    355:        case PPP_AUTH_PAP:
                    356:                return (auth->cred.u.pap.name);
                    357:        case PPP_AUTH_CHAP_MSV1:
                    358:        case PPP_AUTH_CHAP_MSV2:
                    359:        case PPP_AUTH_CHAP_MD5:
                    360:                return (auth->cred.u.chap.name);
                    361:        default:
                    362:                return ("");
                    363:        }
                    364: }
                    365: 
                    366: /*
                    367:  * Get endpoint ID.
                    368:  */
                    369: void
                    370: ppp_link_get_eid(struct ppp_link *link, int dir, struct ppp_eid *eid)
                    371: {
                    372:        struct ppp_lcp_req req;
                    373: 
                    374:        dir &= 1;
                    375:        ppp_lcp_get_req(link->lcp, &req);
                    376:        *eid = req.eid[dir];
                    377: }
                    378: 
                    379: void
                    380: ppp_link_get_mppe(struct ppp_link *link, int dir, union ppp_auth_mppe *mppe)
                    381: {
                    382:        struct ppp_link_auth *const auth = &link->auth[dir & 1];
                    383: 
                    384:        memcpy(mppe, &auth->mppe, sizeof(*mppe));
                    385: }
                    386: 
                    387: /*
                    388:  * Ouput a packet on the link.
                    389:  */
                    390: void
                    391: ppp_link_write(struct ppp_link *link,
                    392:        u_int16_t proto, const void *data, size_t len)
                    393: {
                    394:        int rtn;
                    395: 
                    396:        /* Drop packet if channel is down */
                    397:        if (!link->device_up)
                    398:                return;
                    399: 
                    400:        /* Write packet */
                    401:        if (link->bundle != NULL) {
                    402:                rtn = ppp_bundle_write(link->bundle,
                    403:                    link->link_num, proto, data, len);
                    404:        } else  {
                    405:                rtn = ppp_node_write(link->node,
                    406:                    link->link_num, proto, data, len);
                    407:        }
                    408: 
                    409:        if (rtn == -1) {
                    410:                LOG(LOG_ERR, "%s: %m", "error writing to bypass");
                    411:                ppp_link_close(link);
                    412:        }
                    413: }
                    414: 
                    415: /***********************************************************************
                    416:                        LCP EVENT HANDLER
                    417: ***********************************************************************/
                    418: 
                    419: static void
                    420: ppp_link_lcp_event(void *arg)
                    421: {
                    422:        struct ppp_link *link = arg;
                    423:        struct mesg_port *const outport = ppp_fsm_get_outport(link->lcp);
                    424:        struct ppp_fsm_output *output;
                    425: 
                    426:        /* Read and handle all FSM events */
                    427:        while ((output = mesg_port_get(outport, 0)) != NULL) {
                    428: 
                    429:                /* Check it out */
                    430:                switch (output->type) {
                    431:                case FSM_OUTPUT_OPEN:
                    432:                        ppp_channel_open(link->device);
                    433:                        break;
                    434:                case FSM_OUTPUT_CLOSE:
                    435:                        ppp_channel_close(link->device);
                    436:                        break;
                    437:                case FSM_OUTPUT_UP:
                    438:                    {
                    439:                        struct ng_ppp_node_conf conf;
                    440:                        struct ng_ppp_link_conf *const lconf = &conf.links[0];
                    441: 
                    442:                        /* Get ng_ppp(4) node configuration */
                    443:                        if (ppp_node_get_config(link->node, &conf) == -1) {
                    444:                                LOG(LOG_ERR, "can't configure node: %m");
                    445:                                ppp_link_close(link);
                    446:                                break;
                    447:                        }
                    448: 
                    449:                        /* Update with negotiated LCP parameters */
                    450:                        ppp_lcp_get_req(link->lcp, &link->lcp_req);
                    451:                        lconf->enableProtoComp = link->lcp_req.pfcomp[PPP_PEER];
                    452:                        lconf->enableACFComp = link->lcp_req.acfcomp[PPP_PEER];
                    453:                        lconf->mru = MIN(
                    454:                            WINXP_PPTP_HACK(link->lcp_req.mru[PPP_PEER]),
                    455:                            ppp_channel_get_mtu(link->device));
                    456:                        lconf->latency = LINK_LATENCY;
                    457:                        lconf->bandwidth = LINK_BANDWIDTH;
                    458:                        if (ppp_node_set_config(link->node, &conf) == -1) {
                    459:                                LOG(LOG_ERR, "can't configure node: %m");
                    460:                                ppp_link_close(link);
                    461:                                break;
                    462:                        }
                    463: 
                    464:                        /* Begin authentication phase */
                    465:                        link->state = PPP_LINK_AUTH;
                    466:                        ppp_link_auth_start(link);
                    467:                        break;
                    468:                    }
                    469:                case FSM_OUTPUT_DOWN:
                    470:                        link->state = PPP_LINK_DOWN;
                    471:                        ppp_link_auth_stop(link);
                    472:                        if (link->bundle != NULL) {
                    473: 
                    474:                                /* Leave our bundle */
                    475:                                assert(link->node == NULL);
                    476:                                ppp_bundle_unjoin(&link->bundle, link);
                    477: 
                    478:                                /* Create a new node for this link */
                    479:                                if (ppp_link_get_node(link) == -1) {
                    480:                                        ppp_link_close(link);
                    481:                                        break;
                    482:                                }
                    483:                        }
                    484:                        break;
                    485:                case FSM_OUTPUT_DATA:
                    486:                        ppp_link_write(link, PPP_PROTO_LCP,
                    487:                            output->u.data.data, output->u.data.length);
                    488:                        break;
                    489:                case FSM_OUTPUT_PROTOREJ:
                    490:                    {
                    491:                        /* Log it */
                    492:                        LOG(LOG_NOTICE,
                    493:                            "peer rejected protocol 0x%04x", output->u.proto);
                    494: 
                    495:                        /* If fatal, shut down, else report to bundle */
                    496:                        switch (output->u.proto) {
                    497:                        case PPP_PROTO_LCP:
                    498:                        case PPP_PROTO_CHAP:
                    499:                        case PPP_PROTO_PAP:
                    500:                        case PPP_PROTO_MP:
                    501:                                ppp_fsm_input(link->lcp,
                    502:                                    FSM_INPUT_RECD_PROTOREJ, output->u.proto);
                    503:                                break;
                    504:                        default:
                    505:                                if (link->bundle != NULL) {
                    506:                                        ppp_bundle_protorej(link->bundle,
                    507:                                            output->u.proto);
                    508:                                }
                    509:                                break;
                    510:                        }
                    511:                        break;
                    512:                    }
                    513:                case FSM_OUTPUT_DEAD:
                    514:                        LOG(LOG_INFO, "LCP is dead: %s",
                    515:                            ppp_fsm_reason_str(output));
                    516:                        if (link->bundle != NULL)
                    517:                                ppp_link_unjoin(link);
                    518:                        ppp_fsm_free_output(output);
                    519:                        ppp_link_destroy(&link);
                    520:                        return;
                    521:                }
                    522: 
                    523:                /* Free output */
                    524:                ppp_fsm_free_output(output);
                    525:        }
                    526: }
                    527: 
                    528: /***********************************************************************
                    529:                        DEVICE EVENT HANDLER
                    530: ***********************************************************************/
                    531: 
                    532: static void
                    533: ppp_link_device_event(void *arg)
                    534: {
                    535:        struct ppp_link *const link = arg;
                    536:        struct mesg_port *const outport = ppp_channel_get_outport(link->device);
                    537:        struct ppp_channel_output *output;
                    538: 
                    539:        /* Handle channel events */
                    540:        while ((output = mesg_port_get(outport, 0)) != NULL) {
                    541: 
                    542:                /* Check event */
                    543:                switch (output->type) {
                    544:                case PPP_CHANNEL_OUTPUT_UP:
                    545:                        LOG(LOG_INFO, "device layer is up");
                    546:                        ppp_fsm_input(link->lcp, FSM_INPUT_UP);
                    547:                        link->device_up = 1;
                    548:                        break;
                    549:                case PPP_CHANNEL_OUTPUT_DOWN_FATAL:
                    550:                case PPP_CHANNEL_OUTPUT_DOWN_NONFATAL:
                    551:                        LOG(LOG_INFO, "device layer is down: %s", output->info);
                    552:                        ppp_fsm_input(link->lcp,
                    553:                            output->type == PPP_CHANNEL_OUTPUT_DOWN_FATAL ?
                    554:                              FSM_INPUT_DOWN_FATAL : FSM_INPUT_DOWN_NONFATAL);
                    555:                        link->device_up = 0;
                    556:                        break;
                    557:                }
                    558: 
                    559:                /* Free channel output */
                    560:                ppp_channel_free_output(link->device, output);
                    561:        }
                    562: }
                    563: 
                    564: /***********************************************************************
                    565:                        PPP NODE OUTPUT HANDLER
                    566: ***********************************************************************/
                    567: 
                    568: /*
                    569:  * Handle data received from the node's bypass hook.
                    570:  */
                    571: void
                    572: ppp_link_recv_bypass(struct ppp_link *link,
                    573:        u_int16_t proto, u_char *data, size_t len)
                    574: {
                    575:        LOG(LOG_DEBUG + 1, "rec'd proto 0x%04x %u bytes", proto, len);
                    576:        switch (proto) {
                    577:        case PPP_PROTO_LCP:
                    578:                ppp_fsm_input(link->lcp, FSM_INPUT_DATA, data, len);
                    579:                break;
                    580:        case PPP_PROTO_PAP:
                    581:        case PPP_PROTO_CHAP:
                    582:            {
                    583:                int i;
                    584: 
                    585:                for (i = 0; i < 2; i++) {
                    586:                        struct ppp_link_auth *const auth = &link->auth[i];
                    587: 
                    588:                        if (auth->type == NULL
                    589:                            || auth->arg == NULL
                    590:                            || auth->proto != proto)
                    591:                                continue;
                    592:                        (*auth->type->input)(auth->arg, i, data, len);
                    593:                }
                    594:                break;
                    595:            }
                    596:        case PPP_PROTO_MP:
                    597:        case PPP_PROTO_IPCP:
                    598:        case PPP_PROTO_IP:
                    599:        case PPP_PROTO_VJCOMP:
                    600:        case PPP_PROTO_VJUNCOMP:
                    601:        case PPP_PROTO_CCP:
                    602:        case PPP_PROTO_COMPD:
                    603:                break;
                    604:        default:                        /* send a protocol-reject */
                    605:                ppp_fsm_input(link->lcp,
                    606:                    FSM_INPUT_XMIT_PROTOREJ, proto, data, len);
                    607:                break;
                    608:        }
                    609: }
                    610: 
                    611: static void
                    612: ppp_link_node_recv(void *arg, u_int link_num,
                    613:        u_int16_t proto, u_char *data, size_t len)
                    614: {
                    615:        struct ppp_link *const link = arg;
                    616: 
                    617:        assert(link_num == 0);
                    618:        ppp_link_recv_bypass(link, proto, data, len);
                    619: }
                    620: 
                    621: /***********************************************************************
                    622:                        AUTHORIZATION PHASE
                    623: ***********************************************************************/
                    624: 
                    625: /*
                    626:  * Begin link authorization.
                    627:  */
                    628: static void
                    629: ppp_link_auth_start(struct ppp_link *link)
                    630: {
                    631:        int i;
                    632: 
                    633:        /* Get auth types negotiated by LCP */
                    634:        for (i = 0; i < 2; i++) {
                    635:                link->auth[i].type = (link->lcp_req.auth[i] != PPP_AUTH_NONE) ?
                    636:                    ppp_auth_by_index(link->lcp_req.auth[i]) : NULL;
                    637:        }
                    638:        LOG(LOG_DEBUG, "auth required: self=%s peer=%s",
                    639:            link->auth[PPP_PEER].type != NULL ?
                    640:              link->auth[PPP_PEER].type->name : "None",
                    641:            link->auth[PPP_SELF].type != NULL ?
                    642:              link->auth[PPP_SELF].type->name : "None");
                    643: 
                    644:        /* If no auth required, skip it */
                    645:        if (link->auth[PPP_SELF].type == NULL
                    646:            && link->auth[PPP_PEER].type == NULL) {
                    647:                ppp_link_join(link);
                    648:                return;
                    649:        }
                    650: 
                    651:        /* Start auth timer */
                    652:        pevent_unregister(&link->auth_timer);
                    653:        if (pevent_register(link->ev_ctx, &link->auth_timer, 0,
                    654:            link->mutex, ppp_link_auth_timeout, link, PEVENT_TIME,
                    655:            AUTH_TIMEOUT * 1000) == -1) {
                    656:                LOG(LOG_ERR, "%s: %m", "pevent_register");
                    657:                ppp_link_close(link);
                    658:                return;
                    659:        }
                    660: 
                    661:        /* Start authorization in each direction */
                    662:        for (i = 0; i < 2; i++) {
                    663:                struct ppp_link_auth *const auth = &link->auth[i];
                    664: 
                    665:                if (auth->type == NULL)
                    666:                        continue;
                    667:                if ((auth->arg = (*auth->type->start)(link->ev_ctx, link,
                    668:                    link->mutex, i, &auth->proto, ppp_log_dup(link->log)))
                    669:                    == NULL) {
                    670:                        LOG(LOG_ERR, "failed to initialize authorization");
                    671:                        ppp_link_close(link);
                    672:                        return;
                    673:                }
                    674:        }
                    675: }
                    676: 
                    677: /*
                    678:  * Stop link authorization.
                    679:  */
                    680: static void
                    681: ppp_link_auth_stop(struct ppp_link *link)
                    682: {
                    683:        int i;
                    684: 
                    685:        /* Stop auth timer */
                    686:        pevent_unregister(&link->auth_timer);
                    687: 
                    688:        /* Stop auth in both directions */
                    689:        for (i = 0; i < 2; i++) {
                    690:                struct ppp_link_auth *const auth = &link->auth[i];
                    691: 
                    692:                /* Kill any threads */
                    693:                paction_cancel(&auth->action);
                    694: 
                    695:                /* Clean up authorization code */
                    696:                if (auth->arg != NULL) {
                    697:                        (*auth->type->cancel)(auth->arg);
                    698:                        auth->arg = NULL;
                    699:                }
                    700:        }
                    701: }
                    702: 
                    703: /*
                    704:  * Authorization failed to happen within the alloted time.
                    705:  */
                    706: static void
                    707: ppp_link_auth_timeout(void *arg)
                    708: {
                    709:        struct ppp_link *const link = arg;
                    710: 
                    711:        pevent_unregister(&link->auth_timer);
                    712:        LOG(LOG_ERR, "authorization timed out");
                    713:        ppp_link_close(link);
                    714: }
                    715: 
                    716: /***********************************************************************
                    717:                        AUTHORIZATION CALLBACKS
                    718: ***********************************************************************/
                    719: 
                    720: #define AUTHINFO_MTYPE         "ppp_link.authinfo"
                    721: 
                    722: /* Authorization acquire/check state */
                    723: struct ppp_link_auth_info {
                    724:        struct ppp_link                 *link;  /* link being authorized */
                    725:        struct ppp_auth_cred            cred;   /* auth credentials */
                    726:        struct ppp_auth_resp            resp;   /* auth response */
                    727:        ppp_link_auth_finish_t          *finish;/* auth finish routine */
                    728:        int                             rtn;    /* return value from user */
                    729:        int                             error;  /* saved value of 'errno' */
                    730: };
                    731: 
                    732: static paction_handler_t       ppp_link_auth_acquire_main;
                    733: static paction_finish_t                ppp_link_auth_acquire_finish;
                    734: 
                    735: static paction_handler_t       ppp_link_auth_check_main;
                    736: static paction_finish_t                ppp_link_auth_check_finish;
                    737: 
                    738: /*
                    739:  * Acquire or check authorization credentials.
                    740:  *
                    741:  * This action is done in a separate thread.
                    742:  */
                    743: int
                    744: ppp_link_authorize(struct ppp_link *link, int dir,
                    745:        const struct ppp_auth_cred *cred, ppp_link_auth_finish_t *authfinish)
                    746: {
                    747:        struct ppp_link_auth *const auth = &link->auth[dir];
                    748:        struct ppp_link_auth_info *authinfo;
                    749:        paction_handler_t *handler;
                    750:        paction_finish_t *finish;
                    751: 
                    752:        /* Sanity check */
                    753:        assert(auth->action == NULL);
                    754: 
                    755:        /* Set up for 'acquire' or 'check' */
                    756:        if (dir == PPP_PEER) {
                    757:                if (link->conf.auth.meth->acquire == NULL) {
                    758:                        LOG(LOG_ERR, "no method provided for %s credentials",
                    759:                            "acquiring");
                    760:                        return (-1);
                    761:                }
                    762:                handler = ppp_link_auth_acquire_main;
                    763:                finish = ppp_link_auth_acquire_finish;
                    764:        } else {
                    765:                if (link->conf.auth.meth->check == NULL) {
                    766:                        LOG(LOG_ERR, "no method provided for %s credentials",
                    767:                            "checking");
                    768:                        return (-1);
                    769:                }
                    770:                handler = ppp_link_auth_check_main;
                    771:                finish = ppp_link_auth_check_finish;
                    772:        }
                    773: 
                    774:        /* Create auth info */
                    775:        if ((authinfo = MALLOC(AUTHINFO_MTYPE, sizeof(*authinfo))) == NULL) {
                    776:                LOG(LOG_ERR, "%s: %m", "malloc");
                    777:                return (-1);
                    778:        }
                    779:        memset(authinfo, 0, sizeof(*authinfo));
                    780:        authinfo->link = link;
                    781:        authinfo->cred = *cred;
                    782:        authinfo->finish = authfinish;
                    783: 
                    784:        /* Initiate authorization action */
                    785:        if (paction_start(&auth->action, link->mutex,
                    786:            handler, finish, authinfo) == -1) {
                    787:                LOG(LOG_ERR, "%s: %m", "paction_start");
                    788:                FREE(AUTHINFO_MTYPE, authinfo);
                    789:                return (-1);
                    790:        }
                    791: 
                    792:        /* Done */
                    793:        return (0);
                    794: }
                    795: 
                    796: /*
                    797:  * Acquire authorization credentials.
                    798:  *
                    799:  * The mutex is NOT locked when this is called.
                    800:  */
                    801: static void
                    802: ppp_link_auth_acquire_main(void *arg)
                    803: {
                    804:        struct ppp_link_auth_info *const authinfo = arg;
                    805:        struct ppp_link *const link = authinfo->link;
                    806: 
                    807:        /* Acquire credentials */
                    808:        authinfo->rtn = (*link->conf.auth.meth->acquire)(link,
                    809:            &authinfo->cred, &authinfo->resp);
                    810:        authinfo->error = errno;
                    811: }
                    812: 
                    813: /*
                    814:  * Finish acquiring authorization credentials.
                    815:  *
                    816:  * The mutex is locked when this is called unless 'canceled' is true.
                    817:  */
                    818: static void
                    819: ppp_link_auth_acquire_finish(void *arg, int canceled)
                    820: {
                    821:        struct ppp_link_auth_info *const authinfo = arg;
                    822:        struct ppp_link *const link = authinfo->link;
                    823:        struct ppp_link_auth *const auth = &link->auth[PPP_PEER];
                    824: 
                    825:        /* If canceled, just clean up */
                    826:        if (canceled)
                    827:                goto done;
                    828: 
                    829:        /* If acquiring credentials failed, bail out here */
                    830:        if (authinfo->rtn != 0) {
                    831:                if (*authinfo->resp.errmsg == '\0') {
                    832:                        strlcpy(authinfo->resp.errmsg,
                    833:                            strerror(authinfo->error),
                    834:                            sizeof(authinfo->resp.errmsg));
                    835:                }
                    836:                LOG(LOG_WARNING, "failed to acquire credentials: %s",
                    837:                    auth->resp.errmsg);
                    838:                ppp_link_auth_complete(link, PPP_PEER, NULL, NULL);
                    839:                return;
                    840:        }
                    841: 
                    842:        /* Save a copy of credentials */
                    843:        auth->cred = authinfo->cred;
                    844:        auth->resp = authinfo->resp;
                    845: 
                    846:        /* Report credentials back to authorization code */
                    847:        (*authinfo->finish)(auth->arg, &authinfo->cred, &authinfo->resp);
                    848: 
                    849: done:
                    850:        /* Free authinfo */
                    851:        FREE(AUTHINFO_MTYPE, authinfo);
                    852: }
                    853: 
                    854: /*
                    855:  * Check authorization credentials.
                    856:  *
                    857:  * The mutex is NOT locked when this is called.
                    858:  */
                    859: static void
                    860: ppp_link_auth_check_main(void *arg)
                    861: {
                    862:        struct ppp_link_auth_info *const authinfo = arg;
                    863:        struct ppp_link *const link = authinfo->link;
                    864: 
                    865:        /* Check credentials */
                    866:        authinfo->rtn = (*link->conf.auth.meth->check)(link,
                    867:            &authinfo->cred, &authinfo->resp);
                    868:        authinfo->error = errno;
                    869: }
                    870: 
                    871: /*
                    872:  * Finish checking authorization credentials.
                    873:  *
                    874:  * The mutex is locked when this is called.
                    875:  */
                    876: static void
                    877: ppp_link_auth_check_finish(void *arg, int canceled)
                    878: {
                    879:        struct ppp_link_auth_info *const authinfo = arg;
                    880:        struct ppp_link *const link = authinfo->link;
                    881:        struct ppp_link_auth *const auth = &link->auth[PPP_SELF];
                    882: 
                    883:        /* If canceled, just clean up */
                    884:        if (canceled)
                    885:                goto done;
                    886: 
                    887:        /* Save a copy of credentials */
                    888:        auth->cred = authinfo->cred;
                    889:        auth->resp = authinfo->resp;
                    890: 
                    891:        /* Fill in error message to indicate invalid credentials */
                    892:        if (authinfo->rtn != 0) {
                    893:                if (*authinfo->resp.errmsg == '\0') {
                    894:                        strlcpy(authinfo->resp.errmsg,
                    895:                            strerror(authinfo->error),
                    896:                            sizeof(authinfo->resp.errmsg));
                    897:                }
                    898:        }
                    899: 
                    900:        /* Report result back to authorization code */
                    901:        (*authinfo->finish)(auth->arg, &authinfo->cred, &authinfo->resp);
                    902: 
                    903: done:
                    904:        /* Free authinfo */
                    905:        FREE(AUTHINFO_MTYPE, authinfo);
                    906: }
                    907: 
                    908: /* 
                    909:  * Determine if an authorization action is already in progress.
                    910:  */
                    911: int
                    912: ppp_link_auth_in_progress(struct ppp_link *link, int dir)
                    913: {
                    914:        struct ppp_link_auth *const auth = &link->auth[dir];
                    915: 
                    916:        return (auth->action != NULL);
                    917: }
                    918: 
                    919: /*
                    920:  * Finish link authorization (in one direction).
                    921:  *
                    922:  * A NULL 'cred' indicates failure.
                    923:  */
                    924: void
                    925: ppp_link_auth_complete(struct ppp_link *link, int dir,
                    926:        const struct ppp_auth_cred *cred, const union ppp_auth_mppe *mppe)
                    927: {
                    928:        struct ppp_link_auth *const auth = &link->auth[dir];
                    929: 
                    930:        /* Sanity check */
                    931:        assert(auth->arg != NULL);
                    932: 
                    933:        /* If auth failed, close link */
                    934:        if (cred == NULL) {
                    935:                LOG(LOG_NOTICE, "authorization %s peer failed",
                    936:                    dir == PPP_SELF ? "from" : "to");
                    937:                ppp_link_close(link);
                    938:                return;
                    939:        }
                    940: 
                    941:        /* Save credentials and MPPE info */
                    942:        auth->cred = *cred;
                    943:        if (mppe != NULL)
                    944:                auth->mppe = *mppe;
                    945: 
                    946:        /* Destroy auth object for this direction */
                    947:        (*auth->type->cancel)(auth->arg);
                    948:        auth->arg = NULL;
                    949: 
                    950:        /* If other direction still active, let it finish */
                    951:        if (link->auth[!dir].arg != NULL)
                    952:                return;
                    953: 
                    954:        /* Move to the 'UP' state */
                    955:        ppp_link_auth_stop(link);
                    956:        ppp_link_join(link);
                    957: }
                    958: 
                    959: /*
                    960:  * Get this link's authorization configuration.
                    961:  */
                    962: const struct ppp_auth_config *
                    963: ppp_link_auth_get_config(struct ppp_link *link)
                    964: {
                    965:        return (&link->conf.auth);
                    966: }
                    967: 
                    968: /*
                    969:  * Get this link's authorization type in one direction.
                    970:  */
                    971: const struct ppp_auth_type *
                    972: ppp_link_get_auth(struct ppp_link *link, int dir)
                    973: {
                    974:        dir &= 1;
                    975:        return (link->auth[dir].type);
                    976: }
                    977: 
                    978: /*
                    979:  * Get this link's log
                    980:  */
                    981: struct ppp_log *
                    982: ppp_link_get_log(struct ppp_link *link)
                    983: {
                    984:        return (link->log);
                    985: }
                    986: 
                    987: /***********************************************************************
                    988:                        BUNDLE OPERATIONS
                    989: ***********************************************************************/
                    990: 
                    991: /*
                    992:  * The link FSM has reached the OPENED state and authentication
                    993:  * was successful, so join a bundle.
                    994:  */
                    995: static void
                    996: ppp_link_join(struct ppp_link *link)
                    997: {
                    998:        assert(link->bundle == NULL);
                    999:        if ((link->bundle = ppp_engine_join(link->engine,
                   1000:            link, &link->node, &link->link_num)) == NULL) {
                   1001:                ppp_link_close(link);
                   1002:                return;
                   1003:        }
                   1004:        link->state = PPP_LINK_UP;
                   1005: }
                   1006: 
                   1007: /*
                   1008:  * Link has left the OPENED state, so leave bundle (if any).
                   1009:  */
                   1010: static void
                   1011: ppp_link_unjoin(struct ppp_link *link)
                   1012: {
                   1013:        ppp_bundle_unjoin(&link->bundle, link);         /* ok if bundle null */
                   1014: }
                   1015: 
                   1016: /***********************************************************************
                   1017:                        INTERNAL FUNCTIONS
                   1018: ***********************************************************************/
                   1019: 
                   1020: /*
                   1021:  * Acquire an ng_ppp(4) node for this link to use.
                   1022:  */
                   1023: static int
                   1024: ppp_link_get_node(struct ppp_link *link)
                   1025: {
                   1026:        const char *node;
                   1027:        const char *hook;
                   1028: 
                   1029:        /* Sanity check */
                   1030:        if (link->node != NULL)
                   1031:                return (0);
                   1032: 
                   1033:        /* Get new node */
                   1034:        if ((link->node = ppp_node_create(link->ev_ctx,
                   1035:            link->mutex, ppp_log_dup(link->log))) == NULL) {
                   1036:                LOG(LOG_ERR, "%s: %m", "creating ppp node");
                   1037:                return (-1);
                   1038:        }
                   1039: 
                   1040:        /* Connect device to node */
                   1041:        if ((node = ppp_channel_get_node(link->device)) == NULL
                   1042:            || (hook = ppp_channel_get_hook(link->device)) == NULL) {
                   1043:                LOG(LOG_ERR, "channel is not a device");
                   1044:                ppp_node_destroy(&link->node);
                   1045:                return (-1);
                   1046:        }
                   1047:        if (ppp_node_connect(link->node, 0, node, hook) == -1) {
                   1048:                LOG(LOG_ERR, "%s: %m", "connecting device to node");
                   1049:                ppp_node_destroy(&link->node);
                   1050:                return (-1);
                   1051:        }
                   1052: 
                   1053:        /* Receive all node bypass packets */
                   1054:        ppp_node_set_recv(link->node, ppp_link_node_recv, link);
                   1055: 
                   1056:        /* Done */
                   1057:        return (0);
                   1058: }
                   1059: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>