Annotation of embedaddon/libpdel/ppp/ppp_lcp.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_fsm_option.h"
43: #include "ppp/ppp_fsm.h"
44: #include "ppp/ppp_auth.h"
45: #include "ppp/ppp_lcp.h"
46: #include "ppp/ppp_util.h"
47:
48: /* Memory type */
49: #define LCP_MTYPE "lcp"
50:
51: /* LCP configuration options */
52: enum lcp_option {
53: LCP_OPT_VENDOR =0, /* Vendor specific */
54: LCP_OPT_MRU =1, /* Maximum-Receive-Unit */
55: LCP_OPT_ACCMAP =2, /* Async-Control-Character-Map */
56: LCP_OPT_AUTH =3, /* Authentication-Protocol */
57: LCP_OPT_QUAL =4, /* Quality-Protocol */
58: LCP_OPT_MAGIC =5, /* Magic-Number */
59: LCP_OPT_PFCMP =7, /* Protocol-Field-Compression */
60: LCP_OPT_ACFCMP =8, /* Address&Ctrl-Field-Compression */
61: LCP_OPT_FCSALT =9, /* FCS-Alternatives */
62: LCP_OPT_SDP =10, /* Self-Dscribing-Padding */
63: LCP_OPT_NBMODE =11, /* Numbered-Mode */
64: LCP_OPT_MULTILINK =12, /* Multi-link procedure (?) */
65: LCP_OPT_CALLBK =13, /* Callback */
66: LCP_OPT_CTTIME =14, /* Connect time */
67: LCP_OPT_COMPFR =15, /* Compound-Frames */
68: LCP_OPT_NDS =16, /* Nominal-Data-Encapsulation */
69: LCP_OPT_MRRU =17, /* Multi-link MRRU size */
70: LCP_OPT_SHSEQ =18, /* Short seq number header */
71: LCP_OPT_EDISC =19, /* Unique endpoint discrimiator */
72: LCP_OPT_PROPR =20, /* Proprietary */
73: LCP_OPT_DCEID =21 /* DCE-Identifier */
74: };
75:
76: /* Supported and required FSM codes for normal LCP */
77: #define LCP_SUPPORTED_CODES \
78: (1 << FSM_CODE_CONFIGREQ) \
79: | (1 << FSM_CODE_CONFIGACK) \
80: | (1 << FSM_CODE_CONFIGNAK) \
81: | (1 << FSM_CODE_CONFIGREJ) \
82: | (1 << FSM_CODE_TERMREQ) \
83: | (1 << FSM_CODE_TERMACK) \
84: | (1 << FSM_CODE_CODEREJ) \
85: | (1 << FSM_CODE_PROTOREJ) \
86: | (1 << FSM_CODE_ECHOREQ) \
87: | (1 << FSM_CODE_ECHOREP) \
88: | (1 << FSM_CODE_DISCREQ) \
89: | (1 << FSM_CODE_IDENT) \
90: | (1 << FSM_CODE_TIMEREM)
91: #define LCP_REQUIRED_CODES \
92: (1 << FSM_CODE_CONFIGREQ) \
93: | (1 << FSM_CODE_CONFIGACK) \
94: | (1 << FSM_CODE_CONFIGNAK) \
95: | (1 << FSM_CODE_CONFIGREJ) \
96: | (1 << FSM_CODE_TERMREQ) \
97: | (1 << FSM_CODE_TERMACK) \
98: | (1 << FSM_CODE_CODEREJ) \
99: | (1 << FSM_CODE_PROTOREJ) \
100: | (1 << FSM_CODE_ECHOREQ) \
101: | (1 << FSM_CODE_ECHOREP)
102:
103: /* Supported and required FSM codes for LCP sent over a multilink bundle */
104: #define MP_LCP_SUPPORTED_CODES \
105: (1 << FSM_CODE_CODEREJ) \
106: | (1 << FSM_CODE_PROTOREJ) \
107: | (1 << FSM_CODE_ECHOREQ) \
108: | (1 << FSM_CODE_ECHOREP) \
109: | (1 << FSM_CODE_DISCREQ) \
110: | (1 << FSM_CODE_IDENT) \
111: | (1 << FSM_CODE_TIMEREM)
112: #define MP_LCP_REQUIRED_CODES \
113: (1 << FSM_CODE_CODEREJ) \
114: | (1 << FSM_CODE_PROTOREJ) \
115: | (1 << FSM_CODE_ECHOREQ) \
116: | (1 << FSM_CODE_ECHOREP)
117:
118: struct eid_type {
119: u_char min;
120: u_char max;
121: const char *desc;
122: };
123:
124: static const struct eid_type eid_types[PPP_EID_CLASS_MAX] = {
125: { 0, 0, "Null" }, /* PPP_EID_CLASS_NULL */
126: { 1, PPP_EID_MAXLEN, "Local" }, /* PPP_EID_CLASS_LOCAL */
127: { 4, 4, "IP" }, /* PPP_EID_CLASS_IP */
128: { 6, 6, "MAC" }, /* PPP_EID_CLASS_MAC */
129: { 4, PPP_EID_MAXLEN, "Magic" }, /* PPP_EID_CLASS_MAGIC */
130: { 1, PPP_EID_MAXLEN, "E.164" }, /* PPP_EID_CLASS_E164 */
131: };
132:
133: static opt_pr_t lcp_pr_eid;
134:
135: /* FSM options descriptors */
136: const struct ppp_fsm_optdesc lcp_opt_desc[] = {
137: { "Vendor", LCP_OPT_VENDOR, 4, 255, 0, NULL },
138: { "MRU", LCP_OPT_MRU, 2, 2, 1, ppp_fsm_pr_int16 },
139: { "ACCM", LCP_OPT_ACCMAP, 4, 4, 1, ppp_fsm_pr_hex32 },
140: { "Auth", LCP_OPT_AUTH, 2, 255, 1, ppp_auth_print},
141: { "Qual", LCP_OPT_QUAL, 0, 255, 0, NULL },
142: { "Magic", LCP_OPT_MAGIC, 4, 4, 1, ppp_fsm_pr_hex32 },
143: { "PFComp", LCP_OPT_PFCMP, 0, 0, 1, NULL },
144: { "ACFComp", LCP_OPT_ACFCMP, 0, 0, 1, NULL },
145: { "FCSAlt", LCP_OPT_FCSALT, 1, 1, 0, NULL },
146: { "SDP", LCP_OPT_SDP, 1, 1, 0, NULL },
147: { "NumMode", LCP_OPT_NBMODE, 0, 255, 0, NULL },
148: { "Callback", LCP_OPT_CALLBK, 1, 255, 0, NULL },
149: { "CnctTime", LCP_OPT_CTTIME, 0, 255, 0, NULL },
150: { "CompFrames", LCP_OPT_COMPFR, 0, 255, 0, NULL },
151: { "NDEncap", LCP_OPT_NDS, 0, 255, 0, NULL },
152: { "MP-MRRU", LCP_OPT_MRRU, 2, 2, 1, ppp_fsm_pr_int16 },
153: { "MP-ShortSq", LCP_OPT_SHSEQ, 0, 0, 1, NULL },
154: { "EID", LCP_OPT_EDISC, 1,
155: 1 + PPP_EID_MAXLEN, 1, lcp_pr_eid },
156: { "Proprietry", LCP_OPT_PROPR, 0, 255, 0, NULL },
157: { "DCE-Ident", LCP_OPT_DCEID, 0, 255, 0, NULL },
158: { NULL, 0, 0, 0, 0, NULL }
159: };
160:
161: /* Default configuration options */
162: static /*const*/ u_char lcp_default_mru[2] = {
163: (LCP_DEFAULT_MRU >> 8), (LCP_DEFAULT_MRU & 0xff)
164: };
165: static /*const*/ u_char lcp_default_accm[4] = {
166: 0xff, 0xff, 0xff, 0xff
167: };
168: static /*const*/ u_char lcp_default_eid[1] = {
169: PPP_EID_CLASS_NULL
170: };
171:
172: /* Default configuration option list */
173: static /*const*/ struct ppp_fsm_option lcp_opt_default_list[] = {
174: { LCP_OPT_MRU, sizeof(lcp_default_mru), lcp_default_mru },
175: { LCP_OPT_ACCMAP, sizeof(lcp_default_accm), lcp_default_accm },
176: { LCP_OPT_EDISC, sizeof(lcp_default_eid), lcp_default_eid },
177: };
178: static const struct ppp_fsm_options lcp_opt_default = {
179: sizeof(lcp_opt_default_list) / sizeof(*lcp_opt_default_list),
180: lcp_opt_default_list
181: };
182:
183: /* FSM type for LCP */
184: static ppp_fsm_type_destroy_t ppp_lcp_destroy;
185: static ppp_fsm_type_build_conf_req_t ppp_lcp_build_conf_req;
186: static ppp_fsm_type_recv_conf_req_t ppp_lcp_recv_conf_req;
187: static ppp_fsm_type_recv_conf_rej_t ppp_lcp_recv_conf_rej;
188: static ppp_fsm_type_recv_conf_nak_t ppp_lcp_recv_conf_nak;
189: static ppp_fsm_type_get_magic_t ppp_lcp_get_magic;
190:
191: const struct ppp_fsm_type ppp_fsm_lcp = {
192: "LCP",
193: PPP_PROTO_LCP,
194: LCP_SUPPORTED_CODES,
195: LCP_REQUIRED_CODES,
196: lcp_opt_desc,
197: &lcp_opt_default,
198: ppp_lcp_destroy,
199: ppp_lcp_build_conf_req,
200: ppp_lcp_recv_conf_req,
201: ppp_lcp_recv_conf_rej,
202: ppp_lcp_recv_conf_nak,
203: ppp_lcp_get_magic,
204: NULL,
205: NULL,
206: NULL
207: };
208:
209: const struct ppp_fsm_type ppp_fsm_mp_lcp = {
210: "LCP",
211: PPP_PROTO_LCP,
212: MP_LCP_SUPPORTED_CODES,
213: MP_LCP_REQUIRED_CODES,
214: NULL,
215: NULL,
216: ppp_lcp_destroy,
217: NULL,
218: NULL,
219: NULL,
220: NULL,
221: NULL,
222: NULL,
223: NULL,
224: NULL
225: };
226:
227: /* LCP instance state */
228: struct lcp {
229: struct ppp_lcp_config conf; /* initial config */
230: struct ppp_lcp_req req; /* current request state */
231: };
232:
233: /***********************************************************************
234: PUBLIC FUNCTIONS
235: ***********************************************************************/
236:
237: struct ppp_fsm_instance *
238: ppp_lcp_create(struct ppp_lcp_config *conf)
239: {
240: struct ppp_fsm_instance *inst;
241: struct ppp_lcp_req *req;
242: struct lcp *lcp = NULL;
243: int nauth[2];
244: int i;
245:
246: /* Construct instance object */
247: if ((inst = MALLOC(LCP_MTYPE, sizeof(*inst))) == NULL)
248: return (NULL);
249: memset(inst, 0, sizeof(*inst));
250: inst->type = (conf != NULL) ? &ppp_fsm_lcp : &ppp_fsm_mp_lcp;
251:
252: /* Attach private data */
253: if ((lcp = MALLOC(LCP_MTYPE, sizeof(*lcp))) == NULL)
254: goto fail;
255: memset(lcp, 0, sizeof(*lcp));
256: inst->arg = lcp;
257:
258: /* No configuration required for MP LCP's */
259: if (conf == NULL)
260: goto no_conf;
261:
262: /* Sanity check and normalize configuration */
263: lcp->conf = *conf;
264: conf = &lcp->conf;
265: for (i = 0; i < 2; i++) {
266: if (conf->max_mru[i] == 0)
267: conf->max_mru[i] = LCP_MAX_MRU;
268: if (conf->max_mrru[i] == 0)
269: conf->max_mrru[i] = LCP_MAX_MRRU;
270: conf->min_mru[i] = MAX(conf->min_mru[i], LCP_MIN_MRU);
271: conf->max_mru[i] = MIN(conf->max_mru[i], LCP_MAX_MRU);
272: conf->min_mrru[i] = MAX(conf->min_mrru[i], LCP_MIN_MRRU);
273: conf->max_mrru[i] = MIN(conf->max_mrru[i], LCP_MAX_MRRU);
274: }
275:
276: /* Multilink cannot be both enabled and denied */
277: if (!conf->multilink[PPP_PEER]) {
278: conf->shortseq[PPP_SELF] = 0;
279: conf->shortseq[PPP_PEER] = 0;
280: if (conf->multilink[PPP_SELF]) {
281: errno = EINVAL;
282: goto fail;
283: }
284: }
285:
286: /* Check MRU values are self-consistent */
287: if (conf->min_mru[PPP_SELF] > conf->max_mru[PPP_SELF]
288: || conf->min_mru[PPP_PEER] > conf->max_mru[PPP_PEER]
289: || conf->min_mrru[PPP_SELF] > conf->max_mrru[PPP_SELF]
290: || conf->min_mrru[PPP_PEER] > conf->max_mrru[PPP_PEER]) {
291: errno = EINVAL;
292: goto fail;
293: }
294:
295: /* Check MRRU values are self-consistent (if multilink is possible) */
296: if (conf->multilink[PPP_PEER]
297: && (conf->min_mrru[PPP_SELF] > conf->max_mrru[PPP_SELF]
298: || conf->min_mrru[PPP_PEER] > conf->max_mrru[PPP_PEER])) {
299: errno = EINVAL;
300: goto fail;
301: }
302:
303: /* Sanity check EID */
304: if (conf->eid.class >= PPP_EID_CLASS_MAX
305: || conf->eid.length < eid_types[conf->eid.class].min
306: || conf->eid.length > eid_types[conf->eid.class].max) {
307: errno = EINVAL;
308: goto fail;
309: }
310:
311: /*
312: * At least one type of authentication (including "none")
313: * must be enabled in each direction.
314: */
315: nauth[PPP_SELF] = 0;
316: nauth[PPP_PEER] = 0;
317: for (i = 0; i < PPP_AUTH_MAX; i++) {
318: if (conf->auth[PPP_SELF][i] != 0)
319: nauth[PPP_SELF]++;
320: if (conf->auth[PPP_PEER][i] != 0)
321: nauth[PPP_PEER]++;
322: }
323: if (nauth[PPP_SELF] == 0 || nauth[PPP_PEER] == 0) {
324: errno = EINVAL;
325: goto fail;
326: }
327:
328: /* Initialize local request state */
329: req = &lcp->req;
330: req->mru[PPP_SELF] = conf->max_mru[PPP_SELF];
331: req->accm[PPP_SELF] = conf->accm;
332: req->magic[PPP_SELF] = random() ^ time(NULL) ^ (getpid() << 16);
333: req->acfcomp[PPP_SELF] = conf->acfcomp[PPP_SELF];
334: req->pfcomp[PPP_SELF] = conf->pfcomp[PPP_SELF];
335: for (i = PPP_AUTH_MAX - 1; i >= 0; i--) {
336: if (conf->auth[PPP_SELF][i] != 0) {
337: req->auth[PPP_SELF] = i;
338: break;
339: }
340: }
341: req->multilink[PPP_SELF] = conf->multilink[PPP_SELF];
342: req->mrru[PPP_SELF] = conf->max_mrru[PPP_SELF];
343: req->shortseq[PPP_SELF] = conf->shortseq[PPP_SELF];
344: req->eid[PPP_SELF] = conf->eid;
345:
346: no_conf:
347: /* Done */
348: return (inst);
349:
350: fail:
351: /* Clean up after failure */
352: if (lcp != NULL)
353: FREE(LCP_MTYPE, lcp);
354: FREE(LCP_MTYPE, inst);
355: return (NULL);
356: }
357:
358: /*
359: * Get LCP request state.
360: */
361: void
362: ppp_lcp_get_req(struct ppp_fsm *fsm, struct ppp_lcp_req *req)
363: {
364: struct ppp_fsm_instance *const inst = ppp_fsm_get_instance(fsm);
365: struct lcp *const lcp = inst->arg;
366:
367: assert(inst->type == &ppp_fsm_lcp
368: || inst->type == &ppp_fsm_mp_lcp);
369: memcpy(req, &lcp->req, sizeof(*req));
370: }
371:
372: /***********************************************************************
373: FSM CALLBACKS
374: ***********************************************************************/
375:
376: static void
377: ppp_lcp_destroy(struct ppp_fsm_instance *inst)
378: {
379: struct lcp *const lcp = inst->arg;
380:
381: FREE(LCP_MTYPE, lcp);
382: FREE(LCP_MTYPE, inst);
383: }
384:
385: static int
386: ppp_lcp_build_conf_req(struct ppp_fsm_instance *fsm,
387: struct ppp_fsm_options *opts)
388: {
389: struct lcp *const lcp = (struct lcp *)fsm->arg;
390: struct ppp_lcp_req *const req = &lcp->req;
391: u_int16_t val16;
392: u_int32_t val32;
393:
394: /* Do MRU, ACCM, ACF compression, PF compression, and magic # */
395: val16 = htons(req->mru[PPP_SELF]);
396: if (ppp_fsm_option_add(opts, LCP_OPT_MRU, 2, &val16) == -1)
397: return (-1);
398: val32 = htonl(req->accm[PPP_SELF]);
399: if (ppp_fsm_option_add(opts, LCP_OPT_ACCMAP, 4, &val32) == -1)
400: return (-1);
401: if (req->acfcomp[PPP_SELF]
402: && ppp_fsm_option_add(opts, LCP_OPT_ACFCMP, 0, NULL) == -1)
403: return (-1);
404: if (req->pfcomp[PPP_SELF]
405: && ppp_fsm_option_add(opts, LCP_OPT_PFCMP, 0, NULL) == -1)
406: return (-1);
407: val32 = htonl(req->magic[PPP_SELF]);
408: if (ppp_fsm_option_add(opts, LCP_OPT_MAGIC, 4, &val32) == -1)
409: return (-1);
410: if (req->auth[PPP_SELF] != PPP_AUTH_NONE) {
411: const struct ppp_auth_type *const a
412: = ppp_auth_by_index(req->auth[PPP_SELF]);
413:
414: if (ppp_fsm_option_add(opts,
415: LCP_OPT_AUTH, a->len, a->data) == -1)
416: return (-1);
417: }
418:
419: /* Do multi-link stuff */
420: if (req->multilink[PPP_SELF]) {
421: val16 = htons(req->mrru[PPP_SELF]);
422: if (ppp_fsm_option_add(opts, LCP_OPT_MRRU, 2, &val16) == -1)
423: return (-1);
424: if (req->shortseq[PPP_SELF]
425: && ppp_fsm_option_add(opts, LCP_OPT_SHSEQ, 0, NULL) == -1)
426: return (-1);
427: }
428:
429: /* Do endpoint descriminator */
430: if (req->eid[PPP_SELF].class != PPP_EID_CLASS_NULL) {
431: u_char eid_buf[1 + PPP_EID_MAXLEN];
432:
433: eid_buf[0] = req->eid[PPP_SELF].class;
434: memcpy(eid_buf + 1,
435: req->eid[PPP_SELF].value, req->eid[PPP_SELF].length);
436: if (ppp_fsm_option_add(opts, LCP_OPT_EDISC,
437: 1 + req->eid[PPP_SELF].length, eid_buf) == -1)
438: return (-1);
439: }
440:
441: /* Done */
442: return (0);
443: }
444:
445: static int
446: ppp_lcp_recv_conf_req(struct ppp_fsm_instance *fsm, struct ppp_fsm_options *crq,
447: struct ppp_fsm_options *nak, struct ppp_fsm_options *rej)
448: {
449: struct lcp *const lcp = (struct lcp *)fsm->arg;
450: struct ppp_lcp_config *const conf = &lcp->conf;
451: struct ppp_lcp_req *const req = &lcp->req;
452: int i;
453:
454: /* Initialize peer's request state */
455: req->mru[PPP_PEER] = LCP_DEFAULT_MRU;
456: req->accm[PPP_PEER] = ~0;
457: req->acfcomp[PPP_PEER] = 0;
458: req->pfcomp[PPP_PEER] = 0;
459: req->magic[PPP_PEER] = 0;
460: req->auth[PPP_PEER] = PPP_AUTH_NONE;
461: req->mrru[PPP_PEER] = LCP_DEFAULT_MRRU;
462: req->multilink[PPP_PEER] = 0;
463: req->shortseq[PPP_PEER] = 0;
464: req->eid[PPP_PEER].class = PPP_EID_CLASS_NULL;
465: req->eid[PPP_PEER].length = 0;
466:
467: /* Process options */
468: for (i = 0; i < crq->num; i++) {
469: const struct ppp_fsm_option *const opt = &crq->opts[i];
470:
471: switch (opt->type) {
472: case LCP_OPT_MRU:
473: {
474: u_int16_t mru;
475:
476: memcpy(&mru, opt->data, 2);
477: mru = ntohs(mru);
478: if (mru < conf->min_mru[PPP_PEER]) {
479: mru = htons(conf->min_mru[PPP_PEER]);
480: if (ppp_fsm_option_add(nak, opt->type,
481: sizeof(mru), &mru) == -1)
482: return (-1);
483: break;
484: }
485: if (mru > conf->max_mru[PPP_PEER]) {
486: mru = htons(conf->max_mru[PPP_PEER]);
487: if (ppp_fsm_option_add(nak, opt->type,
488: sizeof(mru), &mru) == -1)
489: return (-1);
490: break;
491: }
492: req->mru[PPP_PEER] = mru;
493: break;
494: }
495: case LCP_OPT_ACCMAP:
496: {
497: memcpy(&req->accm[PPP_PEER], opt->data, 4);
498: req->accm[PPP_PEER] = ntohl(req->accm[PPP_PEER]);
499: break;
500: }
501: case LCP_OPT_PFCMP:
502: {
503: if (!conf->pfcomp[PPP_PEER])
504: goto reject;
505: req->pfcomp[PPP_PEER] = 1;
506: break;
507: }
508: case LCP_OPT_ACFCMP:
509: {
510: if (!conf->acfcomp[PPP_PEER])
511: goto reject;
512: req->acfcomp[PPP_PEER] = 1;
513: break;
514: }
515: case LCP_OPT_MAGIC:
516: {
517: u_int32_t magic;
518:
519: memcpy(&magic, opt->data, 4);
520: magic = ntohl(magic);
521: if (magic == req->magic[PPP_SELF]) {
522: errno = ELOOP; /* indicate loopback */
523: return (-1);
524: }
525: req->magic[PPP_PEER] = magic;
526: break;
527: }
528: case LCP_OPT_AUTH:
529: {
530: const struct ppp_auth_type *a = ppp_auth_by_option(opt);
531: int i;
532:
533: /* Sanity check */
534: if (a == NULL)
535: break;
536:
537: /* Check if we accept peer's auth proposal */
538: if (conf->auth[PPP_PEER][a->index] != 0) {
539: req->auth[PPP_PEER] = a->index;
540: break;
541: }
542:
543: /* See what other type we can do and nak with it */
544: for (i = 1; i < PPP_AUTH_MAX; i++) {
545: if (conf->auth[PPP_PEER][i] != 0) {
546: a = ppp_auth_by_index(i);
547: if (ppp_fsm_option_add(nak, opt->type,
548: a->len, a->data) == -1)
549: return (-1);
550: break;
551: }
552: }
553:
554: /* No auth type is acceptable */
555: goto reject;
556: }
557: case LCP_OPT_MRRU:
558: {
559: u_int16_t mrru;
560:
561: if (!conf->multilink[PPP_PEER])
562: goto reject;
563: memcpy(&mrru, opt->data, 2);
564: mrru = ntohs(mrru);
565: if (mrru < conf->min_mrru[PPP_PEER]) {
566: mrru = htons(conf->min_mrru[PPP_PEER]);
567: if (ppp_fsm_option_add(nak,
568: opt->type, 2, &mrru) == -1)
569: return (-1);
570: break;
571: }
572: if (mrru > conf->max_mrru[PPP_PEER]) {
573: mrru = htons(conf->max_mrru[PPP_PEER]);
574: if (ppp_fsm_option_add(nak,
575: opt->type, 2, &mrru) == -1)
576: return (-1);
577: break;
578: }
579: req->multilink[PPP_PEER] = 1;
580: req->multilink[PPP_SELF] = 1;
581: req->mrru[PPP_PEER] = mrru;
582: break;
583: }
584: case LCP_OPT_SHSEQ:
585: {
586: if (!conf->multilink[PPP_PEER]
587: || !conf->shortseq[PPP_PEER])
588: goto reject;
589: req->shortseq[PPP_PEER] = 1;
590: break;
591: }
592: case LCP_OPT_EDISC:
593: {
594: struct ppp_eid eid;
595:
596: if (opt->len < 1)
597: goto reject;
598: eid.class = opt->data[0];
599: eid.length = opt->len - 1;
600: if (eid.class >= PPP_EID_CLASS_MAX
601: || eid.length < eid_types[eid.class].min
602: || eid.length > eid_types[eid.class].max)
603: goto reject;
604: memcpy(eid.value, opt->data + 1, eid.length);
605: req->eid[PPP_PEER] = eid;
606: break;
607: }
608: default:
609: goto reject;
610: }
611:
612: /* OK */
613: continue;
614:
615: reject:
616: /* Reject this requested option */
617: if (ppp_fsm_option_add(rej,
618: opt->type, opt->len, opt->data) == -1)
619: return (-1);
620: }
621:
622: /* If no auth requested, but we require auth, nak for it */
623: if (req->auth[PPP_PEER] == PPP_AUTH_NONE
624: && !conf->auth[PPP_PEER][PPP_AUTH_NONE]) {
625: for (i = 1; i < PPP_AUTH_MAX; i++) {
626: if (conf->auth[PPP_PEER][i] != 0) {
627: const struct ppp_auth_type *const a
628: = ppp_auth_by_index(i);
629:
630: if (ppp_fsm_option_add(nak,
631: LCP_OPT_AUTH, a->len, a->data) == -1)
632: return (-1);
633: }
634: }
635: }
636:
637: /* Do same for multilink? */
638:
639: /* Done */
640: return (0);
641: }
642:
643: static int
644: ppp_lcp_recv_conf_rej(struct ppp_fsm_instance *fsm, struct ppp_fsm_options *rej)
645: {
646: struct lcp *const lcp = (struct lcp *)fsm->arg;
647: struct ppp_lcp_config *const conf = &lcp->conf;
648: struct ppp_lcp_req *const req = &lcp->req;
649: int i;
650:
651: for (i = 0; i < rej->num; i++) {
652: const struct ppp_fsm_option *const opt = &rej->opts[i];
653:
654: switch (opt->type) {
655: case LCP_OPT_MRU:
656: req->mru[PPP_SELF] = LCP_DEFAULT_MRU;
657: break;
658: case LCP_OPT_ACCMAP:
659: req->accm[PPP_SELF] = ~0;
660: break;
661: case LCP_OPT_PFCMP:
662: req->pfcomp[PPP_SELF] = 0;
663: break;
664: case LCP_OPT_ACFCMP:
665: req->acfcomp[PPP_SELF] = 0;
666: break;
667: case LCP_OPT_MAGIC:
668: req->magic[PPP_SELF] = 0;
669: break;
670: case LCP_OPT_AUTH:
671: {
672: const struct ppp_auth_type *a = ppp_auth_by_option(opt);
673: int i;
674:
675: /* Sanity check */
676: if (a == NULL)
677: break;
678:
679: /* Mark this auth type as rejected by peer */
680: req->auth_rej[a->index] = 1;
681:
682: /* Find next acceptable type not rejected by peer */
683: for (i = 0; i < PPP_AUTH_MAX; i++) {
684: if (conf->auth[PPP_SELF][i]
685: && !req->auth_rej[i]) {
686: req->auth[PPP_SELF] = i;
687: break;
688: }
689: }
690:
691: /* None found? Can't continue */
692: if (i == PPP_AUTH_MAX) {
693: errno = EINVAL;
694: return (-1);
695: }
696: break;
697: }
698: case LCP_OPT_MRRU:
699: req->multilink[PPP_SELF] = 0;
700: /* fall through */
701: case LCP_OPT_SHSEQ:
702: req->shortseq[PPP_SELF] = 0;
703: break;
704: case LCP_OPT_EDISC:
705: req->eid[PPP_SELF].class = PPP_EID_CLASS_NULL;
706: req->eid[PPP_SELF].length = 0;
707: break;
708: default:
709: break;
710: }
711: }
712:
713: /* Done */
714: return (0);
715: }
716:
717: static int
718: ppp_lcp_recv_conf_nak(struct ppp_fsm_instance *fsm, struct ppp_fsm_options *nak)
719: {
720: struct lcp *const lcp = (struct lcp *)fsm->arg;
721: struct ppp_lcp_config *const conf = &lcp->conf;
722: struct ppp_lcp_req *const req = &lcp->req;
723: int i;
724:
725: for (i = 0; i < nak->num; i++) {
726: const struct ppp_fsm_option *const opt = &nak->opts[i];
727:
728: switch (opt->type) {
729: case LCP_OPT_MRU:
730: {
731: u_int16_t mru;
732:
733: memcpy(&mru, opt->data, 2);
734: mru = ntohs(mru);
735: if (mru < conf->min_mru[PPP_SELF])
736: mru = conf->min_mru[PPP_SELF];
737: if (mru > conf->max_mru[PPP_SELF])
738: mru = conf->max_mru[PPP_SELF];
739: req->mru[PPP_SELF] = mru;
740: break;
741: }
742: case LCP_OPT_ACCMAP:
743: {
744: memcpy(&req->accm[PPP_SELF], opt->data, 4);
745: req->accm[PPP_SELF] = ntohl(req->accm[PPP_SELF]);
746: break;
747: }
748: case LCP_OPT_PFCMP:
749: {
750: if (conf->pfcomp[PPP_SELF])
751: req->pfcomp[PPP_SELF] = 1;
752: break;
753: }
754: case LCP_OPT_ACFCMP:
755: {
756: if (conf->acfcomp[PPP_SELF])
757: req->acfcomp[PPP_SELF] = 1;
758: break;
759: }
760: case LCP_OPT_AUTH:
761: {
762: const struct ppp_auth_type *a = ppp_auth_by_option(opt);
763:
764: if (a != NULL && conf->auth[PPP_SELF][a->index])
765: req->auth[PPP_SELF] = a->index;
766: break;
767: }
768: case LCP_OPT_MRRU:
769: {
770: u_int16_t mrru;
771:
772: memcpy(&mrru, opt->data, 2);
773: mrru = ntohs(mrru);
774: if (mrru < conf->min_mrru[PPP_SELF])
775: mrru = conf->min_mrru[PPP_SELF];
776: if (mrru > conf->max_mrru[PPP_SELF])
777: mrru = conf->max_mrru[PPP_SELF];
778: req->mrru[PPP_SELF] = mrru;
779: break;
780: }
781: case LCP_OPT_SHSEQ:
782: {
783: if (conf->shortseq[PPP_SELF])
784: req->shortseq[PPP_SELF] = 1;
785: break;
786: }
787: default:
788: break;
789: }
790: }
791:
792: /* Done */
793: return (0);
794: }
795:
796: static u_int32_t
797: ppp_lcp_get_magic(struct ppp_fsm_instance *fsm, int dir)
798: {
799: struct lcp *const lcp = (struct lcp *)fsm->arg;
800: struct ppp_lcp_req *const req = &lcp->req;
801:
802: return (req->magic[dir]);
803: }
804:
805: /***********************************************************************
806: INTERNAL FUNCTIONS
807: ***********************************************************************/
808:
809: static void
810: lcp_pr_eid(const struct ppp_fsm_optdesc *desc,
811: const struct ppp_fsm_option *opt, char *buf, size_t bmax)
812: {
813: const struct eid_type *type;
814: struct ppp_eid eid;
815: int i;
816:
817: if (opt->len < 1) {
818: strlcpy(buf, "<truncated>", bmax);
819: return;
820: }
821: eid.class = opt->data[0];
822: if (eid.class >= PPP_EID_CLASS_MAX) {
823: snprintf(buf, bmax, "<invalid class %u>", eid.class);
824: return;
825: }
826: type = &eid_types[eid.class];
827: eid.length = opt->len - 1;
828: if (eid.length < type->min || eid.length > type->max) {
829: snprintf(buf, bmax,
830: "[%s] <invalid length %d>", type->desc, eid.length);
831: return;
832: }
833: memcpy(eid.value, opt->data + 1, eid.length);
834: snprintf(buf, bmax, "%s:", type->desc);
835: switch (eid.class) {
836: case PPP_EID_CLASS_NULL:
837: break;
838: case PPP_EID_CLASS_IP:
839: {
840: struct in_addr ip;
841:
842: memcpy(&ip, eid.value, sizeof(ip));
843: strlcpy(buf + strlen(buf), inet_ntoa(ip), bmax - strlen(buf));
844: break;
845: }
846: case PPP_EID_CLASS_LOCAL:
847: for (i = 0; i < eid.length
848: && (isprint(eid.value[i]) || isspace(eid.value[i])); i++);
849: if (i == eid.length) {
850: ppp_util_ascify(buf + strlen(buf),
851: bmax - strlen(buf), eid.value, eid.length);
852: break;
853: }
854: /* FALL THROUGH */
855: default:
856: for (i = 0; i < eid.length; i++) {
857: snprintf(buf + strlen(buf), bmax - strlen(buf),
858: "%s%02x", (i > 0) ? ":" : "", eid.value[i]);
859: }
860: break;
861: }
862: }
863:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>