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

Cache object: de801c1ad8165a882a7dd0104c6a5983


[ 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.