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(&copy);
                    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>