The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netgraph/ng_parse.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 
    2 /*
    3  * ng_parse.c
    4  *
    5  * Copyright (c) 1999 Whistle Communications, Inc.
    6  * All rights reserved.
    7  * 
    8  * Subject to the following obligations and disclaimer of warranty, use and
    9  * redistribution of this software, in source or object code forms, with or
   10  * without modifications are expressly permitted by Whistle Communications;
   11  * provided, however, that:
   12  * 1. Any and all reproductions of the source or object code must include the
   13  *    copyright notice above and the following disclaimer of warranties; and
   14  * 2. No rights are granted, in any manner or form, to use Whistle
   15  *    Communications, Inc. trademarks, including the mark "WHISTLE
   16  *    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
   17  *    such appears in the above copyright notice or in the software.
   18  * 
   19  * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
   20  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
   21  * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
   22  * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
   23  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
   24  * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
   25  * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
   26  * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
   27  * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
   28  * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
   29  * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
   30  * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
   31  * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
   32  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   33  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   34  * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
   35  * OF SUCH DAMAGE.
   36  *
   37  * Author: Archie Cobbs <archie@freebsd.org>
   38  *
   39  * $Whistle: ng_parse.c,v 1.3 1999/11/29 01:43:48 archie Exp $
   40  * $FreeBSD$
   41  */
   42 
   43 #include <sys/types.h>
   44 #include <sys/param.h>
   45 #include <sys/systm.h>
   46 #include <sys/errno.h>
   47 #include <sys/malloc.h>
   48 #include <sys/ctype.h>
   49 
   50 #include <netinet/in.h>
   51 
   52 #include <netgraph/ng_message.h>
   53 #include <netgraph/netgraph.h>
   54 #include <netgraph/ng_parse.h>
   55 
   56 /* Compute alignment for primitive integral types */
   57 struct int16_temp {
   58         char    x;
   59         int16_t y;
   60 };
   61 
   62 struct int32_temp {
   63         char    x;
   64         int32_t y;
   65 };
   66 
   67 struct int64_temp {
   68         char    x;
   69         int64_t y;
   70 };
   71 
   72 #define INT8_ALIGNMENT          1
   73 #define INT16_ALIGNMENT         ((int)&((struct int16_temp *)0)->y)
   74 #define INT32_ALIGNMENT         ((int)&((struct int32_temp *)0)->y)
   75 #define INT64_ALIGNMENT         ((int)&((struct int64_temp *)0)->y)
   76 
   77 /* Type of composite object: struct, array, or fixedarray */
   78 enum comptype {
   79         CT_STRUCT,
   80         CT_ARRAY,
   81         CT_FIXEDARRAY,
   82 };
   83 
   84 /* Composite types helper functions */
   85 static int      ng_parse_composite(const struct ng_parse_type *type,
   86                         const char *s, int *off, const u_char *start,
   87                         u_char *const buf, int *buflen, enum comptype ctype);
   88 static int      ng_unparse_composite(const struct ng_parse_type *type,
   89                         const u_char *data, int *off, char *cbuf, int cbuflen,
   90                         enum comptype ctype);
   91 static int      ng_get_composite_elem_default(const struct ng_parse_type *type,
   92                         int index, const u_char *start, u_char *buf,
   93                         int *buflen, enum comptype ctype);
   94 static int      ng_get_composite_len(const struct ng_parse_type *type,
   95                         const u_char *start, const u_char *buf,
   96                         enum comptype ctype);
   97 static const    struct ng_parse_type *ng_get_composite_etype(const struct
   98                         ng_parse_type *type, int index, enum comptype ctype);
   99 static int      ng_parse_get_elem_pad(const struct ng_parse_type *type,
  100                         int index, enum comptype ctype, int posn);
  101 
  102 /* Parsing helper functions */
  103 static int      ng_parse_skip_value(const char *s, int off, int *lenp);
  104 
  105 /* Poor man's virtual method calls */
  106 #define METHOD(t,m)     (ng_get_ ## m ## _method(t))
  107 #define INVOKE(t,m)     (*METHOD(t,m))
  108 
  109 static ng_parse_t       *ng_get_parse_method(const struct ng_parse_type *t);
  110 static ng_unparse_t     *ng_get_unparse_method(const struct ng_parse_type *t);
  111 static ng_getDefault_t  *ng_get_getDefault_method(const
  112                                 struct ng_parse_type *t);
  113 static ng_getAlign_t    *ng_get_getAlign_method(const struct ng_parse_type *t);
  114 
  115 #define ALIGNMENT(t)    (METHOD(t, getAlign) == NULL ? \
  116                                 0 : INVOKE(t, getAlign)(t))
  117 
  118 /* For converting binary to string */
  119 #define NG_PARSE_APPEND(fmt, args...)                           \
  120                 do {                                            \
  121                         int len;                                \
  122                                                                 \
  123                         len = snprintf((cbuf), (cbuflen),       \
  124                                 fmt , ## args);                 \
  125                         if (len >= (cbuflen))                   \
  126                                 return (ERANGE);                \
  127                         (cbuf) += len;                          \
  128                         (cbuflen) -= len;                       \
  129                 } while (0)
  130 
  131 /************************************************************************
  132                         PUBLIC FUNCTIONS
  133  ************************************************************************/
  134 
  135 /*
  136  * Convert an ASCII string to binary according to the supplied type descriptor
  137  */
  138 int
  139 ng_parse(const struct ng_parse_type *type,
  140         const char *string, int *off, u_char *buf, int *buflen)
  141 {
  142         return INVOKE(type, parse)(type, string, off, buf, buf, buflen);
  143 }
  144 
  145 /*
  146  * Convert binary to an ASCII string according to the supplied type descriptor
  147  */
  148 int
  149 ng_unparse(const struct ng_parse_type *type,
  150         const u_char *data, char *cbuf, int cbuflen)
  151 {
  152         int off = 0;
  153 
  154         return INVOKE(type, unparse)(type, data, &off, cbuf, cbuflen);
  155 }
  156 
  157 /*
  158  * Fill in the default value according to the supplied type descriptor
  159  */
  160 int
  161 ng_parse_getDefault(const struct ng_parse_type *type, u_char *buf, int *buflen)
  162 {
  163         ng_getDefault_t *const func = METHOD(type, getDefault);
  164 
  165         if (func == NULL)
  166                 return (EOPNOTSUPP);
  167         return (*func)(type, buf, buf, buflen);
  168 }
  169 
  170 
  171 /************************************************************************
  172                         STRUCTURE TYPE
  173  ************************************************************************/
  174 
  175 static int
  176 ng_struct_parse(const struct ng_parse_type *type,
  177         const char *s, int *off, const u_char *const start,
  178         u_char *const buf, int *buflen)
  179 {
  180         return ng_parse_composite(type, s, off, start, buf, buflen, CT_STRUCT);
  181 }
  182 
  183 static int
  184 ng_struct_unparse(const struct ng_parse_type *type,
  185         const u_char *data, int *off, char *cbuf, int cbuflen)
  186 {
  187         return ng_unparse_composite(type, data, off, cbuf, cbuflen, CT_STRUCT);
  188 }
  189 
  190 static int
  191 ng_struct_getDefault(const struct ng_parse_type *type,
  192         const u_char *const start, u_char *buf, int *buflen)
  193 {
  194         int off = 0;
  195 
  196         return ng_parse_composite(type,
  197             "{}", &off, start, buf, buflen, CT_STRUCT);
  198 }
  199 
  200 static int
  201 ng_struct_getAlign(const struct ng_parse_type *type)
  202 {
  203         const struct ng_parse_struct_info *si = type->info;
  204         const struct ng_parse_struct_field *field;
  205         int align = 0;
  206 
  207         for (field = si->fields; field->name != NULL; field++) {
  208                 int falign = ALIGNMENT(field->type);
  209 
  210                 if (falign > align)
  211                         align = falign;
  212         }
  213         return align;
  214 }
  215 
  216 const struct ng_parse_type ng_parse_struct_type = {
  217         NULL,
  218         NULL,
  219         NULL,
  220         ng_struct_parse,
  221         ng_struct_unparse,
  222         ng_struct_getDefault,
  223         ng_struct_getAlign
  224 };
  225 
  226 /************************************************************************
  227                         FIXED LENGTH ARRAY TYPE
  228  ************************************************************************/
  229 
  230 static int
  231 ng_fixedarray_parse(const struct ng_parse_type *type,
  232         const char *s, int *off, const u_char *const start,
  233         u_char *const buf, int *buflen)
  234 {
  235         return ng_parse_composite(type,
  236             s, off, start, buf, buflen, CT_FIXEDARRAY);
  237 }
  238 
  239 static int
  240 ng_fixedarray_unparse(const struct ng_parse_type *type,
  241         const u_char *data, int *off, char *cbuf, int cbuflen)
  242 {
  243         return ng_unparse_composite(type,
  244                 data, off, cbuf, cbuflen, CT_FIXEDARRAY);
  245 }
  246 
  247 static int
  248 ng_fixedarray_getDefault(const struct ng_parse_type *type,
  249         const u_char *const start, u_char *buf, int *buflen)
  250 {
  251         int off = 0;
  252 
  253         return ng_parse_composite(type,
  254             "[]", &off, start, buf, buflen, CT_FIXEDARRAY);
  255 }
  256 
  257 static int
  258 ng_fixedarray_getAlign(const struct ng_parse_type *type)
  259 {
  260         const struct ng_parse_fixedarray_info *fi = type->info;
  261 
  262         return ALIGNMENT(fi->elementType);
  263 }
  264 
  265 const struct ng_parse_type ng_parse_fixedarray_type = {
  266         NULL,
  267         NULL,
  268         NULL,
  269         ng_fixedarray_parse,
  270         ng_fixedarray_unparse,
  271         ng_fixedarray_getDefault,
  272         ng_fixedarray_getAlign
  273 };
  274 
  275 /************************************************************************
  276                         VARIABLE LENGTH ARRAY TYPE
  277  ************************************************************************/
  278 
  279 static int
  280 ng_array_parse(const struct ng_parse_type *type,
  281         const char *s, int *off, const u_char *const start,
  282         u_char *const buf, int *buflen)
  283 {
  284         return ng_parse_composite(type, s, off, start, buf, buflen, CT_ARRAY);
  285 }
  286 
  287 static int
  288 ng_array_unparse(const struct ng_parse_type *type,
  289         const u_char *data, int *off, char *cbuf, int cbuflen)
  290 {
  291         return ng_unparse_composite(type, data, off, cbuf, cbuflen, CT_ARRAY);
  292 }
  293 
  294 static int
  295 ng_array_getDefault(const struct ng_parse_type *type,
  296         const u_char *const start, u_char *buf, int *buflen)
  297 {
  298         int off = 0;
  299 
  300         return ng_parse_composite(type,
  301             "[]", &off, start, buf, buflen, CT_ARRAY);
  302 }
  303 
  304 static int
  305 ng_array_getAlign(const struct ng_parse_type *type)
  306 {
  307         const struct ng_parse_array_info *ai = type->info;
  308 
  309         return ALIGNMENT(ai->elementType);
  310 }
  311 
  312 const struct ng_parse_type ng_parse_array_type = {
  313         NULL,
  314         NULL,
  315         NULL,
  316         ng_array_parse,
  317         ng_array_unparse,
  318         ng_array_getDefault,
  319         ng_array_getAlign
  320 };
  321 
  322 /************************************************************************
  323                                 INT8 TYPE
  324  ************************************************************************/
  325 
  326 static int
  327 ng_int8_parse(const struct ng_parse_type *type,
  328         const char *s, int *off, const u_char *const start,
  329         u_char *const buf, int *buflen)
  330 {
  331         long val;
  332         int8_t val8;
  333         char *eptr;
  334 
  335         val = strtol(s + *off, &eptr, 0);
  336         if (val < -0x80 || val > 0xff || eptr == s + *off)
  337                 return (EINVAL);
  338         *off = eptr - s;
  339         val8 = (int8_t)val;
  340         bcopy(&val8, buf, sizeof(int8_t));
  341         *buflen = sizeof(int8_t);
  342         return (0);
  343 }
  344 
  345 static int
  346 ng_int8_unparse(const struct ng_parse_type *type,
  347         const u_char *data, int *off, char *cbuf, int cbuflen)
  348 {
  349         int8_t val;
  350 
  351         bcopy(data + *off, &val, sizeof(int8_t));
  352         NG_PARSE_APPEND("%d", (int)val);
  353         *off += sizeof(int8_t);
  354         return (0);
  355 }
  356 
  357 static int
  358 ng_int8_getDefault(const struct ng_parse_type *type,
  359         const u_char *const start, u_char *buf, int *buflen)
  360 {
  361         int8_t val;
  362 
  363         if (*buflen < sizeof(int8_t))
  364                 return (ERANGE);
  365         val = 0;
  366         bcopy(&val, buf, sizeof(int8_t));
  367         *buflen = sizeof(int8_t);
  368         return (0);
  369 }
  370 
  371 static int
  372 ng_int8_getAlign(const struct ng_parse_type *type)
  373 {
  374         return INT8_ALIGNMENT;
  375 }
  376 
  377 const struct ng_parse_type ng_parse_int8_type = {
  378         NULL,
  379         NULL,
  380         NULL,
  381         ng_int8_parse,
  382         ng_int8_unparse,
  383         ng_int8_getDefault,
  384         ng_int8_getAlign
  385 };
  386 
  387 /************************************************************************
  388                                 INT16 TYPE
  389  ************************************************************************/
  390 
  391 static int
  392 ng_int16_parse(const struct ng_parse_type *type,
  393         const char *s, int *off, const u_char *const start,
  394         u_char *const buf, int *buflen)
  395 {
  396         long val;
  397         int16_t val16;
  398         char *eptr;
  399 
  400         val = strtol(s + *off, &eptr, 0);
  401         if (val < -0x8000 || val > 0xffff || eptr == s + *off)
  402                 return (EINVAL);
  403         *off = eptr - s;
  404         val16 = (int16_t)val;
  405         bcopy(&val16, buf, sizeof(int16_t));
  406         *buflen = sizeof(int16_t);
  407         return (0);
  408 }
  409 
  410 static int
  411 ng_int16_unparse(const struct ng_parse_type *type,
  412         const u_char *data, int *off, char *cbuf, int cbuflen)
  413 {
  414         int16_t val;
  415 
  416         bcopy(data + *off, &val, sizeof(int16_t));
  417         NG_PARSE_APPEND("%d", (int)val);
  418         *off += sizeof(int16_t);
  419         return (0);
  420 }
  421 
  422 static int
  423 ng_int16_getDefault(const struct ng_parse_type *type,
  424         const u_char *const start, u_char *buf, int *buflen)
  425 {
  426         int16_t val;
  427 
  428         if (*buflen < sizeof(int16_t))
  429                 return (ERANGE);
  430         val = 0;
  431         bcopy(&val, buf, sizeof(int16_t));
  432         *buflen = sizeof(int16_t);
  433         return (0);
  434 }
  435 
  436 static int
  437 ng_int16_getAlign(const struct ng_parse_type *type)
  438 {
  439         return INT16_ALIGNMENT;
  440 }
  441 
  442 const struct ng_parse_type ng_parse_int16_type = {
  443         NULL,
  444         NULL,
  445         NULL,
  446         ng_int16_parse,
  447         ng_int16_unparse,
  448         ng_int16_getDefault,
  449         ng_int16_getAlign
  450 };
  451 
  452 /************************************************************************
  453                                 INT32 TYPE
  454  ************************************************************************/
  455 
  456 static int
  457 ng_int32_parse(const struct ng_parse_type *type,
  458         const char *s, int *off, const u_char *const start,
  459         u_char *const buf, int *buflen)
  460 {
  461         long val;                       /* assumes long is at least 32 bits */
  462         int32_t val32;
  463         char *eptr;
  464 
  465         val = strtol(s + *off, &eptr, 0);
  466         if (val < (long)-0x80000000
  467             || val > (u_long)0xffffffff || eptr == s + *off)
  468                 return (EINVAL);
  469         *off = eptr - s;
  470         val32 = (int32_t)val;
  471         bcopy(&val32, buf, sizeof(int32_t));
  472         *buflen = sizeof(int32_t);
  473         return (0);
  474 }
  475 
  476 static int
  477 ng_int32_unparse(const struct ng_parse_type *type,
  478         const u_char *data, int *off, char *cbuf, int cbuflen)
  479 {
  480         int32_t val;
  481 
  482         bcopy(data + *off, &val, sizeof(int32_t));
  483         NG_PARSE_APPEND("%ld", (long)val);
  484         *off += sizeof(int32_t);
  485         return (0);
  486 }
  487 
  488 static int
  489 ng_int32_getDefault(const struct ng_parse_type *type,
  490         const u_char *const start, u_char *buf, int *buflen)
  491 {
  492         int32_t val;
  493 
  494         if (*buflen < sizeof(int32_t))
  495                 return (ERANGE);
  496         val = 0;
  497         bcopy(&val, buf, sizeof(int32_t));
  498         *buflen = sizeof(int32_t);
  499         return (0);
  500 }
  501 
  502 static int
  503 ng_int32_getAlign(const struct ng_parse_type *type)
  504 {
  505         return INT32_ALIGNMENT;
  506 }
  507 
  508 const struct ng_parse_type ng_parse_int32_type = {
  509         NULL,
  510         NULL,
  511         NULL,
  512         ng_int32_parse,
  513         ng_int32_unparse,
  514         ng_int32_getDefault,
  515         ng_int32_getAlign
  516 };
  517 
  518 /************************************************************************
  519                                 INT64 TYPE
  520  ************************************************************************/
  521 
  522 static int
  523 ng_int64_parse(const struct ng_parse_type *type,
  524         const char *s, int *off, const u_char *const start,
  525         u_char *const buf, int *buflen)
  526 {
  527         quad_t val;
  528         int64_t val64;
  529         char *eptr;
  530 
  531         val = strtoq(s + *off, &eptr, 0);
  532         if (eptr == s + *off)
  533                 return (EINVAL);
  534         *off = eptr - s;
  535         val64 = (int64_t)val;
  536         bcopy(&val64, buf, sizeof(int64_t));
  537         *buflen = sizeof(int64_t);
  538         return (0);
  539 }
  540 
  541 static int
  542 ng_int64_unparse(const struct ng_parse_type *type,
  543         const u_char *data, int *off, char *cbuf, int cbuflen)
  544 {
  545         int64_t val;
  546 
  547         bcopy(data + *off, &val, sizeof(int64_t));
  548         NG_PARSE_APPEND("%lld", (long long)val);
  549         *off += sizeof(int64_t);
  550         return (0);
  551 }
  552 
  553 static int
  554 ng_int64_getDefault(const struct ng_parse_type *type,
  555         const u_char *const start, u_char *buf, int *buflen)
  556 {
  557         int64_t val;
  558 
  559         if (*buflen < sizeof(int64_t))
  560                 return (ERANGE);
  561         val = 0;
  562         bcopy(&val, buf, sizeof(int64_t));
  563         *buflen = sizeof(int64_t);
  564         return (0);
  565 }
  566 
  567 static int
  568 ng_int64_getAlign(const struct ng_parse_type *type)
  569 {
  570         return INT64_ALIGNMENT;
  571 }
  572 
  573 const struct ng_parse_type ng_parse_int64_type = {
  574         NULL,
  575         NULL,
  576         NULL,
  577         ng_int64_parse,
  578         ng_int64_unparse,
  579         ng_int64_getDefault,
  580         ng_int64_getAlign
  581 };
  582 
  583 /************************************************************************
  584                                 STRING TYPE
  585  ************************************************************************/
  586 
  587 static int
  588 ng_string_parse(const struct ng_parse_type *type,
  589         const char *s, int *off, const u_char *const start,
  590         u_char *const buf, int *buflen)
  591 {
  592         char *sval;
  593         int len;
  594 
  595         if ((sval = ng_get_string_token(s, off, &len)) == NULL)
  596                 return (EINVAL);
  597         *off += len;
  598         len = strlen(sval) + 1;
  599         bcopy(sval, buf, len);
  600         FREE(sval, M_NETGRAPH);
  601         *buflen = len;
  602         return (0);
  603 }
  604 
  605 static int
  606 ng_string_unparse(const struct ng_parse_type *type,
  607         const u_char *data, int *off, char *cbuf, int cbuflen)
  608 {
  609         const char *const raw = (const char *)data + *off;
  610         char *const s = ng_encode_string(raw);
  611 
  612         if (s == NULL)
  613                 return (ENOMEM);
  614         NG_PARSE_APPEND("%s", s);
  615         *off += strlen(raw) + 1;
  616         FREE(s, M_NETGRAPH);
  617         return (0);
  618 }
  619 
  620 static int
  621 ng_string_getDefault(const struct ng_parse_type *type,
  622         const u_char *const start, u_char *buf, int *buflen)
  623 {
  624 
  625         if (*buflen < 1)
  626                 return (ERANGE);
  627         buf[0] = (u_char)'\0';
  628         *buflen = 1;
  629         return (0);
  630 }
  631 
  632 const struct ng_parse_type ng_parse_string_type = {
  633         NULL,
  634         NULL,
  635         NULL,
  636         ng_string_parse,
  637         ng_string_unparse,
  638         ng_string_getDefault,
  639         NULL
  640 };
  641 
  642 /************************************************************************
  643                         FIXED BUFFER STRING TYPE
  644  ************************************************************************/
  645 
  646 static int
  647 ng_fixedstring_parse(const struct ng_parse_type *type,
  648         const char *s, int *off, const u_char *const start,
  649         u_char *const buf, int *buflen)
  650 {
  651         const struct ng_parse_fixedstring_info *const fi = type->info;
  652         char *sval;
  653         int len;
  654 
  655         if ((sval = ng_get_string_token(s, off, &len)) == NULL)
  656                 return (EINVAL);
  657         if (strlen(sval) + 1 > fi->bufSize)
  658                 return (E2BIG);
  659         *off += len;
  660         len = strlen(sval) + 1;
  661         bcopy(sval, buf, len);
  662         FREE(sval, M_NETGRAPH);
  663         bzero(buf + len, fi->bufSize - len);
  664         *buflen = fi->bufSize;
  665         return (0);
  666 }
  667 
  668 static int
  669 ng_fixedstring_unparse(const struct ng_parse_type *type,
  670         const u_char *data, int *off, char *cbuf, int cbuflen)
  671 {
  672         const struct ng_parse_fixedstring_info *const fi = type->info;
  673         int error, temp = *off;
  674 
  675         if ((error = ng_string_unparse(type, data, &temp, cbuf, cbuflen)) != 0)
  676                 return (error);
  677         *off += fi->bufSize;
  678         return (0);
  679 }
  680 
  681 static int
  682 ng_fixedstring_getDefault(const struct ng_parse_type *type,
  683         const u_char *const start, u_char *buf, int *buflen)
  684 {
  685         const struct ng_parse_fixedstring_info *const fi = type->info;
  686 
  687         if (*buflen < fi->bufSize)
  688                 return (ERANGE);
  689         bzero(buf, fi->bufSize);
  690         *buflen = fi->bufSize;
  691         return (0);
  692 }
  693 
  694 const struct ng_parse_type ng_parse_fixedstring_type = {
  695         NULL,
  696         NULL,
  697         NULL,
  698         ng_fixedstring_parse,
  699         ng_fixedstring_unparse,
  700         ng_fixedstring_getDefault,
  701         NULL
  702 };
  703 
  704 const struct ng_parse_fixedstring_info ng_parse_nodebuf_info = {
  705         NG_NODELEN + 1
  706 };
  707 const struct ng_parse_type ng_parse_nodebuf_type = {
  708         &ng_parse_fixedstring_type,
  709         &ng_parse_nodebuf_info
  710 };
  711 
  712 const struct ng_parse_fixedstring_info ng_parse_hookbuf_info = {
  713         NG_HOOKLEN + 1
  714 };
  715 const struct ng_parse_type ng_parse_hookbuf_type = {
  716         &ng_parse_fixedstring_type,
  717         &ng_parse_hookbuf_info
  718 };
  719 
  720 const struct ng_parse_fixedstring_info ng_parse_pathbuf_info = {
  721         NG_PATHLEN + 1
  722 };
  723 const struct ng_parse_type ng_parse_pathbuf_type = {
  724         &ng_parse_fixedstring_type,
  725         &ng_parse_pathbuf_info
  726 };
  727 
  728 const struct ng_parse_fixedstring_info ng_parse_typebuf_info = {
  729         NG_TYPELEN + 1
  730 };
  731 const struct ng_parse_type ng_parse_typebuf_type = {
  732         &ng_parse_fixedstring_type,
  733         &ng_parse_typebuf_info
  734 };
  735 
  736 const struct ng_parse_fixedstring_info ng_parse_cmdbuf_info = {
  737         NG_CMDSTRLEN + 1
  738 };
  739 const struct ng_parse_type ng_parse_cmdbuf_type = {
  740         &ng_parse_fixedstring_type,
  741         &ng_parse_cmdbuf_info
  742 };
  743 
  744 /************************************************************************
  745                         IP ADDRESS TYPE
  746  ************************************************************************/
  747 
  748 static int
  749 ng_ipaddr_parse(const struct ng_parse_type *type,
  750         const char *s, int *off, const u_char *const start,
  751         u_char *const buf, int *buflen)
  752 {
  753         int i, error;
  754 
  755         for (i = 0; i < 4; i++) {
  756                 if ((error = ng_int8_parse(&ng_parse_int8_type,
  757                     s, off, start, buf + i, buflen)) != 0)
  758                         return (error);
  759                 if (i < 3 && s[*off] != '.')
  760                         return (EINVAL);
  761                 (*off)++;
  762         }
  763         *buflen = 4;
  764         return (0);
  765 }
  766 
  767 static int
  768 ng_ipaddr_unparse(const struct ng_parse_type *type,
  769         const u_char *data, int *off, char *cbuf, int cbuflen)
  770 {
  771         struct in_addr ip;
  772 
  773         bcopy(data + *off, &ip, sizeof(ip));
  774         NG_PARSE_APPEND("%d.%d.%d.%d", ((u_char *)&ip)[0],
  775             ((u_char *)&ip)[1], ((u_char *)&ip)[2], ((u_char *)&ip)[3]);
  776         *off += sizeof(ip);
  777         return (0);
  778 }
  779 
  780 static int
  781 ng_ipaddr_getDefault(const struct ng_parse_type *type,
  782         const u_char *const start, u_char *buf, int *buflen)
  783 {
  784         struct in_addr ip = { 0 };
  785 
  786         if (*buflen < sizeof(ip))
  787                 return (ERANGE);
  788         bcopy(&ip, buf, sizeof(ip));
  789         *buflen = sizeof(ip);
  790         return (0);
  791 }
  792 
  793 const struct ng_parse_type ng_parse_ipaddr_type = {
  794         NULL,
  795         NULL,
  796         NULL,
  797         ng_ipaddr_parse,
  798         ng_ipaddr_unparse,
  799         ng_ipaddr_getDefault,
  800         ng_int32_getAlign
  801 };
  802 
  803 /************************************************************************
  804                         BYTE ARRAY TYPE
  805  ************************************************************************/
  806 
  807 /* Get the length of a byte array */
  808 static int
  809 ng_parse_bytearray_subtype_getLength(const struct ng_parse_type *type,
  810         const u_char *start, const u_char *buf)
  811 {
  812         ng_parse_array_getLength_t *const getLength = type->private;
  813 
  814         return (*getLength)(type, start, buf);
  815 }
  816 
  817 static int
  818 ng_bytearray_elem_unparse(const struct ng_parse_type *type,
  819         const u_char *data, int *off, char *cbuf, int cbuflen)
  820 {
  821         int8_t val;
  822 
  823         bcopy(data + *off, &val, sizeof(int8_t));
  824         NG_PARSE_APPEND("0x%02x", (int)val & 0xff);     /* always hex format */
  825         *off += sizeof(int8_t);
  826         return (0);
  827 }
  828 
  829 /* Byte array element type is int8, but always output in hex format */
  830 const struct ng_parse_type ng_parse_bytearray_elem_type = {
  831         &ng_parse_int8_type,
  832         NULL,
  833         NULL,
  834         NULL,
  835         ng_bytearray_elem_unparse,
  836         NULL,
  837         NULL
  838 };
  839 
  840 static const struct ng_parse_array_info ng_parse_bytearray_subtype_info = {
  841         &ng_parse_bytearray_elem_type,
  842         &ng_parse_bytearray_subtype_getLength,
  843         NULL
  844 };
  845 static const struct ng_parse_type ng_parse_bytearray_subtype = {
  846         &ng_parse_array_type,
  847         &ng_parse_bytearray_subtype_info
  848 };
  849 
  850 static int
  851 ng_bytearray_parse(const struct ng_parse_type *type,
  852         const char *s, int *off, const u_char *const start,
  853         u_char *const buf, int *buflen)
  854 {
  855         char *str;
  856         int toklen;
  857 
  858         /* We accept either an array of bytes or a string constant */
  859         if ((str = ng_get_string_token(s, off, &toklen)) != NULL) {
  860                 ng_parse_array_getLength_t *const getLength = type->info;
  861                 int arraylen, slen;
  862 
  863                 arraylen = (*getLength)(type, start, buf);
  864                 if (arraylen > *buflen) {
  865                         FREE(str, M_NETGRAPH);
  866                         return (ERANGE);
  867                 }
  868                 slen = strlen(str) + 1;
  869                 if (slen > arraylen) {
  870                         FREE(str, M_NETGRAPH);
  871                         return (E2BIG);
  872                 }
  873                 bcopy(str, buf, slen);
  874                 bzero(buf + slen, arraylen - slen);
  875                 FREE(str, M_NETGRAPH);
  876                 *off += toklen;
  877                 *buflen = arraylen;
  878                 return (0);
  879         } else {
  880                 struct ng_parse_type subtype;
  881 
  882                 subtype = ng_parse_bytearray_subtype;
  883                 (const void *)subtype.private = type->info;
  884                 return ng_array_parse(&subtype, s, off, start, buf, buflen);
  885         }
  886 }
  887 
  888 static int
  889 ng_bytearray_unparse(const struct ng_parse_type *type,
  890         const u_char *data, int *off, char *cbuf, int cbuflen)
  891 {
  892         struct ng_parse_type subtype;
  893 
  894         subtype = ng_parse_bytearray_subtype;
  895         (const void *)subtype.private = type->info;
  896         return ng_array_unparse(&subtype, data, off, cbuf, cbuflen);
  897 }
  898 
  899 static int
  900 ng_bytearray_getDefault(const struct ng_parse_type *type,
  901         const u_char *const start, u_char *buf, int *buflen)
  902 {
  903         struct ng_parse_type subtype;
  904 
  905         subtype = ng_parse_bytearray_subtype;
  906         (const void *)subtype.private = type->info;
  907         return ng_array_getDefault(&subtype, start, buf, buflen);
  908 }
  909 
  910 const struct ng_parse_type ng_parse_bytearray_type = {
  911         NULL,
  912         NULL,
  913         NULL,
  914         ng_bytearray_parse,
  915         ng_bytearray_unparse,
  916         ng_bytearray_getDefault,
  917         NULL
  918 };
  919 
  920 /************************************************************************
  921                         STRUCT NG_MESG TYPE
  922  ************************************************************************/
  923 
  924 /* Get msg->header.arglen when "buf" is pointing to msg->data */
  925 static int
  926 ng_parse_ng_mesg_getLength(const struct ng_parse_type *type,
  927         const u_char *start, const u_char *buf)
  928 {
  929         const struct ng_mesg *msg;
  930 
  931         msg = (const struct ng_mesg *)(buf - sizeof(*msg));
  932         return msg->header.arglen;
  933 }
  934 
  935 /* Type for the variable length data portion of a struct ng_mesg */
  936 static const struct ng_parse_type ng_msg_data_type = {
  937         &ng_parse_bytearray_type,
  938         &ng_parse_ng_mesg_getLength
  939 };
  940 
  941 /* Type for the entire struct ng_mesg header with data section */
  942 static const struct ng_parse_struct_info
  943         ng_parse_ng_mesg_type_info = NG_GENERIC_NG_MESG_INFO(&ng_msg_data_type);
  944 const struct ng_parse_type ng_parse_ng_mesg_type = {
  945         &ng_parse_struct_type,
  946         &ng_parse_ng_mesg_type_info,
  947 };
  948 
  949 /************************************************************************
  950                         COMPOSITE HELPER ROUTINES
  951  ************************************************************************/
  952 
  953 /*
  954  * Convert a structure or array from ASCII to binary
  955  */
  956 static int
  957 ng_parse_composite(const struct ng_parse_type *type, const char *s,
  958         int *off, const u_char *const start, u_char *const buf, int *buflen,
  959         const enum comptype ctype)
  960 {
  961         const int num = ng_get_composite_len(type, start, buf, ctype);
  962         int nextIndex = 0;              /* next implicit array index */
  963         u_int index;                    /* field or element index */
  964         int *foff;                      /* field value offsets in string */
  965         int align, len, blen, error = 0;
  966 
  967         /* Initialize */
  968         MALLOC(foff, int *, num * sizeof(*foff), M_NETGRAPH, M_NOWAIT);
  969         if (foff == NULL) {
  970                 error = ENOMEM;
  971                 goto done;
  972         }
  973         bzero(foff, num * sizeof(*foff));
  974 
  975         /* Get opening brace/bracket */
  976         if (ng_parse_get_token(s, off, &len)
  977             != (ctype == CT_STRUCT ? T_LBRACE : T_LBRACKET)) {
  978                 error = EINVAL;
  979                 goto done;
  980         }
  981         *off += len;
  982 
  983         /* Get individual element value positions in the string */
  984         for (;;) {
  985                 enum ng_parse_token tok;
  986 
  987                 /* Check for closing brace/bracket */
  988                 tok = ng_parse_get_token(s, off, &len);
  989                 if (tok == (ctype == CT_STRUCT ? T_RBRACE : T_RBRACKET)) {
  990                         *off += len;
  991                         break;
  992                 }
  993 
  994                 /* For arrays, the 'name' (ie, index) is optional, so
  995                    distinguish name from values by seeing if the next
  996                    token is an equals sign */
  997                 if (ctype != CT_STRUCT) {
  998                         int len2, off2;
  999                         char *eptr;
 1000 
 1001                         /* If an opening brace/bracket, index is implied */
 1002                         if (tok == T_LBRACE || tok == T_LBRACKET) {
 1003                                 index = nextIndex++;
 1004                                 goto gotIndex;
 1005                         }
 1006 
 1007                         /* Might be an index, might be a value, either way... */
 1008                         if (tok != T_WORD) {
 1009                                 error = EINVAL;
 1010                                 goto done;
 1011                         }
 1012 
 1013                         /* If no equals sign follows, index is implied */
 1014                         off2 = *off + len;
 1015                         if (ng_parse_get_token(s, &off2, &len2) != T_EQUALS) {
 1016                                 index = nextIndex++;
 1017                                 goto gotIndex;
 1018                         }
 1019 
 1020                         /* Index was specified explicitly; parse it */
 1021                         index = (u_int)strtoul(s + *off, &eptr, 0);
 1022                         if (index < 0 || eptr - (s + *off) != len) {
 1023                                 error = EINVAL;
 1024                                 goto done;
 1025                         }
 1026                         nextIndex = index + 1;
 1027                         *off += len + len2;
 1028 gotIndex:
 1029                 } else {                        /* a structure field */
 1030                         const struct ng_parse_struct_field *field = NULL;
 1031                         const struct ng_parse_struct_info *si = type->info;
 1032 
 1033                         /* Find the field by name (required) in field list */
 1034                         if (tok != T_WORD) {
 1035                                 error = EINVAL;
 1036                                 goto done;
 1037                         }
 1038                         for (index = 0; index < num; index++) {
 1039                                 field = &si->fields[index];
 1040                                 if (strncmp(&s[*off], field->name, len) == 0
 1041                                     && field->name[len] == '\0')
 1042                                         break;
 1043                         }
 1044                         if (index == num) {
 1045                                 error = ENOENT;
 1046                                 goto done;
 1047                         }
 1048                         *off += len;
 1049 
 1050                         /* Get equals sign */
 1051                         if (ng_parse_get_token(s, off, &len) != T_EQUALS) {
 1052                                 error = EINVAL;
 1053                                 goto done;
 1054                         }
 1055                         *off += len;
 1056                 }
 1057 
 1058                 /* Check array index */
 1059                 if (index >= num) {
 1060                         error = E2BIG;
 1061                         goto done;
 1062                 }
 1063 
 1064                 /* Save value's position and skip over it for now */
 1065                 if (foff[index] != 0) {
 1066                         error = EALREADY;               /* duplicate */
 1067                         goto done;
 1068                 }
 1069                 while (isspace(s[*off]))
 1070                         (*off)++;
 1071                 foff[index] = *off;
 1072                 if ((error = ng_parse_skip_value(s, *off, &len)) != 0)
 1073                         goto done;
 1074                 *off += len;
 1075         }
 1076 
 1077         /* Now build binary structure from supplied values and defaults */
 1078         for (blen = index = 0; index < num; index++) {
 1079                 const struct ng_parse_type *const
 1080                     etype = ng_get_composite_etype(type, index, ctype);
 1081                 int k, pad, vlen;
 1082 
 1083                 /* Zero-pad any alignment bytes */
 1084                 pad = ng_parse_get_elem_pad(type, index, ctype, blen);
 1085                 for (k = 0; k < pad; k++) {
 1086                         if (blen >= *buflen) {
 1087                                 error = ERANGE;
 1088                                 goto done;
 1089                         }
 1090                         buf[blen++] = 0;
 1091                 }
 1092 
 1093                 /* Get value */
 1094                 vlen = *buflen - blen;
 1095                 if (foff[index] == 0) {         /* use default value */
 1096                         error = ng_get_composite_elem_default(type, index,
 1097                             start, buf + blen, &vlen, ctype);
 1098                 } else {                        /* parse given value */
 1099                         *off = foff[index];
 1100                         error = INVOKE(etype, parse)(etype,
 1101                             s, off, start, buf + blen, &vlen);
 1102                 }
 1103                 if (error != 0)
 1104                         goto done;
 1105                 blen += vlen;
 1106         }
 1107 
 1108         /* Make total composite structure size a multiple of its alignment */
 1109         if ((align = ALIGNMENT(type)) != 0) {
 1110                 while (blen % align != 0) {
 1111                         if (blen >= *buflen) {
 1112                                 error = ERANGE;
 1113                                 goto done;
 1114                         }
 1115                         buf[blen++] = 0;
 1116                 }
 1117         }
 1118 
 1119         /* Done */
 1120         *buflen = blen;
 1121 done:
 1122         FREE(foff, M_NETGRAPH);
 1123         return (error);
 1124 }
 1125 
 1126 /*
 1127  * Convert an array or structure from binary to ASCII
 1128  */
 1129 static int
 1130 ng_unparse_composite(const struct ng_parse_type *type, const u_char *data,
 1131         int *off, char *cbuf, int cbuflen, const enum comptype ctype)
 1132 {
 1133         const int num = ng_get_composite_len(type, data, data + *off, ctype);
 1134         int nextIndex = 0, didOne = 0;
 1135         int error, index;
 1136 
 1137         /* Opening brace/bracket */
 1138         NG_PARSE_APPEND("%c", (ctype == CT_STRUCT) ? '{' : '[');
 1139 
 1140         /* Do each item */
 1141         for (index = 0; index < num; index++) {
 1142                 const struct ng_parse_type *const
 1143                     etype = ng_get_composite_etype(type, index, ctype);
 1144                 u_char temp[1024];
 1145 
 1146                 /* Skip any alignment pad bytes */
 1147                 *off += ng_parse_get_elem_pad(type, index, ctype, *off);
 1148 
 1149                 /* See if element is equal to its default value; skip if so */
 1150                 if (*off < sizeof(temp)) {
 1151                         int tempsize = sizeof(temp) - *off;
 1152 
 1153                         bcopy(data, temp, *off);
 1154                         if (ng_get_composite_elem_default(type, index, temp,
 1155                               temp + *off, &tempsize, ctype) == 0
 1156                             && bcmp(temp + *off, data + *off, tempsize) == 0) {
 1157                                 *off += tempsize;
 1158                                 continue;
 1159                         }
 1160                 }
 1161 
 1162                 /* Print name= */
 1163                 NG_PARSE_APPEND(" ");
 1164                 if (ctype != CT_STRUCT) {
 1165                         if (index != nextIndex) {
 1166                                 nextIndex = index;
 1167                                 NG_PARSE_APPEND("%d=", index);
 1168                         }
 1169                         nextIndex++;
 1170                 } else {
 1171                         const struct ng_parse_struct_info *si = type->info;
 1172 
 1173                         NG_PARSE_APPEND("%s=", si->fields[index].name);
 1174                 }
 1175 
 1176                 /* Print value */
 1177                 if ((error = INVOKE(etype, unparse)
 1178                     (etype, data, off, cbuf, cbuflen)) != 0)
 1179                         return (error);
 1180                 cbuflen -= strlen(cbuf);
 1181                 cbuf += strlen(cbuf);
 1182                 didOne = 1;
 1183         }
 1184 
 1185         /* Closing brace/bracket */
 1186         NG_PARSE_APPEND("%s%c",
 1187             didOne ? " " : "", (ctype == CT_STRUCT) ? '}' : ']');
 1188         return (0);
 1189 }
 1190 
 1191 /*
 1192  * Generate the default value for an element of an array or structure
 1193  * Returns EOPNOTSUPP if default value is unspecified.
 1194  */
 1195 static int
 1196 ng_get_composite_elem_default(const struct ng_parse_type *type,
 1197         int index, const u_char *const start, u_char *buf, int *buflen,
 1198         const enum comptype ctype)
 1199 {
 1200         const struct ng_parse_type *etype;
 1201         ng_getDefault_t *func;
 1202 
 1203         switch (ctype) {
 1204         case CT_STRUCT:
 1205                 break;
 1206         case CT_ARRAY:
 1207             {
 1208                 const struct ng_parse_array_info *const ai = type->info;
 1209 
 1210                 if (ai->getDefault != NULL) {
 1211                         return (*ai->getDefault)(type,
 1212                             index, start, buf, buflen);
 1213                 }
 1214                 break;
 1215             }
 1216         case CT_FIXEDARRAY:
 1217             {
 1218                 const struct ng_parse_fixedarray_info *const fi = type->info;
 1219 
 1220                 if (*fi->getDefault != NULL) {
 1221                         return (*fi->getDefault)(type,
 1222                             index, start, buf, buflen);
 1223                 }
 1224                 break;
 1225             }
 1226         default:
 1227             panic("%s", __FUNCTION__);
 1228         }
 1229 
 1230         /* Default to element type default */
 1231         etype = ng_get_composite_etype(type, index, ctype);
 1232         func = METHOD(etype, getDefault);
 1233         if (func == NULL)
 1234                 return (EOPNOTSUPP);
 1235         return (*func)(etype, start, buf, buflen);
 1236 }
 1237 
 1238 /*
 1239  * Get the number of elements in a struct, variable or fixed array.
 1240  */
 1241 static int
 1242 ng_get_composite_len(const struct ng_parse_type *type,
 1243         const u_char *const start, const u_char *buf,
 1244         const enum comptype ctype)
 1245 {
 1246         switch (ctype) {
 1247         case CT_STRUCT:
 1248             {
 1249                 const struct ng_parse_struct_info *const si = type->info;
 1250                 int numFields = 0;
 1251 
 1252                 for (numFields = 0; ; numFields++) {
 1253                         const struct ng_parse_struct_field *const
 1254                                 fi = &si->fields[numFields];
 1255 
 1256                         if (fi->name == NULL)
 1257                                 break;
 1258                 }
 1259                 return (numFields);
 1260             }
 1261         case CT_ARRAY:
 1262             {
 1263                 const struct ng_parse_array_info *const ai = type->info;
 1264 
 1265                 return (*ai->getLength)(type, start, buf);
 1266             }
 1267         case CT_FIXEDARRAY:
 1268             {
 1269                 const struct ng_parse_fixedarray_info *const fi = type->info;
 1270 
 1271                 return fi->length;
 1272             }
 1273         default:
 1274             panic("%s", __FUNCTION__);
 1275         }
 1276         return (0);
 1277 }
 1278 
 1279 /*
 1280  * Return the type of the index'th element of a composite structure
 1281  */
 1282 static const struct ng_parse_type *
 1283 ng_get_composite_etype(const struct ng_parse_type *type,
 1284         int index, const enum comptype ctype)
 1285 {
 1286         const struct ng_parse_type *etype = NULL;
 1287 
 1288         switch (ctype) {
 1289         case CT_STRUCT:
 1290             {
 1291                 const struct ng_parse_struct_info *const si = type->info;
 1292 
 1293                 etype = si->fields[index].type;
 1294                 break;
 1295             }
 1296         case CT_ARRAY:
 1297             {
 1298                 const struct ng_parse_array_info *const ai = type->info;
 1299 
 1300                 etype = ai->elementType;
 1301                 break;
 1302             }
 1303         case CT_FIXEDARRAY:
 1304             {
 1305                 const struct ng_parse_fixedarray_info *const fi = type->info;
 1306 
 1307                 etype = fi->elementType;
 1308                 break;
 1309             }
 1310         default:
 1311             panic("%s", __FUNCTION__);
 1312         }
 1313         return (etype);
 1314 }
 1315 
 1316 /*
 1317  * Get the number of bytes to skip to align for the next
 1318  * element in a composite structure.
 1319  */
 1320 static int
 1321 ng_parse_get_elem_pad(const struct ng_parse_type *type,
 1322         int index, enum comptype ctype, int posn)
 1323 {
 1324         const struct ng_parse_type *const
 1325             etype = ng_get_composite_etype(type, index, ctype);
 1326         int align;
 1327 
 1328         /* Get element's alignment, and possibly override */
 1329         align = ALIGNMENT(etype);
 1330         if (ctype == CT_STRUCT) {
 1331                 const struct ng_parse_struct_info *si = type->info;
 1332 
 1333                 if (si->fields[index].alignment != 0)
 1334                         align = si->fields[index].alignment;
 1335         }
 1336 
 1337         /* Return number of bytes to skip to align */
 1338         return (align ? (align - (posn % align)) % align : 0);
 1339 }
 1340 
 1341 /************************************************************************
 1342                         PARSING HELPER ROUTINES
 1343  ************************************************************************/
 1344 
 1345 /*
 1346  * Skip over a value
 1347  */
 1348 static int
 1349 ng_parse_skip_value(const char *s, int off0, int *lenp)
 1350 {
 1351         int len, nbracket, nbrace;
 1352         int off = off0;
 1353 
 1354         len = nbracket = nbrace = 0;
 1355         do {
 1356                 switch (ng_parse_get_token(s, &off, &len)) {
 1357                 case T_LBRACKET:
 1358                         nbracket++;
 1359                         break;
 1360                 case T_LBRACE:
 1361                         nbrace++;
 1362                         break;
 1363                 case T_RBRACKET:
 1364                         if (nbracket-- == 0)
 1365                                 return (EINVAL);
 1366                         break;
 1367                 case T_RBRACE:
 1368                         if (nbrace-- == 0)
 1369                                 return (EINVAL);
 1370                         break;
 1371                 case T_EOF:
 1372                         return (EINVAL);
 1373                 default:
 1374                         break;
 1375                 }
 1376                 off += len;
 1377         } while (nbracket > 0 || nbrace > 0);
 1378         *lenp = off - off0;
 1379         return (0);
 1380 }
 1381 
 1382 /*
 1383  * Find the next token in the string, starting at offset *startp.
 1384  * Returns the token type, with *startp pointing to the first char
 1385  * and *lenp the length.
 1386  */
 1387 enum ng_parse_token
 1388 ng_parse_get_token(const char *s, int *startp, int *lenp)
 1389 {
 1390         char *t;
 1391         int i;
 1392 
 1393         while (isspace(s[*startp]))
 1394                 (*startp)++;
 1395         switch (s[*startp]) {
 1396         case '\0':
 1397                 *lenp = 0;
 1398                 return T_EOF;
 1399         case '{':
 1400                 *lenp = 1;
 1401                 return T_LBRACE;
 1402         case '}':
 1403                 *lenp = 1;
 1404                 return T_RBRACE;
 1405         case '[':
 1406                 *lenp = 1;
 1407                 return T_LBRACKET;
 1408         case ']':
 1409                 *lenp = 1;
 1410                 return T_RBRACKET;
 1411         case '=':
 1412                 *lenp = 1;
 1413                 return T_EQUALS;
 1414         case '"':
 1415                 if ((t = ng_get_string_token(s, startp, lenp)) == NULL)
 1416                         return T_ERROR;
 1417                 FREE(t, M_NETGRAPH);
 1418                 return T_STRING;
 1419         default:
 1420                 for (i = *startp + 1; s[i] != '\0' && !isspace(s[i])
 1421                     && s[i] != '{' && s[i] != '}' && s[i] != '['
 1422                     && s[i] != ']' && s[i] != '=' && s[i] != '"'; i++)
 1423                         ;
 1424                 *lenp = i - *startp;
 1425                 return T_WORD;
 1426         }
 1427 }
 1428 
 1429 /*
 1430  * Get a string token, which must be enclosed in double quotes.
 1431  * The normal C backslash escapes are recognized.
 1432  */
 1433 char *
 1434 ng_get_string_token(const char *s, int *startp, int *lenp)
 1435 {
 1436         char *cbuf, *p;
 1437         int start, off;
 1438 
 1439         while (isspace(s[*startp]))
 1440                 (*startp)++;
 1441         start = *startp;
 1442         if (s[*startp] != '"')
 1443                 return (NULL);
 1444         MALLOC(cbuf, char *, strlen(s + start), M_NETGRAPH, M_NOWAIT);
 1445         if (cbuf == NULL)
 1446                 return (NULL);
 1447         strcpy(cbuf, s + start + 1);
 1448         for (off = 1, p = cbuf; *p != '\0'; off++, p++) {
 1449                 if (*p == '"') {
 1450                         *p = '\0';
 1451                         *lenp = off + 1;
 1452                         return (cbuf);
 1453                 } else if (p[0] == '\\' && p[1] != '\0') {
 1454                         int x, k;
 1455                         char *v;
 1456 
 1457                         strcpy(p, p + 1);
 1458                         v = p;
 1459                         switch (*p) {
 1460                         case 't':
 1461                                 *v = '\t';
 1462                                 off++;
 1463                                 continue;
 1464                         case 'n':
 1465                                 *v = '\n';
 1466                                 off++;
 1467                                 continue;
 1468                         case 'r':
 1469                                 *v = '\r';
 1470                                 off++;
 1471                                 continue;
 1472                         case 'v':
 1473                                 *v =  '\v';
 1474                                 off++;
 1475                                 continue;
 1476                         case 'f':
 1477                                 *v =  '\f';
 1478                                 off++;
 1479                                 continue;
 1480                         case '"':
 1481                                 *v =  '"';
 1482                                 off++;
 1483                                 continue;
 1484                         case '': case '1': case '2': case '3':
 1485                         case '4': case '5': case '6': case '7':
 1486                                 for (x = k = 0;
 1487                                     k < 3 && *v >= '' && *v <= '7'; v++) {
 1488                                         x = (x << 3) + (*v - '');
 1489                                         off++;
 1490                                 }
 1491                                 *--v = (char)x;
 1492                                 break;
 1493                         case 'x':
 1494                                 for (v++, x = k = 0;
 1495                                     k < 2 && isxdigit(*v); v++) {
 1496                                         x = (x << 4) + (isdigit(*v) ?
 1497                                               (*v - '') :
 1498                                               (tolower(*v) - 'a' + 10));
 1499                                         off++;
 1500                                 }
 1501                                 *--v = (char)x;
 1502                                 break;
 1503                         default:
 1504                                 continue;
 1505                         }
 1506                         strcpy(p, v);
 1507                 }
 1508         }
 1509         return (NULL);          /* no closing quote */
 1510 }
 1511 
 1512 /*
 1513  * Encode a string so it can be safely put in double quotes.
 1514  * Caller must free the result.
 1515  */
 1516 char *
 1517 ng_encode_string(const char *raw)
 1518 {
 1519         char *cbuf;
 1520         int off = 0;
 1521 
 1522         MALLOC(cbuf, char *, strlen(raw) * 4 + 3, M_NETGRAPH, M_NOWAIT);
 1523         if (cbuf == NULL)
 1524                 return (NULL);
 1525         cbuf[off++] = '"';
 1526         for ( ; *raw != '\0'; raw++) {
 1527                 switch (*raw) {
 1528                 case '\t':
 1529                         cbuf[off++] = '\\';
 1530                         cbuf[off++] = 't';
 1531                         break;
 1532                 case '\f':
 1533                         cbuf[off++] = '\\';
 1534                         cbuf[off++] = 'f';
 1535                         break;
 1536                 case '\n':
 1537                         cbuf[off++] = '\\';
 1538                         cbuf[off++] = 'n';
 1539                         break;
 1540                 case '\r':
 1541                         cbuf[off++] = '\\';
 1542                         cbuf[off++] = 'r';
 1543                         break;
 1544                 case '\v':
 1545                         cbuf[off++] = '\\';
 1546                         cbuf[off++] = 'v';
 1547                         break;
 1548                 case '"':
 1549                 case '\\':
 1550                         cbuf[off++] = '\\';
 1551                         cbuf[off++] = *raw;
 1552                         break;
 1553                 default:
 1554                         if (*raw < 0x20 || *raw > 0x7e) {
 1555                                 off += sprintf(cbuf + off,
 1556                                     "\\x%02x", (u_char)*raw);
 1557                                 break;
 1558                         }
 1559                         cbuf[off++] = *raw;
 1560                         break;
 1561                 }
 1562         }
 1563         cbuf[off++] = '"';
 1564         cbuf[off] = '\0';
 1565         return (cbuf);
 1566 }
 1567 
 1568 /************************************************************************
 1569                         VIRTUAL METHOD LOOKUP
 1570  ************************************************************************/
 1571 
 1572 static ng_parse_t *
 1573 ng_get_parse_method(const struct ng_parse_type *t)
 1574 {
 1575         while (t != NULL && t->parse == NULL)
 1576                 t = t->supertype;
 1577         return (t ? t->parse : NULL);
 1578 }
 1579 
 1580 static ng_unparse_t *
 1581 ng_get_unparse_method(const struct ng_parse_type *t)
 1582 {
 1583         while (t != NULL && t->unparse == NULL)
 1584                 t = t->supertype;
 1585         return (t ? t->unparse : NULL);
 1586 }
 1587 
 1588 static ng_getDefault_t *
 1589 ng_get_getDefault_method(const struct ng_parse_type *t)
 1590 {
 1591         while (t != NULL && t->getDefault == NULL)
 1592                 t = t->supertype;
 1593         return (t ? t->getDefault : NULL);
 1594 }
 1595 
 1596 static ng_getAlign_t *
 1597 ng_get_getAlign_method(const struct ng_parse_type *t)
 1598 {
 1599         while (t != NULL && t->getAlign == NULL)
 1600                 t = t->supertype;
 1601         return (t ? t->getAlign : NULL);
 1602 }
 1603 

Cache object: 2dda05c2fc1b51fdf4efd7ba5abab10e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.