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>