Annotation of embedaddon/libpdel/ppp/ppp_fsm_option.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:
45: #define FSM_OPTION_MTYPE "ppp_fsm_option"
46:
47: /***********************************************************************
48: PUBLIC FUNCTIONS
49: ***********************************************************************/
50:
51: /*
52: * Create new options array.
53: */
54: struct ppp_fsm_options *
55: ppp_fsm_option_create(void)
56: {
57: struct ppp_fsm_options *opt;
58:
59: if ((opt = MALLOC(FSM_OPTION_MTYPE, sizeof(*opt))) == NULL)
60: return (NULL);
61: memset(opt, 0, sizeof(*opt));
62: return (opt);
63: }
64:
65: /*
66: * Destroy options array.
67: */
68: void
69: ppp_fsm_option_destroy(struct ppp_fsm_options **optsp)
70: {
71: struct ppp_fsm_options *const opts = *optsp;
72: int i;
73:
74: if (opts == NULL)
75: return;
76: *optsp = NULL;
77: for (i = 0; i < opts->num; i++)
78: FREE(FSM_OPTION_MTYPE, opts->opts[i].data);
79: FREE(FSM_OPTION_MTYPE, opts->opts);
80: FREE(FSM_OPTION_MTYPE, opts);
81: }
82:
83: /*
84: * Add an option to an options array.
85: */
86: int
87: ppp_fsm_option_add(struct ppp_fsm_options *opts,
88: u_char type, u_char len, const void *data)
89: {
90: struct ppp_fsm_option *opt;
91: void *buf = NULL;
92: void *mem;
93:
94: /* Copy option data into buffer */
95: if (len > 0) {
96: if ((buf = MALLOC(FSM_OPTION_MTYPE, len)) == NULL)
97: return (-1);
98: memcpy(buf, data, len);
99: }
100:
101: /* Extend options array by one */
102: if ((mem = REALLOC(FSM_OPTION_MTYPE, opts->opts,
103: (opts->num + 1) * sizeof(*opts->opts))) == NULL) {
104: FREE(FSM_OPTION_MTYPE, buf);
105: return (-1);
106: }
107: opts->opts = mem;
108: opt = &opts->opts[opts->num++];
109:
110: /* Fill in option info */
111: opt->type = type;
112: opt->len = len;
113: opt->data = buf;
114:
115: /* Done */
116: return (0);
117: }
118:
119: /*
120: * Remove an option from an options array.
121: */
122: int
123: ppp_fsm_option_del(struct ppp_fsm_options *opts, u_int index)
124: {
125: struct ppp_fsm_option *const opt = opts->opts + index;
126:
127: if (index >= opts->num) {
128: errno = EDOM;
129: return (-1);
130: }
131: FREE(FSM_OPTION_MTYPE, opt->data);
132: memmove(opts->opts + index, opts->opts + index + 1,
133: (--opts->num - index) * sizeof(*opts->opts));
134: return (0);
135: }
136:
137: /*
138: * Reset an options array to empty.
139: */
140: void
141: ppp_fsm_option_zero(struct ppp_fsm_options *opts)
142: {
143: while (opts->num > 0)
144: ppp_fsm_option_del(opts, 0);
145: FREE(FSM_OPTION_MTYPE, opts->opts);
146: opts->opts = NULL;
147: }
148:
149: /*
150: * Copy an options array.
151: */
152: struct ppp_fsm_options *
153: ppp_fsm_option_copy(struct ppp_fsm_options *opts)
154: {
155: struct ppp_fsm_options *copy;
156: int i;
157:
158: if ((copy = ppp_fsm_option_create()) == NULL)
159: return (NULL);
160: for (i = 0; i < opts->num; i++) {
161: const struct ppp_fsm_option *const opt = &opts->opts[i];
162:
163: if (ppp_fsm_option_add(copy,
164: opt->type, opt->len, opt->data) == -1) {
165: ppp_fsm_option_destroy(©);
166: return (NULL);
167: }
168: }
169: return (copy);
170: }
171:
172: /*
173: * Compare two options arrays for equality.
174: *
175: * If "i1" or "i2" is equal to -1 then we compare all options.
176: * Otherwise we just compare option "i1" of "o1" to option "i2" of "o2".
177: */
178: int
179: ppp_fsm_option_equal(const struct ppp_fsm_options *o1,
180: int i1, const struct ppp_fsm_options *o2, int i2)
181: {
182: int i;
183:
184: /* Compare all options? */
185: if (i1 == -1 && i2 == -1) {
186: if (o1->num != o2->num)
187: return (0);
188: for (i = 0; i < o1->num; i++) {
189: if (!ppp_fsm_option_equal(o1, i, o2, i))
190: return (0);
191: }
192: return (1);
193: }
194:
195: /* Sanity check indicies */
196: if (i1 < 0 || i2 < 0 || i1 >= o1->num || i2 >= o2->num) {
197: errno = EINVAL;
198: return (-1);
199: }
200:
201: /* Compare two options */
202: if (o1->opts[i1].type != o2->opts[i2].type)
203: return (0);
204: if (o1->opts[i1].len != o2->opts[i2].len)
205: return (0);
206: if (memcmp(o1->opts[i1].data, o2->opts[i2].data, o1->opts[i1].len) != 0)
207: return (0);
208: return (1);
209: }
210:
211: /*
212: * Print out options into the log.
213: */
214: void
215: ppp_fsm_options_decode(const struct ppp_fsm_optdesc *optlist,
216: const u_char *data, u_int len, char *buf, size_t bmax)
217: {
218: struct ppp_fsm_options *opts;
219: int i;
220:
221: /* Decode options */
222: if ((opts = ppp_fsm_option_unpack(data, len)) == NULL)
223: return;
224:
225: /* Special case for empty */
226: if (opts->num == 0) {
227: strlcpy(buf, "(no options)", bmax);
228: goto done;
229: }
230:
231: /* Print options into buffer */
232: strlcpy(buf, "", bmax);
233: for (i = 0; i < opts->num; i++) {
234: const struct ppp_fsm_option *const opt = &opts->opts[i];
235: const struct ppp_fsm_optdesc *const desc
236: = ppp_fsm_option_desc(optlist, opt);
237:
238: if (i > 0)
239: strlcat(buf, " ", bmax); /* separator */
240: strlcat(buf, "[", bmax);
241: if (desc == NULL) {
242: snprintf(buf + strlen(buf), bmax - strlen(buf),
243: "?%u (len=%u)", opt->type, opt->len);
244: } else {
245: strlcat(buf, desc->name, bmax);
246: if (desc->print != NULL) {
247: strlcat(buf, " ", bmax);
248: (*desc->print)(desc, opt,
249: buf + strlen(buf), bmax - strlen(buf));
250: }
251: }
252: strlcat(buf, "]", bmax);
253: }
254:
255: done:
256: /* Clean up */
257: ppp_fsm_option_destroy(&opts);
258: }
259:
260: /*
261: * Find option descriptor in a table.
262: */
263: const struct ppp_fsm_optdesc *
264: ppp_fsm_option_desc(const struct ppp_fsm_optdesc *optlist,
265: const struct ppp_fsm_option *opt)
266: {
267: const struct ppp_fsm_optdesc *desc;
268:
269: for (desc = optlist; desc->name != NULL; desc++) {
270: if (opt->type == desc->type)
271: return (desc);
272: }
273: return (NULL);
274: }
275:
276: /***********************************************************************
277: PACKING/UNPACKING OPTIONS
278: ***********************************************************************/
279:
280: /*
281: * Extract encoded options, stopping at the first malformed option.
282: *
283: * Returns NULL if there was a system error.
284: */
285: struct ppp_fsm_options *
286: ppp_fsm_option_unpack(const u_char *data, u_int len)
287: {
288: struct ppp_fsm_options *opts;
289:
290: if ((opts = ppp_fsm_option_create()) == NULL)
291: return (NULL);
292: while (len >= 2) {
293: const u_char type = data[0];
294: const u_char olen = data[1];
295:
296: if (olen < 2 || olen > len)
297: break;
298: if (ppp_fsm_option_add(opts, type, olen - 2, data + 2) == -1) {
299: ppp_fsm_option_destroy(&opts);
300: return (NULL);
301: }
302: data += olen;
303: len -= olen;
304: }
305: return (opts);
306: }
307:
308: /*
309: * Compute length of packed options.
310: */
311: u_int
312: ppp_fsm_option_packlen(struct ppp_fsm_options *opts)
313: {
314: u_int len;
315: int i;
316:
317: for (len = i = 0; i < opts->num; i++)
318: len += 2 + opts->opts[i].len;
319: return (len);
320: }
321:
322: /*
323: * Pack options into buffer.
324: */
325: void
326: ppp_fsm_option_pack(struct ppp_fsm_options *opts, u_char *buf)
327: {
328: int i;
329:
330: for (i = 0; i < opts->num; i++) {
331: struct ppp_fsm_option *const opt = &opts->opts[i];
332:
333: *buf++ = opt->type;
334: *buf++ = 2 + opt->len;
335: memcpy(buf, opt->data, opt->len);
336: buf += opt->len;
337: }
338: }
339:
340: /***********************************************************************
341: BUILT-IN OPTIONS PRINTER FUNCTIONS
342: ***********************************************************************/
343:
344: #define MAX_BINARY 16
345:
346: /*
347: * Print option as binary data.
348: */
349: void
350: ppp_fsm_pr_binary(const struct ppp_fsm_optdesc *desc,
351: const struct ppp_fsm_option *opt, char *buf, size_t bmax)
352: {
353: int i;
354:
355: for (i = 0; i < opt->len; i++) {
356: if (i >= MAX_BINARY) {
357: snprintf(buf + strlen(buf), bmax - strlen(buf),
358: "...");
359: break;
360: }
361: if (i == 0)
362: snprintf(buf, bmax, "%02x", opt->data[0]);
363: else
364: snprintf(buf + strlen(buf), bmax - strlen(buf),
365: " %02x", opt->data[i]);
366: }
367: }
368:
369: /*
370: * Print option as 32 bit hex value.
371: */
372: void
373: ppp_fsm_pr_hex32(const struct ppp_fsm_optdesc *desc,
374: const struct ppp_fsm_option *opt, char *buf, size_t bmax)
375: {
376: u_int32_t val;
377:
378: if (opt->len < 4) {
379: snprintf(buf, bmax, "<truncated>");
380: return;
381: }
382: memcpy(&val, opt->data, 4);
383: val = ntohl(val);
384: snprintf(buf, bmax, "0x%08x", val);
385: }
386:
387: /*
388: * Print option as a 16 bit hex value.
389: */
390: void
391: ppp_fsm_pr_int16(const struct ppp_fsm_optdesc *desc,
392: const struct ppp_fsm_option *opt, char *buf, size_t bmax)
393: {
394: u_int16_t val;
395:
396: if (opt->len < 2) {
397: snprintf(buf, bmax, "<truncated>");
398: return;
399: }
400: memcpy(&val, opt->data, 2);
401: val = ntohs(val);
402: snprintf(buf, bmax, "%u", val);
403: }
404:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>