Annotation of embedaddon/libpdel/ppp/ppp_engine.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_node.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_bundle.h"
                     49: #include "ppp/ppp_manager.h"
                     50: #include "ppp/ppp_engine.h"
                     51: #include "ppp/ppp_pptp_server.h"
                     52: #include "ppp/ppp_l2tp_server.h"
                     53: 
                     54: #define ENGINE_MTYPE           "ppp_engine"
                     55: #define ENGINE_HASH_LOAD       200
                     56: 
                     57: struct ppp_engine {
                     58:        struct ppp_manager      *manager;       /* ppp manager object */
                     59:        struct pevent_ctx       *ev_ctx;        /* event context */
                     60:        pthread_mutex_t         mutex;          /* mutex for context */
                     61:        struct ppp_log          *log;           /* log */
                     62:        struct ghash            *bundles;       /* bundles, each >= 1 link */
                     63:        struct ghash            *links;         /* "floating" unbundled links */
                     64:        void                    *pptp_server;   /* pptp server */
                     65:        void                    *l2tp_server;   /* l2tp server */
                     66: };
                     67: 
                     68: /* Macro for logging */
                     69: #define LOG(sev, fmt, args...) PPP_LOG(engine->log, sev, fmt , ## args)
                     70: 
                     71: /*
                     72:  * Create a new PPP engine.
                     73:  *
                     74:  * The "log" is destroyed when the engine is destroyed.
                     75:  */
                     76: struct ppp_engine *
                     77: ppp_engine_create(struct ppp_manager *manager,
                     78:        const pthread_attr_t *attr, struct ppp_log *log)
                     79: {
                     80:        struct ppp_engine *engine;
                     81:        pthread_mutexattr_t mattr;
                     82:        int got_mutex = 0;
                     83:        int got_mattr = 0;
                     84: 
                     85:        /* Create engine object */
                     86:        if ((engine = MALLOC(ENGINE_MTYPE, sizeof(*engine))) == NULL)
                     87:                return (NULL);
                     88:        memset(engine, 0, sizeof(*engine));
                     89:        engine->manager = manager;
                     90:        engine->log = log;
                     91: 
                     92:        /* Create hash tables */
                     93:        if ((engine->links = ghash_create(engine, 0, ENGINE_HASH_LOAD,
                     94:            ENGINE_MTYPE, NULL, NULL, NULL, NULL)) == NULL)
                     95:                goto fail;
                     96:        if ((engine->bundles = ghash_create(engine, 0, ENGINE_HASH_LOAD,
                     97:            ENGINE_MTYPE, NULL, NULL, NULL, NULL)) == NULL)
                     98:                goto fail;
                     99: 
                    100:        /* Initialize mutex */
                    101:        if ((errno = pthread_mutexattr_init(&mattr)) != 0)
                    102:                goto fail;
                    103:        got_mattr = 1;
                    104:        if ((errno = pthread_mutexattr_settype(&mattr,
                    105:            PTHREAD_MUTEX_RECURSIVE)) != 0)
                    106:                goto fail;
                    107:        if ((errno = pthread_mutex_init(&engine->mutex, &mattr)) != 0)
                    108:                goto fail;
                    109:        got_mutex = 1;
                    110:        pthread_mutexattr_destroy(&mattr);
                    111:        got_mattr = 0;
                    112: 
                    113:        /* Create event context */
                    114:        if ((engine->ev_ctx = pevent_ctx_create("ppp_engine", attr)) == NULL)
                    115:                goto fail;
                    116: 
                    117:        /* Done */
                    118:        return (engine);
                    119: 
                    120: fail:
                    121:        /* Clean up after failure */
                    122:        ghash_destroy(&engine->bundles);
                    123:        ghash_destroy(&engine->links);
                    124:        if (got_mutex)
                    125:                pthread_mutex_destroy(&engine->mutex);
                    126:        if (got_mattr)
                    127:                pthread_mutexattr_destroy(&mattr);
                    128:        FREE(ENGINE_MTYPE, engine);
                    129:        return (NULL);
                    130: }
                    131: 
                    132: /*
                    133:  * Destroy a PPP engine.
                    134:  *
                    135:  * If "wait" is true, wait for all associated threads to exit.
                    136:  */
                    137: void
                    138: ppp_engine_destroy(struct ppp_engine **enginep, int wait)
                    139: {
                    140:        struct ppp_engine *const engine = *enginep;
                    141:        struct ppp_bundle **bundles;
                    142:        struct ppp_link **links;
                    143:        int num;
                    144:        int i;
                    145: 
                    146:        /* Sanity check */
                    147:        if (engine == NULL)
                    148:                return;
                    149:        *enginep = NULL;
                    150: 
                    151:        /* Stop PPTP and L2TP servers (if any) */
                    152:        ppp_pptp_server_stop(engine);
                    153:        ppp_l2tp_server_stop(engine);
                    154: 
                    155:        /* Destroy floating links */
                    156:        if ((num = ghash_dump(engine->links,
                    157:            (void ***)&links, TYPED_MEM_TEMP)) == -1)
                    158:                LOG(LOG_ERR, "%s: %m", "ghash_dump");
                    159:        else {
                    160:                for (i = 0; i < num; i++)
                    161:                        ppp_link_destroy(&links[i]);
                    162:                FREE(TYPED_MEM_TEMP, links);
                    163:        }
                    164: 
                    165:        /* Destroy bundles */
                    166:        if ((num = ghash_dump(engine->bundles,
                    167:            (void ***)&bundles, TYPED_MEM_TEMP)) == -1)
                    168:                LOG(LOG_ERR, "%s: %m", "ghash_dump");
                    169:        else {
                    170:                for (i = 0; i < num; i++)
                    171:                        ppp_bundle_destroy(&bundles[i]);
                    172:                FREE(TYPED_MEM_TEMP, bundles);
                    173:        }
                    174: 
                    175:        /* Destroy event context; there should be no remaining events */
                    176:        if ((num = pevent_ctx_count(engine->ev_ctx)) != 0) {
                    177:                LOG(LOG_ERR, "%s: %d events remain at shutdown",
                    178:                    __FUNCTION__, num);
                    179:        }
                    180:        pevent_ctx_destroy(&engine->ev_ctx);
                    181: 
                    182:        /* Free engine object */
                    183:        ghash_destroy(&engine->links);
                    184:        ghash_destroy(&engine->bundles);
                    185:        ppp_log_close(&engine->log);
                    186:        FREE(ENGINE_MTYPE, engine);
                    187: }
                    188: 
                    189: /*
                    190:  * Get a list of all known bundles.
                    191:  */
                    192: int
                    193: ppp_engine_get_bundles(struct ppp_engine *engine,
                    194:        struct ppp_bundle ***listp, const char *mtype)
                    195: {
                    196:        return (ghash_dump(engine->bundles, (void ***)listp, mtype));
                    197: }
                    198: 
                    199: /*
                    200:  * Add a newly created (and therefore "floating") link.
                    201:  */
                    202: int
                    203: ppp_engine_add_link(struct ppp_engine *engine, struct ppp_link *link)
                    204: {
                    205:        return (ghash_put(engine->links, link));
                    206: }
                    207: 
                    208: /*
                    209:  * Remove a "floating" link from the floating link hash table.
                    210:  */
                    211: void
                    212: ppp_engine_del_link(struct ppp_engine *engine, struct ppp_link *link)
                    213: {
                    214:        ghash_remove(engine->links, link);
                    215: }
                    216: 
                    217: /*
                    218:  * Add a bundle.
                    219:  */
                    220: int
                    221: ppp_engine_add_bundle(struct ppp_engine *engine, struct ppp_bundle *bundle)
                    222: {
                    223:        return (ghash_put(engine->bundles, bundle));
                    224: }
                    225: 
                    226: /*
                    227:  * Remove a bundle.
                    228:  */
                    229: void
                    230: ppp_engine_del_bundle(struct ppp_engine *engine, struct ppp_bundle *bundle)
                    231: {
                    232:        ghash_remove(engine->bundles, bundle);
                    233: }
                    234: 
                    235: /*
                    236:  * An "unbundled" link has reached the OPENED state and authenticated.
                    237:  * Add it to an existing bundle or create a new bundle as appropriate.
                    238:  */
                    239: struct ppp_bundle *
                    240: ppp_engine_join(struct ppp_engine *engine, struct ppp_link *link,
                    241:        struct ppp_node **nodep, u_int16_t *link_num)
                    242: {
                    243:        struct ppp_bundle *bundle = NULL;
                    244:        struct ppp_lcp_req lcp_req;
                    245:        struct ghash_walk walk;
                    246: 
                    247:        /* Sanity */
                    248:        assert(*nodep != NULL);
                    249: 
                    250:        /* If link does not have multilink, can't join any bundles */
                    251:        ppp_link_get_lcp_req(link, &lcp_req);
                    252:        if (!lcp_req.multilink[PPP_SELF] || !lcp_req.multilink[PPP_PEER])
                    253:                goto no_join;
                    254: 
                    255:        /* See if link matches any existing bundle */
                    256:        ghash_walk_init(engine->bundles, &walk);
                    257:        while ((bundle = ghash_walk_next(engine->bundles, &walk)) != NULL) {
                    258:                const char *link_authname[2];
                    259:                const char *bund_authname[2];
                    260:                struct ppp_eid link_eid[2];
                    261:                struct ppp_eid bund_eid[2];
                    262:                int j;
                    263: 
                    264:                /* If bundle does not have multilink, can't join it */
                    265:                if (!ppp_bundle_get_multilink(bundle))
                    266:                        continue;
                    267: 
                    268:                /* Get info about link and bundle */
                    269:                for (j = 0; j < 2; j++) {
                    270:                        link_authname[j] = ppp_link_get_authname(link, j);
                    271:                        ppp_link_get_eid(link, j, &link_eid[j]);
                    272:                        bund_authname[j] = ppp_bundle_get_authname(bundle, j);
                    273:                        ppp_bundle_get_eid(bundle, j, &bund_eid[j]);
                    274:                }
                    275: 
                    276:                /* Compare them */
                    277:                for (j = 0; j < 2; j++) {
                    278:                        if (strcmp(link_authname[j], bund_authname[j]) != 0)
                    279:                                break;
                    280:                        if (link_eid[j].class != bund_eid[j].class)
                    281:                                break;
                    282:                        if (link_eid[j].length != bund_eid[j].length)
                    283:                                break;
                    284:                        if (memcmp(link_eid[j].value,
                    285:                            bund_eid[j].value, link_eid[j].length) != 0)
                    286:                                break;
                    287:                }
                    288: 
                    289:                /* If equal, stop */
                    290:                if (j == 2)
                    291:                        break;
                    292:        }
                    293: 
                    294: no_join:
                    295:        /* If no matching bundle found, create a new one */
                    296:        if (bundle == NULL) {
                    297: 
                    298:                /* Create new bundle */
                    299:                if ((bundle = ppp_bundle_create(engine,
                    300:                    link, *nodep)) == NULL) {
                    301:                        PPP_LOG(ppp_link_get_log(link), LOG_ERR,
                    302:                            "failed to create new bundle: %m");
                    303:                        return (NULL);
                    304:                }
                    305: 
                    306:                /* The bundle steals the link's node */
                    307:                *nodep = NULL;
                    308:                *link_num = 0;
                    309:        } else {
                    310: 
                    311:                /* Join link into bundle */
                    312:                if (ppp_bundle_join(bundle, link, *nodep, link_num) == -1) {
                    313:                        PPP_LOG(ppp_link_get_log(link), LOG_ERR,
                    314:                            "link failed to join bundle: %m");
                    315:                        return (NULL);
                    316:                }
                    317: 
                    318:                /* Destroy link's node: it's no longer needed */
                    319:                ppp_node_destroy(nodep);
                    320:        }
                    321: 
                    322:        /* Link is no longer 'floating' as bundle now references it */
                    323:        ppp_engine_del_link(engine, link);
                    324: 
                    325:        /* Done */
                    326:        return (bundle);
                    327: }
                    328: 
                    329: void
                    330: ppp_engine_set_pptp_server(struct ppp_engine *engine, void *s)
                    331: {
                    332:        engine->pptp_server = s;
                    333: }
                    334: 
                    335: void *
                    336: ppp_engine_get_pptp_server(struct ppp_engine *engine)
                    337: {
                    338:        return (engine->pptp_server);
                    339: }
                    340: 
                    341: void
                    342: ppp_engine_set_l2tp_server(struct ppp_engine *engine, void *s)
                    343: {
                    344:        engine->l2tp_server = s;
                    345: }
                    346: 
                    347: void *
                    348: ppp_engine_get_l2tp_server(struct ppp_engine *engine)
                    349: {
                    350:        return (engine->l2tp_server);
                    351: }
                    352: 
                    353: struct pevent_ctx *
                    354: ppp_engine_get_ev_ctx(struct ppp_engine *engine)
                    355: {
                    356:        return (engine->ev_ctx);
                    357: }
                    358: 
                    359: pthread_mutex_t        *
                    360: ppp_engine_get_mutex(struct ppp_engine *engine)
                    361: {
                    362:        return (&engine->mutex);
                    363: }
                    364: 
                    365: struct ppp_log *
                    366: ppp_engine_get_log(struct ppp_engine *engine)
                    367: {
                    368:        return (engine->log);
                    369: }
                    370: 
                    371: /********************************************************************
                    372:                    MANAGER CALL-THROUGH FUNCTIONS
                    373: ********************************************************************/
                    374: 
                    375: /*
                    376:  * Configure a bundle.
                    377:  */
                    378: void *
                    379: ppp_engine_bundle_config(struct ppp_engine *engine,
                    380:        struct ppp_link *link, struct ppp_bundle_config *conf)
                    381: {
                    382:        return (ppp_manager_bundle_config(engine->manager, link, conf));
                    383: }
                    384: 
                    385: /*
                    386:  * Plumb 'top' side of netgraph node.
                    387:  */
                    388: void *
                    389: ppp_engine_bundle_plumb(struct ppp_engine *engine,
                    390:        struct ppp_bundle *bundle, const char *path, const char *hook,
                    391:        struct in_addr *ips, struct in_addr *dns, struct in_addr *nbns,
                    392:        u_int mtu)
                    393: {
                    394:        return (ppp_manager_bundle_plumb(engine->manager, bundle,
                    395:            path, hook, ips, dns, nbns, mtu));
                    396: }
                    397: 
                    398: /*
                    399:  * Disconnect 'top' side of netgraph node.
                    400:  */
                    401: void
                    402: ppp_engine_bundle_unplumb(struct ppp_engine *engine, void *arg,
                    403:        struct ppp_bundle *bundle)
                    404: {
                    405:        ppp_manager_bundle_unplumb(engine->manager, arg, bundle);
                    406: }
                    407: 
                    408: /*
                    409:  * Release an IP address for a peer.
                    410:  */
                    411: void
                    412: ppp_engine_release_ip(struct ppp_engine *engine,
                    413:        struct ppp_bundle *bundle, struct in_addr ip)
                    414: {
                    415:        ppp_manager_release_ip(engine->manager, bundle, ip);
                    416: }
                    417: 

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