Annotation of embedaddon/libpdel/ppp/ppp_engine.c, revision 1.1
1.1 ! misho 1:
! 2: /*
! 3: * Copyright (c) 2001-2002 Packet Design, LLC.
! 4: * All rights reserved.
! 5: *
! 6: * Subject to the following obligations and disclaimer of warranty,
! 7: * use and redistribution of this software, in source or object code
! 8: * forms, with or without modifications are expressly permitted by
! 9: * Packet Design; provided, however, that:
! 10: *
! 11: * (i) Any and all reproductions of the source or object code
! 12: * must include the copyright notice above and the following
! 13: * disclaimer of warranties; and
! 14: * (ii) No rights are granted, in any manner or form, to use
! 15: * Packet Design trademarks, including the mark "PACKET DESIGN"
! 16: * on advertising, endorsements, or otherwise except as such
! 17: * appears in the above copyright notice or in the software.
! 18: *
! 19: * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
! 20: * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
! 21: * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
! 22: * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
! 23: * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
! 24: * OR NON-INFRINGEMENT. PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
! 25: * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
! 26: * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
! 27: * RELIABILITY OR OTHERWISE. IN NO EVENT SHALL PACKET DESIGN BE
! 28: * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
! 29: * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
! 30: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
! 31: * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
! 32: * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
! 33: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 34: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
! 35: * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
! 36: * THE POSSIBILITY OF SUCH DAMAGE.
! 37: *
! 38: * Author: Archie Cobbs <archie@freebsd.org>
! 39: */
! 40:
! 41: #include "ppp/ppp_defs.h"
! 42: #include "ppp/ppp_log.h"
! 43: #include "ppp/ppp_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>