Annotation of embedaddon/libpdel/ppp/ppp_bundle.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_node.h"
47: #include "ppp/ppp_engine.h"
48: #include "ppp/ppp_link.h"
49: #include "ppp/ppp_lcp.h"
50: #include "ppp/ppp_ipcp.h"
51: #include "ppp/ppp_ccp.h"
52: #include "ppp/ppp_bundle.h"
53: #include "ppp/ppp_channel.h"
54: #include "ppp/ppp_msoft.h"
55:
56: #include <netgraph/ng_mppc.h>
57:
58: #ifndef MPPE_56
59: #define MPPE_56 0x00000080
60: #define MPPE_56_UNSUPPORTED
61: #endif
62:
63: #define BUNDLE_MTYPE "ppp_bundle"
64:
65: /* Bundle structure */
66: struct ppp_bundle {
67: struct ppp_engine *engine; /* engine that owns me */
68: struct ppp_bundle_config conf; /* bundle configuration */
69: struct ppp_node *node; /* ng_ppp(4) node */
70: struct ppp_log *log; /* log */
71: struct ng_ppp_node_conf node_conf; /* ng_ppp(4) node config */
72: struct paction *action; /* configuration action */
73: struct ppp_fsm *lcp; /* lcp fsm (for bundle only) */
74: struct ppp_fsm *ipcp; /* ipcp fsm */
75: struct ppp_fsm *ccp; /* ccp fsm */
76: struct pevent_ctx *ev_ctx; /* event context */
77: pthread_mutex_t *mutex; /* mutex */
78: struct pevent *lcp_event; /* lcp fsm event */
79: struct pevent *ipcp_event; /* ipcp fsm event */
80: struct pevent *ccp_event; /* ccp fsm event */
81: struct pevent *config_timeout;/* timer for config operation */
82: void *cookie; /* client bundle cookie */
83: void *plumb_arg; /* client plumbing arg */
84: union ppp_auth_mppe mppe; /* mppe from first link auth */
85: enum ppp_auth_index mppe_auth; /* type of auth on first link */
86: u_char mppe_server; /* which side is mppe server */
87: u_char mppe_64[2][8]; /* 64 bit mppe keys */
88: u_char mppe_128[2][16];/* 128 bit mppe keys */
89: u_char multilink; /* multilink active */
90: u_char shutdown; /* bundle shutting down */
91: u_char ipcp_up; /* ipcp is up */
92: u_char ccp_up; /* ccp is up */
93: struct ppp_eid eid[2]; /* endpoint id */
94: u_int nlinks; /* number of links */
95: struct ppp_link *links[NG_PPP_MAX_LINKS]; /* links */
96: char authname[2][PPP_MAX_AUTHNAME]; /* authname's */
97: };
98:
99: /* Internal functions */
100: static int ppp_bundle_configure(struct ppp_bundle *bundle);
101: static void ppp_bundle_shutdown(struct ppp_bundle *bundle);
102: static void ppp_bundle_fsm_dead(struct ppp_bundle *bundle);
103:
104: static ppp_node_recv_t ppp_bundle_node_recv;
105:
106: /* Event handlers */
107: static pevent_handler_t ppp_bundle_lcp_event;
108: static pevent_handler_t ppp_bundle_ipcp_event;
109: static pevent_handler_t ppp_bundle_ccp_event;
110:
111: /* Internal variables */
112: static const u_char ppp_bundle_zero[16]; /* all zeros */
113:
114: /* Macro for logging */
115: #define LOG(sev, fmt, args...) PPP_LOG(bundle->log, sev, fmt , ## args)
116:
117: /***********************************************************************
118: PUBLIC FUNCTIONS
119: ***********************************************************************/
120:
121: /*
122: * Create a new bundle from a newly opened link.
123: *
124: * We 'steal' the link's ng_ppp(4) node for the bundle's use.
125: * We assume the link's device is already connected as link #0.
126: *
127: * The "log" is destroyed when the bundle is destroyed.
128: */
129: struct ppp_bundle *
130: ppp_bundle_create(struct ppp_engine *engine,
131: struct ppp_link *link, struct ppp_node *node)
132: {
133: struct ppp_lcp_req lcp_req;
134: struct ppp_bundle *bundle;
135: int i;
136:
137: /* Create bundle */
138: if ((bundle = MALLOC(BUNDLE_MTYPE, sizeof(*bundle))) == NULL)
139: return (NULL);
140: memset(bundle, 0, sizeof(*bundle));
141: bundle->engine = engine;
142: bundle->ev_ctx = ppp_engine_get_ev_ctx(engine);
143: bundle->mutex = ppp_engine_get_mutex(engine);
144: bundle->node = node;
145: bundle->links[0] = link;
146: bundle->nlinks = 1;
147:
148: /* Make bundle known to engine */
149: if (ppp_engine_add_bundle(bundle->engine, bundle) == -1)
150: goto fail;
151:
152: /* Get link's negotiated LCP config and inherit from it */
153: ppp_link_get_lcp_req(link, &lcp_req);
154: for (i = 0; i < 2; i++) {
155: strlcpy(bundle->authname[i], ppp_link_get_authname(link, i),
156: sizeof(bundle->authname[i]));
157: bundle->eid[i] = lcp_req.eid[i];
158: }
159: bundle->multilink = lcp_req.multilink[PPP_SELF];
160: bundle->mppe_server = !ppp_link_get_origination(link);
161: bundle->mppe_auth = lcp_req.auth[bundle->mppe_server];
162: ppp_link_get_mppe(link, bundle->mppe_server, &bundle->mppe);
163:
164: /* Initialize ng_ppp(4) node configuration, enabling the first link */
165: if (ppp_node_get_config(bundle->node, &bundle->node_conf) == -1)
166: goto fail;
167: bundle->node_conf.links[0].enableLink = 1;
168: bundle->node_conf.bund.mrru = lcp_req.mrru[PPP_PEER];
169: bundle->node_conf.bund.enableMultilink = bundle->multilink;
170: bundle->node_conf.bund.xmitShortSeq = lcp_req.shortseq[PPP_PEER];
171: bundle->node_conf.bund.recvShortSeq = lcp_req.shortseq[PPP_SELF];
172:
173: /* Update ng_ppp(4) node configuration */
174: if (ppp_node_set_config(bundle->node, &bundle->node_conf) == -1)
175: goto fail;
176:
177: /* Acquire bundle configuration */
178: if (ppp_bundle_configure(bundle) == -1) {
179: ppp_log_put(ppp_link_get_log(link), LOG_ERR,
180: "%s: %m", "error configuring bundle");
181: goto fail;
182: }
183:
184: /* Receive all node bypass packets */
185: ppp_node_set_recv(node, ppp_bundle_node_recv, bundle);
186:
187: /* Done */
188: return (bundle);
189:
190: fail:
191: /* Clean up after failure */
192: paction_cancel(&bundle->action);
193: pevent_unregister(&bundle->lcp_event);
194: ppp_fsm_destroy(&bundle->lcp);
195: ppp_engine_del_bundle(bundle->engine, bundle);
196: FREE(BUNDLE_MTYPE, bundle);
197: return (NULL);
198: }
199:
200: /*
201: * Close a bundle.
202: */
203: void
204: ppp_bundle_close(struct ppp_bundle *bundle)
205: {
206: int i;
207:
208: if (bundle->ipcp != NULL)
209: ppp_fsm_input(bundle->ipcp, FSM_INPUT_CLOSE);
210: if (bundle->ccp != NULL)
211: ppp_fsm_input(bundle->ipcp, FSM_INPUT_CLOSE);
212: for (i = 0; i < bundle->nlinks; i++)
213: ppp_link_close(bundle->links[i]);
214: }
215:
216: /*
217: * Destroy a bundle.
218: */
219: void
220: ppp_bundle_destroy(struct ppp_bundle **bundlep)
221: {
222: struct ppp_bundle *const bundle = *bundlep;
223:
224: /* Avoid recursion */
225: if (bundle == NULL)
226: return;
227: *bundlep = NULL;
228: if (bundle->shutdown)
229: return;
230: bundle->shutdown = 1;
231:
232: /* XXX disable traffic on node first? */
233:
234: /* Unplumb bundle and release IP address */
235: if (bundle->plumb_arg != NULL) {
236: ppp_engine_bundle_unplumb(bundle->engine,
237: bundle->plumb_arg, bundle);
238: }
239: if (bundle->conf.ip[PPP_PEER].s_addr != 0) {
240: ppp_engine_release_ip(bundle->engine,
241: bundle, bundle->conf.ip[PPP_PEER]);
242: }
243:
244: /* Destroy all links */
245: while (bundle->nlinks > 0) {
246: struct ppp_link *link = bundle->links[0];
247:
248: ppp_link_destroy(&link);
249: }
250:
251: /* Destroy bundle */
252: paction_cancel(&bundle->action);
253: ppp_engine_del_bundle(bundle->engine, bundle);
254: pevent_unregister(&bundle->config_timeout);
255: pevent_unregister(&bundle->lcp_event);
256: pevent_unregister(&bundle->ipcp_event);
257: pevent_unregister(&bundle->ccp_event);
258: ppp_fsm_destroy(&bundle->lcp);
259: ppp_fsm_destroy(&bundle->ipcp);
260: ppp_fsm_destroy(&bundle->ccp);
261: ppp_node_destroy(&bundle->node);
262: ppp_log_close(&bundle->log);
263: FREE(BUNDLE_MTYPE, bundle);
264: }
265:
266: const char *
267: ppp_bundle_get_authname(struct ppp_bundle *bundle, int dir)
268: {
269: dir &= 1;
270: return (bundle->authname[dir]);
271: }
272:
273: void
274: ppp_bundle_get_eid(struct ppp_bundle *bundle, int dir, struct ppp_eid *eid)
275: {
276: dir &= 1;
277: *eid = bundle->eid[dir];
278: }
279:
280: int
281: ppp_bundle_get_multilink(struct ppp_bundle *bundle)
282: {
283: return (bundle->multilink);
284: }
285:
286: int
287: ppp_bundle_get_links(struct ppp_bundle *bundle, struct ppp_link **list, int max)
288: {
289: int num;
290: int i;
291:
292: num = MIN(bundle->nlinks, max);
293: for (i = 0; i < num; i++)
294: list[i] = bundle->links[i];
295: return (num);
296: }
297:
298: int
299: ppp_bundle_get_ipcp(struct ppp_bundle *bundle,
300: struct ppp_ipcp_req *ipcp, int *is_up)
301: {
302: if (bundle->ipcp == NULL) {
303: errno = ENXIO;
304: return (-1);
305: }
306: if (ipcp != NULL)
307: ppp_ipcp_get_req(bundle->ipcp, ipcp);
308: if (is_up != NULL)
309: *is_up = (ppp_fsm_get_state(bundle->ipcp) == FSM_STATE_OPENED);
310: return (0);
311: }
312:
313: int
314: ppp_bundle_get_ccp(struct ppp_bundle *bundle,
315: struct ppp_ccp_req *ccp, int *is_up)
316: {
317: if (bundle->ccp == NULL) {
318: errno = ENXIO;
319: return (-1);
320: }
321: if (ccp != NULL)
322: ppp_ccp_get_req(bundle->ccp, ccp);
323: if (is_up != NULL)
324: *is_up = (ppp_fsm_get_state(bundle->ccp) == FSM_STATE_OPENED);
325: return (0);
326: }
327:
328: void *
329: ppp_bundle_get_cookie(struct ppp_bundle *bundle)
330: {
331: return (bundle->cookie);
332: }
333:
334: /*
335: * Join a new link into a bundle that already has one or more links.
336: */
337: int
338: ppp_bundle_join(struct ppp_bundle *bundle, struct ppp_link *link,
339: struct ppp_node *node, u_int16_t *link_num)
340: {
341: struct ppp_channel *const device = ppp_link_get_device(link);
342: struct ng_ppp_node_conf bconf;
343: const char *path;
344: const char *hook;
345:
346: /* Sanity check */
347: if (!bundle->multilink) {
348: LOG(LOG_ERR, "multilink disabled on this bundle");
349: errno = EINVAL;
350: return (-1);
351: }
352: if (bundle->nlinks == NG_PPP_MAX_LINKS) {
353: LOG(LOG_ERR, "too many links in this bundle");
354: errno = ENOSPC;
355: return (-1);
356: }
357:
358: /* Disconnect device from link's node */
359: if (ppp_node_disconnect(bundle->node, 0) == -1) {
360: LOG(LOG_ERR, "can't disconnect link device: %m");
361: return (-1);
362: }
363:
364: /* Connect link's device to our node */
365: if ((path = ppp_channel_get_node(device)) == NULL
366: || (hook = ppp_channel_get_hook(device)) == NULL) {
367: LOG(LOG_ERR, "link's channel is not a device");
368: return (-1);
369: }
370: if (ppp_node_connect(bundle->node, bundle->nlinks, path, hook) == -1) {
371: LOG(LOG_ERR, "%s: %m", "connecting device to node");
372: return (-1);
373: }
374:
375: /* Copy over link's configuration from link node to bundle node */
376: if (ppp_node_get_config(node, &bconf) == -1) {
377: LOG(LOG_ERR, "can't get link's node configuration: %m");
378: return (-1);
379: }
380: bundle->node_conf.links[bundle->nlinks] = bconf.links[0];
381: bundle->node_conf.links[bundle->nlinks].enableLink = 1;
382:
383: /* Update node configuration */
384: if (ppp_node_set_config(bundle->node, &bundle->node_conf) == -1)
385: goto fail;
386:
387: /* Done */
388: *link_num = bundle->nlinks;
389: bundle->links[bundle->nlinks++] = link;
390: return (0);
391:
392: fail:
393: /* Clean up after failure */
394: bundle->node_conf.links[bundle->nlinks].enableLink = 0;
395: (void)ppp_node_set_config(bundle->node, &bundle->node_conf);
396: return (-1);
397: }
398:
399: /*
400: * Remove a link from a bundle.
401: */
402: void
403: ppp_bundle_unjoin(struct ppp_bundle **bundlep, struct ppp_link *link)
404: {
405: struct ppp_bundle *bundle = *bundlep;
406: int link_num;
407:
408: /* Get bundle */
409: if (bundle == NULL)
410: return;
411: *bundlep = NULL;
412:
413: /* Find link; do nothing if not found */
414: for (link_num = 0; link_num < bundle->nlinks
415: && bundle->links[link_num] != link; link_num++);
416: if (link_num == bundle->nlinks) {
417: LOG(LOG_ERR, "link %p not found in bundle", link);
418: return;
419: }
420:
421: /* Disable traffic on link */
422: bundle->node_conf.links[link_num].enableLink = 0;
423: if (ppp_node_set_config(bundle->node, &bundle->node_conf) == -1)
424: LOG(LOG_ERR, "can't disable link: %m");
425:
426: /* Disconnect link's device from bundle's node */
427: if (ppp_node_disconnect(bundle->node, link_num) == -1)
428: LOG(LOG_ERR, "can't disconnect link device: %m");
429:
430: /* Remove link from bundle */
431: memmove(&bundle->links[link_num], &bundle->links[link_num + 1],
432: (--bundle->nlinks - link_num) * sizeof(*bundle->links));
433:
434: /* If no links remain, remove bundle */
435: if (bundle->nlinks == 0)
436: ppp_bundle_destroy(&bundle);
437: }
438:
439: /*
440: * Handle protocol rejection by peer.
441: */
442: void
443: ppp_bundle_protorej(struct ppp_bundle *bundle, u_int16_t proto)
444: {
445: switch (proto) {
446: case PPP_PROTO_LCP: /* these are required */
447: case PPP_PROTO_MP:
448: case PPP_PROTO_IPCP:
449: case PPP_PROTO_IP:
450: case PPP_PROTO_VJCOMP:
451: case PPP_PROTO_VJUNCOMP:
452: case PPP_PROTO_COMPD:
453: ppp_bundle_shutdown(bundle);
454: break;
455: case PPP_PROTO_CCP: /* this one is maybe optional */
456: if (bundle->conf.mppe_reqd)
457: ppp_bundle_shutdown(bundle);
458: else {
459: pevent_unregister(&bundle->ccp_event);
460: ppp_fsm_destroy(&bundle->ccp);
461: }
462: return;
463: default: /* others we don't care */
464: break;
465: }
466: }
467:
468: /*
469: * Write to ng_ppp(4) node "bypass" hook.
470: */
471: int
472: ppp_bundle_write(struct ppp_bundle *bundle, u_int link_num,
473: u_int16_t proto, const void *data, size_t len)
474: {
475: return (ppp_node_write(bundle->node, link_num, proto, data, len));
476: }
477:
478: /***********************************************************************
479: BUNDLE CONFIGURATION
480: ***********************************************************************/
481:
482: #define BCONFIG_MTYPE "ppp_bundle.config"
483: #define CONFIG_TIMEOUT 20 /* 20 seconds */
484:
485: /* Configuration state */
486: struct ppp_bundle_config_state {
487: struct ppp_engine *engine;
488: struct ppp_bundle *bundle;
489: struct ppp_link *link;
490: struct ppp_bundle_config config;
491: void *cookie;
492: };
493:
494: static pevent_handler_t ppp_bundle_config_timeout;
495:
496: static paction_handler_t ppp_bundle_configure_main;
497: static paction_finish_t ppp_bundle_configure_finish;
498:
499: /*
500: * Initiate action to configure bundle.
501: */
502: static int
503: ppp_bundle_configure(struct ppp_bundle *bundle)
504: {
505: struct ppp_bundle_config_state *state;
506:
507: /* Initialize state */
508: if ((state = MALLOC(BCONFIG_MTYPE, sizeof(*state))) == NULL)
509: return (-1);
510: memset(state, 0, sizeof(*state));
511: state->engine = bundle->engine;
512: state->bundle = bundle;
513: state->link = bundle->links[0];
514:
515: /* Set a timeout for ppp_engine_bundle_config() to return */
516: if (pevent_register(bundle->ev_ctx, &bundle->config_timeout, 0,
517: bundle->mutex, ppp_bundle_config_timeout, bundle, PEVENT_TIME,
518: CONFIG_TIMEOUT * 1000) == -1) {
519: LOG(LOG_ERR, "%s: %m", "pevent_register");
520: goto fail;
521: }
522:
523: /* Get the configuration in a separate thread */
524: if (paction_start(&bundle->action, bundle->mutex,
525: ppp_bundle_configure_main, ppp_bundle_configure_finish,
526: state) == -1) {
527: LOG(LOG_ERR, "%s: %m", "paction_start");
528: goto fail;
529: }
530:
531: /* Done */
532: return (0);
533:
534: fail:
535: /* Clean up */
536: paction_cancel(&bundle->action);
537: pevent_unregister(&bundle->config_timeout);
538: FREE(BCONFIG_MTYPE, state);
539: return (-1);
540: }
541:
542: /*
543: * Configure bundle main routine.
544: *
545: * This is called from a separate thread.
546: */
547: static void
548: ppp_bundle_configure_main(void *arg)
549: {
550: struct ppp_bundle_config_state *const state = arg;
551:
552: /* Get configuration for the new bundle */
553: state->cookie = ppp_engine_bundle_config(state->engine,
554: state->link, &state->config);
555:
556: /* Disable 56-bit MPPE if not supported */
557: #ifdef MPPE_56_UNSUPPORTED
558: state->config.mppe_56 = 0;
559: #endif
560: }
561:
562: /*
563: * Configure bundle finish routine.
564: *
565: * This is called from a separate thread.
566: */
567: static void
568: ppp_bundle_configure_finish(void *arg, int was_canceled)
569: {
570: struct ppp_bundle_config_state *const state = arg;
571: struct ppp_bundle *bundle = state->bundle;
572: struct ppp_fsm_instance *inst = NULL;
573: struct ppp_ipcp_config ipcp_config;
574: int i;
575:
576: /* Canceled? */
577: if (was_canceled)
578: goto done;
579:
580: /* Cancel config timer */
581: pevent_unregister(&bundle->config_timeout);
582:
583: /* Check result */
584: if (state->cookie == NULL) {
585: ppp_log_put(ppp_link_get_log(bundle->links[0]),
586: LOG_ERR, "failed to configure new bundle");
587: goto fail;
588: }
589:
590: /* Copy config info to bundle */
591: bundle->conf = state->config;
592: bundle->cookie = state->cookie;
593: bundle->conf.logname[sizeof(bundle->conf.logname) - 1] = '\0';
594:
595: /* Create log */
596: if ((bundle->log = ppp_log_prefix(ppp_engine_get_log(bundle->engine),
597: "%s: ", *bundle->conf.logname != '\0' ? bundle->conf.logname :
598: ppp_link_get_authname(bundle->links[0], PPP_PEER))) == NULL) {
599: ppp_log_put(ppp_link_get_log(bundle->links[0]),
600: LOG_ERR, "failed to create bundle log: %m");
601: goto fail;
602: }
603:
604: /* Create LCP FSM */
605: if ((inst = ppp_lcp_create(NULL)) == NULL) {
606: LOG(LOG_ERR, "failed to create LCP: %m");
607: goto fail;
608: }
609: if ((bundle->lcp = ppp_fsm_create(bundle->ev_ctx,
610: bundle->mutex, inst, bundle->log)) == NULL) {
611: LOG(LOG_ERR, "failed to create LCP: %m");
612: goto fail;
613: }
614: inst = NULL;
615:
616: /* Listen for LCP events */
617: if (pevent_register(bundle->ev_ctx, &bundle->lcp_event,
618: PEVENT_RECURRING, bundle->mutex, ppp_bundle_lcp_event, bundle,
619: PEVENT_MESG_PORT, ppp_fsm_get_outport(bundle->lcp)) == -1) {
620: LOG(LOG_ERR, "%s: %m", "adding read event for lcp");
621: goto fail;
622: }
623:
624: /* Create IPCP FSM */
625: memset(&ipcp_config, 0, sizeof(ipcp_config));
626: if (bundle->conf.dns_servers[0].s_addr != 0) {
627: ipcp_config.dns[0] = bundle->conf.dns_servers[0];
628: ipcp_config.dns[1] = bundle->conf.dns_servers[1];
629: ipcp_config.do_dns[PPP_PEER] = 1;
630: }
631: if (bundle->conf.nbns_servers[0].s_addr != 0) {
632: ipcp_config.nbns[0] = bundle->conf.nbns_servers[0];
633: ipcp_config.nbns[1] = bundle->conf.nbns_servers[1];
634: ipcp_config.do_nbns[PPP_PEER] = 1;
635: }
636: for (i = 0; i < 2; i++) {
637: ipcp_config.ip[i] = bundle->conf.ip[i];
638: ipcp_config.mask[i].s_addr
639: = (ipcp_config.ip[i].s_addr == 0) ? 0 : 0xffffffff;
640: }
641: if ((inst = ppp_ipcp_create(&ipcp_config, bundle->node)) == NULL) {
642: LOG(LOG_ERR, "failed to create IPCP: %m");
643: goto fail;
644: }
645: if ((bundle->ipcp = ppp_fsm_create(bundle->ev_ctx,
646: bundle->mutex, inst, bundle->log)) == NULL) {
647: LOG(LOG_ERR, "failed to create IPCP: %m");
648: goto fail;
649: }
650: inst = NULL;
651:
652: /* Listen for IPCP events */
653: if (pevent_register(bundle->ev_ctx, &bundle->ipcp_event,
654: PEVENT_RECURRING, bundle->mutex, ppp_bundle_ipcp_event, bundle,
655: PEVENT_MESG_PORT, ppp_fsm_get_outport(bundle->ipcp)) == -1) {
656: LOG(LOG_ERR, "%s: %m", "adding ipcp event");
657: goto fail;
658: }
659:
660: /* Start IPCP */
661: ppp_fsm_input(bundle->ipcp, FSM_INPUT_UP);
662: ppp_fsm_input(bundle->ipcp, FSM_INPUT_OPEN);
663:
664: /* Create CCP FSM (if MPPE enabled) */
665: if (bundle->conf.mppe_40
666: || bundle->conf.mppe_56
667: || bundle->conf.mppe_128) {
668: struct ppp_ccp_config ccp_config;
669: int i;
670:
671: /* Create CCP config */
672: memset(&ccp_config, 0, sizeof(ccp_config));
673: for (i = 0; i < 2; i++) {
674: if (bundle->conf.mppe_40)
675: ccp_config.mppe40[i] = 1;
676: if (bundle->conf.mppe_56)
677: ccp_config.mppe56[i] = 1;
678: if (bundle->conf.mppe_128)
679: ccp_config.mppe128[i] = 1;
680: if (bundle->conf.mppe_stateless)
681: ccp_config.mppe_stateless[i] = 1;
682: }
683:
684: /* Derive the MPPE keys we'll need */
685: switch (bundle->mppe_auth) {
686: case PPP_AUTH_CHAP_MSV1:
687: for (i = 0; i < 2; i++) {
688: memcpy(&bundle->mppe_64[i],
689: bundle->mppe.msv1.key_64,
690: sizeof(bundle->mppe_64[i]));
691: memcpy(&bundle->mppe_128[i],
692: bundle->mppe.msv1.key_128,
693: sizeof(bundle->mppe_128[i]));
694: }
695: break;
696: case PPP_AUTH_CHAP_MSV2:
697: for (i = 0; i < 2; i++) {
698: memcpy(&bundle->mppe_64[i],
699: bundle->mppe.msv2.keys[!i
700: ^ bundle->mppe_server],
701: sizeof(bundle->mppe_64[i]));
702: memcpy(&bundle->mppe_128[i],
703: bundle->mppe.msv2.keys[!i
704: ^ bundle->mppe_server],
705: sizeof(bundle->mppe_128[i]));
706: }
707: break;
708: default:
709: if (bundle->conf.mppe_reqd) {
710: LOG(LOG_ERR, "MPPE %s but MS-CHAP was not"
711: " used for authentication", "required");
712: goto fail;
713: } else {
714: LOG(LOG_WARNING, "MPPE %s but MS-CHAP was not"
715: " used for authentication", "requested");
716: goto done;
717: }
718: break;
719: }
720:
721: /* Create CCP instance */
722: if ((inst = ppp_ccp_create(&ccp_config,
723: bundle->node)) == NULL) {
724: LOG(LOG_ERR, "failed to create CCP: %m");
725: goto fail;
726: }
727: if ((bundle->ccp = ppp_fsm_create(bundle->ev_ctx,
728: bundle->mutex, inst, bundle->log)) == NULL) {
729: LOG(LOG_ERR, "failed to create CCP: %m");
730: goto fail;
731: }
732: inst = NULL;
733:
734: /* Listen for CCP events */
735: if (pevent_register(bundle->ev_ctx, &bundle->ccp_event,
736: PEVENT_RECURRING, bundle->mutex, ppp_bundle_ccp_event,
737: bundle, PEVENT_MESG_PORT, ppp_fsm_get_outport(bundle->ccp))
738: == -1) {
739: LOG(LOG_ERR, "%s: %m", "adding ccp event");
740: goto fail;
741: }
742:
743: /* Start CCP */
744: ppp_fsm_input(bundle->ccp, FSM_INPUT_UP);
745: ppp_fsm_input(bundle->ccp, FSM_INPUT_OPEN);
746: }
747:
748: done:
749: /* Done */
750: FREE(BCONFIG_MTYPE, state);
751: return;
752:
753: fail:
754: /* Clean up after failure */
755: if (inst != NULL)
756: (*inst->type->destroy)(inst);
757: ppp_bundle_destroy(&bundle);
758: FREE(BCONFIG_MTYPE, state);
759: }
760:
761: /*
762: * Handle a timeout trying to configure the bundle.
763: */
764: static void
765: ppp_bundle_config_timeout(void *arg)
766: {
767: struct ppp_bundle *bundle = arg;
768:
769: LOG(LOG_ERR, "timed out configuring new bundle");
770: paction_cancel(&bundle->action);
771: ppp_bundle_destroy(&bundle);
772: }
773:
774: /***********************************************************************
775: PPP NODE OUTPUT HANDLER
776: ***********************************************************************/
777:
778: /*
779: * Handle data received from the node's bypass hook.
780: */
781: static void
782: ppp_bundle_node_recv(void *arg, u_int link_num,
783: u_int16_t proto, u_char *data, size_t len)
784: {
785: struct ppp_bundle *const bundle = arg;
786:
787: /* Check for link-specific packets */
788: if (PPP_PROTO_LINK_LAYER(proto) && link_num != NG_PPP_BUNDLE_LINKNUM) {
789: if (link_num >= bundle->nlinks)
790: return;
791: ppp_link_recv_bypass(bundle->links[link_num], proto, data, len);
792: return;
793: }
794:
795: /* Handle packet at the bundle level */
796: switch (proto) {
797: case PPP_PROTO_IPCP:
798: if (bundle->ipcp != NULL)
799: ppp_fsm_input(bundle->ipcp, FSM_INPUT_DATA, data, len);
800: break;
801: case PPP_PROTO_CCP:
802: if (bundle->ccp != NULL)
803: ppp_fsm_input(bundle->ccp, FSM_INPUT_DATA, data, len);
804: else if (bundle->action == NULL) /* got config already */
805: goto proto_reject;
806: break;
807: case PPP_PROTO_MP:
808: case PPP_PROTO_IP:
809: case PPP_PROTO_VJCOMP:
810: case PPP_PROTO_VJUNCOMP:
811: case PPP_PROTO_COMPD:
812: break;
813: default:
814: goto proto_reject;
815: }
816: return;
817:
818: proto_reject:
819: /* Send a protocol reject */
820: if (bundle->lcp != NULL) {
821: ppp_fsm_input(bundle->lcp,
822: FSM_INPUT_XMIT_PROTOREJ, proto, data, len);
823: }
824: }
825:
826: /***********************************************************************
827: LCP EVENT HANDLER
828: ***********************************************************************/
829:
830: static void
831: ppp_bundle_lcp_event(void *arg)
832: {
833: struct ppp_bundle *const bundle = arg;
834: struct mesg_port *const outport = ppp_fsm_get_outport(bundle->lcp);
835: struct ppp_fsm_output *output;
836:
837: /* Read and handle all FSM events */
838: while ((output = mesg_port_get(outport, 0)) != NULL) {
839:
840: /* Check it out */
841: switch (output->type) {
842: case FSM_OUTPUT_DATA: /* probably an echo reply */
843: ppp_node_write(bundle->node, NG_PPP_BUNDLE_LINKNUM,
844: PPP_PROTO_LCP, output->u.data.data,
845: output->u.data.length);
846: break;
847: case FSM_OUTPUT_PROTOREJ:
848: {
849: LOG(LOG_NOTICE, "peer rejected protocol 0x%04x",
850: output->u.proto);
851: ppp_bundle_protorej(bundle, output->u.proto);
852: break;
853: }
854: case FSM_OUTPUT_OPEN:
855: case FSM_OUTPUT_CLOSE:
856: case FSM_OUTPUT_UP:
857: case FSM_OUTPUT_DOWN:
858: case FSM_OUTPUT_DEAD:
859: LOG(LOG_NOTICE, "unexpected LCP output: %s",
860: ppp_fsm_output_str(output));
861: break;
862: }
863:
864: /* Free output */
865: ppp_fsm_free_output(output);
866: }
867: }
868:
869: /***********************************************************************
870: IPCP EVENT HANDLER
871: ***********************************************************************/
872:
873: static void
874: ppp_bundle_ipcp_event(void *arg)
875: {
876: struct ppp_bundle *const bundle = arg;
877: struct mesg_port *const outport = ppp_fsm_get_outport(bundle->ipcp);
878: struct ppp_fsm_output *output;
879:
880: /* Read and handle all FSM events */
881: while ((output = mesg_port_get(outport, 0)) != NULL) {
882:
883: /* Check it out */
884: switch (output->type) {
885: case FSM_OUTPUT_OPEN:
886: case FSM_OUTPUT_CLOSE:
887: break;
888: case FSM_OUTPUT_UP:
889: {
890: static const char *chooks[][2] = {
891: { NG_PPP_HOOK_VJC_IP, NG_VJC_HOOK_IP },
892: { NG_PPP_HOOK_VJC_COMP, NG_VJC_HOOK_VJCOMP },
893: { NG_PPP_HOOK_VJC_UNCOMP, NG_VJC_HOOK_VJUNCOMP },
894: { NG_PPP_HOOK_VJC_VJIP, NG_VJC_HOOK_VJIP },
895: };
896: struct ng_ppp_node_conf conf;
897: struct ngm_vjc_config vjc;
898: struct ppp_ipcp_req req;
899: struct ngm_mkpeer mkpeer;
900: char buf[16];
901: u_int mtu;
902: int i;
903:
904: /* Remember IPCP is up */
905: bundle->ipcp_up = 1;
906:
907: /* Get negotiated parameters */
908: ppp_ipcp_get_req(bundle->ipcp, &req);
909: strlcpy(buf, inet_ntoa(req.ip[PPP_SELF]), sizeof(buf));
910: LOG(LOG_INFO, "IPCP successfully configured: "
911: "%s -> %s", buf, inet_ntoa(req.ip[PPP_PEER]));
912:
913: /* Get ppp node config */
914: if (ppp_node_get_config(bundle->node, &conf) == -1) {
915: LOG(LOG_ERR, "can't get ppp node config: %m");
916: ppp_fsm_input(bundle->ipcp, FSM_INPUT_CLOSE);
917: break;
918: }
919:
920: /* Configure IP traffic */
921: conf.bund.enableIP =
922: !bundle->conf.mppe_reqd || bundle->ccp_up;
923: conf.bund.enableVJCompression = 0;
924: conf.bund.enableVJDecompression = 0;
925:
926: /* Skip VJC config if not negotiated */
927: if (!req.vjc[PPP_SELF].enabled
928: && !req.vjc[PPP_PEER].enabled)
929: goto no_vjc;
930:
931: /* Attach vjc node to ppp node */
932: (void)ppp_node_send_msg(bundle->node,
933: chooks[0][0], NGM_GENERIC_COOKIE,
934: NGM_SHUTDOWN, NULL, 0);
935: memset(&mkpeer, 0, sizeof(mkpeer));
936: strlcpy(mkpeer.type,
937: NG_VJC_NODE_TYPE, sizeof(mkpeer.type));
938: strlcpy(mkpeer.ourhook,
939: chooks[0][0], sizeof(mkpeer.ourhook));
940: strlcpy(mkpeer.peerhook,
941: chooks[0][1], sizeof(mkpeer.peerhook));
942: if (ppp_node_send_msg(bundle->node, NULL,
943: NGM_GENERIC_COOKIE, NGM_MKPEER, &mkpeer,
944: sizeof(mkpeer)) == -1) {
945: LOG(LOG_ERR, "can't attach VJC node: %m");
946: ppp_fsm_input(bundle->ipcp, FSM_INPUT_CLOSE);
947: break;
948: }
949: for (i = 1; i < sizeof(chooks) / sizeof(*chooks); i++) {
950: struct ngm_connect connect;
951:
952: memset(&connect, 0, sizeof(connect));
953: strlcpy(connect.path,
954: NG_PPP_HOOK_VJC_IP, sizeof(connect.path));
955: strlcpy(connect.ourhook,
956: chooks[i][0], sizeof(connect.ourhook));
957: strlcpy(connect.peerhook,
958: chooks[i][1], sizeof(connect.peerhook));
959: if (ppp_node_send_msg(bundle->node, NULL,
960: NGM_GENERIC_COOKIE, NGM_CONNECT, &connect,
961: sizeof(connect)) == -1) {
962: LOG(LOG_ERR,
963: "can't connect VJC node: %m");
964: ppp_fsm_input(bundle->ipcp,
965: FSM_INPUT_CLOSE);
966: break;
967: }
968: }
969: if (i < sizeof(chooks) / sizeof(*chooks)) /* failed */
970: break;
971:
972: /* Configure VJ compression node */
973: memset(&vjc, 0, sizeof(vjc));
974: vjc.enableComp = req.vjc[PPP_PEER].enabled;
975: vjc.enableDecomp = req.vjc[PPP_SELF].enabled;
976: vjc.maxChannel = req.vjc[PPP_PEER].maxchan;
977: vjc.compressCID = req.vjc[PPP_PEER].compcid;
978: if (ppp_node_send_msg(bundle->node, NG_PPP_HOOK_VJC_IP,
979: NGM_VJC_COOKIE, NGM_VJC_SET_CONFIG,
980: &vjc, sizeof(vjc)) == -1) {
981: LOG(LOG_ERR, "error configuring VJC node: %m");
982: ppp_fsm_input(bundle->ipcp, FSM_INPUT_CLOSE);
983: break;
984: }
985:
986: /* Configure ppp node to enable VJ (de)compression */
987: conf.bund.enableVJCompression
988: = req.vjc[PPP_PEER].enabled;
989: conf.bund.enableVJDecompression
990: = req.vjc[PPP_SELF].enabled;
991:
992: no_vjc:
993: /*
994: * Determine the MTU for the interface
995: *
996: * XXX if/when compression is added, we must account
997: * XXX for any possible payload expansion here as well
998: */
999: mtu = bundle->multilink ? bundle->node_conf.bund.mrru
1000: : bundle->node_conf.links[0].mru;
1001: if (bundle->conf.mppe_40
1002: || bundle->conf.mppe_56
1003: || bundle->conf.mppe_128)
1004: mtu -= 4; /* allow for mppe header */
1005:
1006: /* Plumb the 'top' side of the node */
1007: if ((bundle->plumb_arg =
1008: ppp_engine_bundle_plumb(bundle->engine, bundle,
1009: ppp_node_get_path(bundle->node), NG_PPP_HOOK_INET,
1010: req.ip, req.dns, req.nbns, mtu)) == NULL) {
1011: LOG(LOG_ERR, "error plumbing ppp node: %m");
1012: ppp_fsm_input(bundle->ipcp, FSM_INPUT_CLOSE);
1013: break;
1014: }
1015:
1016: /* Update ppp node configuration */
1017: if (ppp_node_set_config(bundle->node, &conf) == -1) {
1018: LOG(LOG_ERR, "error configuring ppp node: %m");
1019: ppp_fsm_input(bundle->ipcp, FSM_INPUT_CLOSE);
1020: break;
1021: }
1022: break;
1023: }
1024: case FSM_OUTPUT_DOWN:
1025: {
1026: struct ng_ppp_node_conf conf;
1027: void *parg;
1028:
1029: /* Remember IPCP is down */
1030: bundle->ipcp_up = 0;
1031:
1032: /* Get ppp node config */
1033: if (ppp_node_get_config(bundle->node, &conf) == -1) {
1034: LOG(LOG_ERR, "can't get ppp node config: %m");
1035: ppp_fsm_input(bundle->ipcp, FSM_INPUT_CLOSE);
1036: break;
1037: }
1038:
1039: /* Disable IP and VJC packets */
1040: conf.bund.enableIP = 0;
1041: conf.bund.enableVJCompression = 0;
1042: conf.bund.enableVJDecompression = 0;
1043:
1044: /* Update ppp node configuration */
1045: if (ppp_node_set_config(bundle->node, &conf) == -1) {
1046: LOG(LOG_ERR, "error configuring ppp node: %m");
1047: ppp_fsm_input(bundle->ipcp, FSM_INPUT_CLOSE);
1048: break;
1049: }
1050:
1051: /* Clobber VJC node (if any) */
1052: (void)ppp_node_send_msg(bundle->node,
1053: NG_PPP_HOOK_VJC_IP, NGM_GENERIC_COOKIE,
1054: NGM_SHUTDOWN, NULL, 0);
1055:
1056: /* Disconnect the 'top' side of the node */
1057: if ((parg = bundle->plumb_arg) != NULL) {
1058: bundle->plumb_arg = NULL;
1059: ppp_engine_bundle_unplumb(bundle->engine,
1060: parg, bundle);
1061: }
1062: break;
1063: }
1064: case FSM_OUTPUT_DATA:
1065: ppp_node_write(bundle->node, NG_PPP_BUNDLE_LINKNUM,
1066: PPP_PROTO_IPCP, output->u.data.data,
1067: output->u.data.length);
1068: break;
1069: case FSM_OUTPUT_PROTOREJ:
1070: LOG(LOG_NOTICE, "unexpected IPCP output: %s",
1071: ppp_fsm_output_str(output));
1072: break;
1073: case FSM_OUTPUT_DEAD:
1074: LOG(LOG_INFO, "IPCP is dead: %s",
1075: ppp_fsm_reason_str(output));
1076: ppp_fsm_destroy(&bundle->ipcp);
1077: ppp_bundle_fsm_dead(bundle);
1078: ppp_fsm_free_output(output);
1079: return;
1080: }
1081:
1082: /* Free output */
1083: ppp_fsm_free_output(output);
1084: }
1085: }
1086:
1087: /***********************************************************************
1088: CCP EVENT HANDLER
1089: ***********************************************************************/
1090:
1091: static void
1092: ppp_bundle_ccp_event(void *arg)
1093: {
1094: struct ppp_bundle *const bundle = arg;
1095: struct mesg_port *const outport = ppp_fsm_get_outport(bundle->ccp);
1096: struct ppp_fsm_output *output;
1097:
1098: /* Read and handle all FSM events */
1099: while ((output = mesg_port_get(outport, 0)) != NULL) {
1100:
1101: /* Check it out */
1102: switch (output->type) {
1103: case FSM_OUTPUT_OPEN:
1104: case FSM_OUTPUT_CLOSE:
1105: break;
1106: case FSM_OUTPUT_UP:
1107: {
1108: struct ng_ppp_node_conf conf;
1109: struct ngm_connect connect;
1110: struct ngm_mkpeer mkpeer;
1111: struct ppp_ccp_req req;
1112: char buf[2][64];
1113: int i;
1114:
1115: /* Remember CCP is up */
1116: bundle->ccp_up = 1;
1117:
1118: /* Some peers don't know 56 bit and will ack it too */
1119: for (i = 0; i < 2; i++) {
1120: if (req.mppe56[i]
1121: && (req.mppe40[i] || req.mppe128[i]))
1122: req.mppe56[i] = 0;
1123: }
1124:
1125: /* Get negotiated parameters */
1126: ppp_ccp_get_req(bundle->ccp, &req);
1127: for (i = 0; i < 2; i++) {
1128: strlcpy(buf[i], "MPPC", sizeof(buf[i]));
1129: if (req.mppc[i]) {
1130: strlcat(buf[i], " compression",
1131: sizeof(buf[i]));
1132: }
1133: if (req.mppe40[i]) {
1134: strlcat(buf[i], " 40 bit encryption",
1135: sizeof(buf[i]));
1136: } else if (req.mppe56[i]) {
1137: strlcat(buf[i], " 56 bit encryption",
1138: sizeof(buf[i]));
1139: } else if (req.mppe128[i]) {
1140: strlcat(buf[i], " 128 bit encryption",
1141: sizeof(buf[i]));
1142: }
1143: if (req.mppe_stateless[i]) {
1144: strlcat(buf[i], ", stateless",
1145: sizeof(buf[i]));
1146: }
1147: }
1148: LOG(LOG_INFO, "CCP successfully configured: "
1149: "Recv: %s; Xmit: %s", buf[PPP_SELF], buf[PPP_PEER]);
1150:
1151: /* Get ppp node config */
1152: if (ppp_node_get_config(bundle->node, &conf) == -1) {
1153: LOG(LOG_ERR, "can't get ppp node config: %m");
1154: ppp_fsm_input(bundle->ccp, FSM_INPUT_CLOSE);
1155: break;
1156: }
1157:
1158: /* Enable IP traffic now */
1159: if (bundle->ipcp_up)
1160: conf.bund.enableIP = 1;
1161:
1162: /* Configure ppp node to enable MPPC (de)compression */
1163: conf.bund.enableCompression = req.mppc[PPP_PEER]
1164: || req.mppe40[PPP_PEER]
1165: || req.mppe56[PPP_PEER]
1166: || req.mppe128[PPP_PEER];
1167: conf.bund.enableDecompression = req.mppc[PPP_SELF]
1168: || req.mppe40[PPP_SELF]
1169: || req.mppe56[PPP_SELF]
1170: || req.mppe128[PPP_SELF];
1171:
1172: /* Attach mppc node to ppp node */
1173: (void)ppp_node_send_msg(bundle->node,
1174: NG_PPP_HOOK_COMPRESS, NGM_GENERIC_COOKIE,
1175: NGM_SHUTDOWN, NULL, 0);
1176: memset(&mkpeer, 0, sizeof(mkpeer));
1177: strlcpy(mkpeer.type,
1178: NG_MPPC_NODE_TYPE, sizeof(mkpeer.type));
1179: strlcpy(mkpeer.ourhook,
1180: NG_PPP_HOOK_COMPRESS, sizeof(mkpeer.ourhook));
1181: strlcpy(mkpeer.peerhook,
1182: NG_MPPC_HOOK_COMP, sizeof(mkpeer.peerhook));
1183: if (ppp_node_send_msg(bundle->node, NULL,
1184: NGM_GENERIC_COOKIE, NGM_MKPEER, &mkpeer,
1185: sizeof(mkpeer)) == -1) {
1186: LOG(LOG_ERR, "can't attach MPPC node: %m");
1187: ppp_fsm_input(bundle->ccp, FSM_INPUT_CLOSE);
1188: break;
1189: }
1190: memset(&connect, 0, sizeof(connect));
1191: strlcpy(connect.path,
1192: NG_PPP_HOOK_COMPRESS, sizeof(connect.path));
1193: strlcpy(connect.ourhook,
1194: NG_PPP_HOOK_DECOMPRESS, sizeof(connect.ourhook));
1195: strlcpy(connect.peerhook,
1196: NG_MPPC_HOOK_DECOMP, sizeof(connect.peerhook));
1197: if (ppp_node_send_msg(bundle->node, NULL,
1198: NGM_GENERIC_COOKIE, NGM_CONNECT, &connect,
1199: sizeof(connect)) == -1) {
1200: LOG(LOG_ERR, "can't connect MPPC node: %m");
1201: ppp_fsm_input(bundle->ccp, FSM_INPUT_CLOSE);
1202: break;
1203: }
1204:
1205: /* Verify we have the MPPE keys that we need */
1206: for (i = 0; i < 2; i++) {
1207: if (((req.mppe40[i] || req.mppe56[i])
1208: && memcmp(&bundle->mppe_64[i],
1209: ppp_bundle_zero, 8) == 0)
1210: || (req.mppe128[i]
1211: && memcmp(&bundle->mppe_128[i],
1212: ppp_bundle_zero, 16) == 0)) {
1213: LOG(LOG_ERR, "can't do MPPE encryption:"
1214: " no keys were provided by the"
1215: " authentication process");
1216: ppp_fsm_input(bundle->ccp,
1217: FSM_INPUT_CLOSE);
1218: break;
1219: }
1220: }
1221: if (i < 2)
1222: break;
1223:
1224: /* Configure MPPC node in both directions */
1225: for (i = 0; i < 2; i++) {
1226: struct ng_mppc_config mppc;
1227:
1228: memset(&mppc, 0, sizeof(mppc));
1229: mppc.enable = req.mppc[i] || req.mppe40[i]
1230: || req.mppe56[i] || req.mppe128[i];
1231: if (req.mppc[i])
1232: mppc.bits |= MPPC_BIT;
1233: if (req.mppe40[i] || req.mppe56[i]) {
1234: mppc.bits |= req.mppe40[i] ?
1235: MPPE_40 : MPPE_56;
1236: memcpy(mppc.startkey,
1237: &bundle->mppe_64[i],
1238: sizeof(bundle->mppe_64[i]));
1239: } else if (req.mppe128[i]) {
1240: mppc.bits |= MPPE_128;
1241: memcpy(mppc.startkey,
1242: &bundle->mppe_128[i],
1243: sizeof(bundle->mppe_128[i]));
1244: }
1245: if (req.mppe_stateless[i])
1246: mppc.bits |= MPPE_STATELESS;
1247: if (ppp_node_send_msg(bundle->node,
1248: NG_PPP_HOOK_COMPRESS, NGM_MPPC_COOKIE,
1249: (i == PPP_SELF) ? NGM_MPPC_CONFIG_DECOMP
1250: : NGM_MPPC_CONFIG_COMP,
1251: &mppc, sizeof(mppc)) == -1) {
1252: LOG(LOG_ERR,
1253: "error configuring MPPC node: %m");
1254: ppp_fsm_input(bundle->ccp,
1255: FSM_INPUT_CLOSE);
1256: break;
1257: }
1258: }
1259:
1260: /* Update ppp node configuration */
1261: if (ppp_node_set_config(bundle->node, &conf) == -1) {
1262: LOG(LOG_ERR, "error configuring ppp node: %m");
1263: ppp_fsm_input(bundle->ccp, FSM_INPUT_CLOSE);
1264: break;
1265: }
1266: break;
1267: }
1268: case FSM_OUTPUT_DOWN:
1269: {
1270: struct ng_ppp_node_conf conf;
1271:
1272: /* Remember CCP is down */
1273: bundle->ccp_up = 0;
1274:
1275: /* Get ppp node config */
1276: if (ppp_node_get_config(bundle->node, &conf) == -1) {
1277: LOG(LOG_ERR, "can't get ppp node config: %m");
1278: ppp_fsm_input(bundle->ccp, FSM_INPUT_CLOSE);
1279: break;
1280: }
1281:
1282: /* Disable IP traffic if encryption is required */
1283: if (bundle->conf.mppe_reqd)
1284: conf.bund.enableIP = 0;
1285:
1286: /* Disable compression */
1287: conf.bund.enableCompression = 0;
1288: conf.bund.enableDecompression = 0;
1289:
1290: /* Update ppp node configuration */
1291: if (ppp_node_set_config(bundle->node, &conf) == -1) {
1292: LOG(LOG_ERR, "error configuring ppp node: %m");
1293: ppp_fsm_input(bundle->ccp, FSM_INPUT_CLOSE);
1294: break;
1295: }
1296:
1297: /* Clobber MPPC node */
1298: (void)ppp_node_send_msg(bundle->node,
1299: NG_PPP_HOOK_COMPRESS, NGM_GENERIC_COOKIE,
1300: NGM_SHUTDOWN, NULL, 0);
1301: break;
1302: }
1303: case FSM_OUTPUT_DATA:
1304: ppp_node_write(bundle->node, NG_PPP_BUNDLE_LINKNUM,
1305: PPP_PROTO_CCP, output->u.data.data,
1306: output->u.data.length);
1307: break;
1308: case FSM_OUTPUT_PROTOREJ:
1309: LOG(LOG_NOTICE, "unexpected CCP output: %s",
1310: ppp_fsm_output_str(output));
1311: break;
1312: case FSM_OUTPUT_DEAD:
1313: LOG(LOG_INFO, "CCP is dead: %s",
1314: ppp_fsm_reason_str(output));
1315: ppp_fsm_destroy(&bundle->ccp);
1316: ppp_bundle_fsm_dead(bundle);
1317: ppp_fsm_free_output(output);
1318: return;
1319: }
1320:
1321: /* Free output */
1322: ppp_fsm_free_output(output);
1323: }
1324: }
1325:
1326: /***********************************************************************
1327: INTERNAL FUNCTIONS
1328: ***********************************************************************/
1329:
1330: /*
1331: * One of our network control protocols has died.
1332: * If this is fatal, then shutdown the bundle.
1333: */
1334: static void
1335: ppp_bundle_fsm_dead(struct ppp_bundle *bundle)
1336: {
1337: if (bundle->ipcp == NULL) {
1338: ppp_bundle_shutdown(bundle);
1339: return;
1340: }
1341: if (bundle->conf.mppe_reqd && bundle->ccp == NULL) {
1342: LOG(LOG_ERR, "MPPE is required but CCP negotiation failed");
1343: ppp_bundle_shutdown(bundle);
1344: }
1345: }
1346:
1347: /*
1348: * Shutdown the bundle.
1349: */
1350: static void
1351: ppp_bundle_shutdown(struct ppp_bundle *bundle)
1352: {
1353: int i;
1354:
1355: if (bundle->ipcp != NULL)
1356: ppp_fsm_input(bundle->ipcp, FSM_INPUT_CLOSE);
1357: if (bundle->ccp != NULL)
1358: ppp_fsm_input(bundle->ccp, FSM_INPUT_CLOSE);
1359: for (i = 0; i < bundle->nlinks; i++)
1360: ppp_link_close(bundle->links[i]);
1361: }
1362:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>