10147868eSNuno Antunes /*
20147868eSNuno Antunes * ng_parse.c
30147868eSNuno Antunes */
40147868eSNuno Antunes
50147868eSNuno Antunes /*-
60147868eSNuno Antunes * Copyright (c) 1999 Whistle Communications, Inc.
70147868eSNuno Antunes * All rights reserved.
80147868eSNuno Antunes *
90147868eSNuno Antunes * Subject to the following obligations and disclaimer of warranty, use and
100147868eSNuno Antunes * redistribution of this software, in source or object code forms, with or
110147868eSNuno Antunes * without modifications are expressly permitted by Whistle Communications;
120147868eSNuno Antunes * provided, however, that:
130147868eSNuno Antunes * 1. Any and all reproductions of the source or object code must include the
140147868eSNuno Antunes * copyright notice above and the following disclaimer of warranties; and
150147868eSNuno Antunes * 2. No rights are granted, in any manner or form, to use Whistle
160147868eSNuno Antunes * Communications, Inc. trademarks, including the mark "WHISTLE
170147868eSNuno Antunes * COMMUNICATIONS" on advertising, endorsements, or otherwise except as
180147868eSNuno Antunes * such appears in the above copyright notice or in the software.
190147868eSNuno Antunes *
200147868eSNuno Antunes * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
210147868eSNuno Antunes * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
220147868eSNuno Antunes * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
230147868eSNuno Antunes * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
240147868eSNuno Antunes * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
250147868eSNuno Antunes * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
260147868eSNuno Antunes * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
270147868eSNuno Antunes * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
280147868eSNuno Antunes * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
290147868eSNuno Antunes * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
300147868eSNuno Antunes * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
310147868eSNuno Antunes * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
320147868eSNuno Antunes * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
330147868eSNuno Antunes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
340147868eSNuno Antunes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
350147868eSNuno Antunes * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
360147868eSNuno Antunes * OF SUCH DAMAGE.
370147868eSNuno Antunes *
380147868eSNuno Antunes * Author: Archie Cobbs <archie@freebsd.org>
390147868eSNuno Antunes *
400147868eSNuno Antunes * $Whistle: ng_parse.c,v 1.3 1999/11/29 01:43:48 archie Exp $
410147868eSNuno Antunes * $FreeBSD: src/sys/netgraph/ng_parse.c,v 1.30 2007/06/23 00:02:20 mjacob Exp $
420147868eSNuno Antunes */
430147868eSNuno Antunes
440147868eSNuno Antunes #include <sys/types.h>
450147868eSNuno Antunes #include <sys/param.h>
460147868eSNuno Antunes #include <sys/systm.h>
470147868eSNuno Antunes #include <sys/kernel.h>
480147868eSNuno Antunes #include <sys/errno.h>
490147868eSNuno Antunes #include <sys/limits.h>
500147868eSNuno Antunes #include <sys/malloc.h>
510147868eSNuno Antunes #include <sys/mbuf.h>
520147868eSNuno Antunes #include <sys/ctype.h>
53*b90e348bSSascha Wildner #include <sys/stdarg.h>
540147868eSNuno Antunes
550147868eSNuno Antunes #include <net/ethernet.h>
560147868eSNuno Antunes
570147868eSNuno Antunes #include <netinet/in.h>
580147868eSNuno Antunes
590147868eSNuno Antunes #include <netgraph7/ng_message.h>
600147868eSNuno Antunes #include <netgraph7/netgraph.h>
610147868eSNuno Antunes #include <netgraph7/ng_parse.h>
620147868eSNuno Antunes
630147868eSNuno Antunes #ifdef NG_SEPARATE_MALLOC
640147868eSNuno Antunes MALLOC_DEFINE(M_NETGRAPH_PARSE, "netgraph_parse", "netgraph parse info");
650147868eSNuno Antunes #else
660147868eSNuno Antunes #define M_NETGRAPH_PARSE M_NETGRAPH
670147868eSNuno Antunes #endif
680147868eSNuno Antunes
690147868eSNuno Antunes /* Compute alignment for primitive integral types */
700147868eSNuno Antunes struct int16_temp {
710147868eSNuno Antunes char x;
720147868eSNuno Antunes int16_t y;
730147868eSNuno Antunes };
740147868eSNuno Antunes
750147868eSNuno Antunes struct int32_temp {
760147868eSNuno Antunes char x;
770147868eSNuno Antunes int32_t y;
780147868eSNuno Antunes };
790147868eSNuno Antunes
800147868eSNuno Antunes struct int64_temp {
810147868eSNuno Antunes char x;
820147868eSNuno Antunes int64_t y;
830147868eSNuno Antunes };
840147868eSNuno Antunes
850147868eSNuno Antunes #define INT8_ALIGNMENT 1
86858d36ecSSascha Wildner #define INT16_ALIGNMENT __offsetof(struct int16_temp, y)
87858d36ecSSascha Wildner #define INT32_ALIGNMENT __offsetof(struct int32_temp, y)
88858d36ecSSascha Wildner #define INT64_ALIGNMENT __offsetof(struct int64_temp, y)
890147868eSNuno Antunes
900147868eSNuno Antunes /* Output format for integral types */
910147868eSNuno Antunes #define INT_UNSIGNED 0
920147868eSNuno Antunes #define INT_SIGNED 1
930147868eSNuno Antunes #define INT_HEX 2
940147868eSNuno Antunes
950147868eSNuno Antunes /* Type of composite object: struct, array, or fixedarray */
960147868eSNuno Antunes enum comptype {
970147868eSNuno Antunes CT_STRUCT,
980147868eSNuno Antunes CT_ARRAY,
990147868eSNuno Antunes CT_FIXEDARRAY,
1000147868eSNuno Antunes };
1010147868eSNuno Antunes
1020147868eSNuno Antunes /* Composite types helper functions */
1030147868eSNuno Antunes static int ng_parse_composite(const struct ng_parse_type *type,
1040147868eSNuno Antunes const char *s, int *off, const u_char *start,
1050147868eSNuno Antunes u_char *const buf, int *buflen, enum comptype ctype);
1060147868eSNuno Antunes static int ng_unparse_composite(const struct ng_parse_type *type,
1070147868eSNuno Antunes const u_char *data, int *off, char *cbuf, int cbuflen,
1080147868eSNuno Antunes enum comptype ctype);
1090147868eSNuno Antunes static int ng_get_composite_elem_default(const struct ng_parse_type *type,
1100147868eSNuno Antunes int index, const u_char *start, u_char *buf,
1110147868eSNuno Antunes int *buflen, enum comptype ctype);
1120147868eSNuno Antunes static int ng_get_composite_len(const struct ng_parse_type *type,
1130147868eSNuno Antunes const u_char *start, const u_char *buf,
1140147868eSNuno Antunes enum comptype ctype);
1150147868eSNuno Antunes static const struct ng_parse_type *ng_get_composite_etype(const struct
1160147868eSNuno Antunes ng_parse_type *type, int index, enum comptype ctype);
1170147868eSNuno Antunes static int ng_parse_get_elem_pad(const struct ng_parse_type *type,
1180147868eSNuno Antunes int index, enum comptype ctype, int posn);
1190147868eSNuno Antunes
1200147868eSNuno Antunes /* Parsing helper functions */
1210147868eSNuno Antunes static int ng_parse_skip_value(const char *s, int off, int *lenp);
1220147868eSNuno Antunes static int ng_parse_append(char **cbufp, int *cbuflenp,
123902c1039SSascha Wildner const char *fmt, ...) __printflike(3, 4);
1240147868eSNuno Antunes
1250147868eSNuno Antunes /* Poor man's virtual method calls */
1260147868eSNuno Antunes #define METHOD(t,m) (ng_get_ ## m ## _method(t))
1270147868eSNuno Antunes #define INVOKE(t,m) (*METHOD(t,m))
1280147868eSNuno Antunes
1290147868eSNuno Antunes static ng_parse_t *ng_get_parse_method(const struct ng_parse_type *t);
1300147868eSNuno Antunes static ng_unparse_t *ng_get_unparse_method(const struct ng_parse_type *t);
1310147868eSNuno Antunes static ng_getDefault_t *ng_get_getDefault_method(const
1320147868eSNuno Antunes struct ng_parse_type *t);
1330147868eSNuno Antunes static ng_getAlign_t *ng_get_getAlign_method(const struct ng_parse_type *t);
1340147868eSNuno Antunes
1350147868eSNuno Antunes #define ALIGNMENT(t) (METHOD(t, getAlign) == NULL ? \
1360147868eSNuno Antunes 0 : INVOKE(t, getAlign)(t))
1370147868eSNuno Antunes
1380147868eSNuno Antunes /************************************************************************
1390147868eSNuno Antunes PUBLIC FUNCTIONS
1400147868eSNuno Antunes ************************************************************************/
1410147868eSNuno Antunes
1420147868eSNuno Antunes /*
1430147868eSNuno Antunes * Convert an ASCII string to binary according to the supplied type descriptor
1440147868eSNuno Antunes */
1450147868eSNuno Antunes int
ng_parse(const struct ng_parse_type * type,const char * string,int * off,u_char * buf,int * buflen)1460147868eSNuno Antunes ng_parse(const struct ng_parse_type *type,
1470147868eSNuno Antunes const char *string, int *off, u_char *buf, int *buflen)
1480147868eSNuno Antunes {
1490147868eSNuno Antunes return INVOKE(type, parse)(type, string, off, buf, buf, buflen);
1500147868eSNuno Antunes }
1510147868eSNuno Antunes
1520147868eSNuno Antunes /*
1530147868eSNuno Antunes * Convert binary to an ASCII string according to the supplied type descriptor
1540147868eSNuno Antunes */
1550147868eSNuno Antunes int
ng_unparse(const struct ng_parse_type * type,const u_char * data,char * cbuf,int cbuflen)1560147868eSNuno Antunes ng_unparse(const struct ng_parse_type *type,
1570147868eSNuno Antunes const u_char *data, char *cbuf, int cbuflen)
1580147868eSNuno Antunes {
1590147868eSNuno Antunes int off = 0;
1600147868eSNuno Antunes
1610147868eSNuno Antunes return INVOKE(type, unparse)(type, data, &off, cbuf, cbuflen);
1620147868eSNuno Antunes }
1630147868eSNuno Antunes
1640147868eSNuno Antunes /*
1650147868eSNuno Antunes * Fill in the default value according to the supplied type descriptor
1660147868eSNuno Antunes */
1670147868eSNuno Antunes int
ng_parse_getDefault(const struct ng_parse_type * type,u_char * buf,int * buflen)1680147868eSNuno Antunes ng_parse_getDefault(const struct ng_parse_type *type, u_char *buf, int *buflen)
1690147868eSNuno Antunes {
1700147868eSNuno Antunes ng_getDefault_t *const func = METHOD(type, getDefault);
1710147868eSNuno Antunes
1720147868eSNuno Antunes if (func == NULL)
1730147868eSNuno Antunes return (EOPNOTSUPP);
1740147868eSNuno Antunes return (*func)(type, buf, buf, buflen);
1750147868eSNuno Antunes }
1760147868eSNuno Antunes
1770147868eSNuno Antunes
1780147868eSNuno Antunes /************************************************************************
1790147868eSNuno Antunes STRUCTURE TYPE
1800147868eSNuno Antunes ************************************************************************/
1810147868eSNuno Antunes
1820147868eSNuno Antunes static int
ng_struct_parse(const struct ng_parse_type * type,const char * s,int * off,const u_char * const start,u_char * const buf,int * buflen)1830147868eSNuno Antunes ng_struct_parse(const struct ng_parse_type *type,
1840147868eSNuno Antunes const char *s, int *off, const u_char *const start,
1850147868eSNuno Antunes u_char *const buf, int *buflen)
1860147868eSNuno Antunes {
1870147868eSNuno Antunes return ng_parse_composite(type, s, off, start, buf, buflen, CT_STRUCT);
1880147868eSNuno Antunes }
1890147868eSNuno Antunes
1900147868eSNuno Antunes static int
ng_struct_unparse(const struct ng_parse_type * type,const u_char * data,int * off,char * cbuf,int cbuflen)1910147868eSNuno Antunes ng_struct_unparse(const struct ng_parse_type *type,
1920147868eSNuno Antunes const u_char *data, int *off, char *cbuf, int cbuflen)
1930147868eSNuno Antunes {
1940147868eSNuno Antunes return ng_unparse_composite(type, data, off, cbuf, cbuflen, CT_STRUCT);
1950147868eSNuno Antunes }
1960147868eSNuno Antunes
1970147868eSNuno Antunes static int
ng_struct_getDefault(const struct ng_parse_type * type,const u_char * const start,u_char * buf,int * buflen)1980147868eSNuno Antunes ng_struct_getDefault(const struct ng_parse_type *type,
1990147868eSNuno Antunes const u_char *const start, u_char *buf, int *buflen)
2000147868eSNuno Antunes {
2010147868eSNuno Antunes int off = 0;
2020147868eSNuno Antunes
2030147868eSNuno Antunes return ng_parse_composite(type,
2040147868eSNuno Antunes "{}", &off, start, buf, buflen, CT_STRUCT);
2050147868eSNuno Antunes }
2060147868eSNuno Antunes
2070147868eSNuno Antunes static int
ng_struct_getAlign(const struct ng_parse_type * type)2080147868eSNuno Antunes ng_struct_getAlign(const struct ng_parse_type *type)
2090147868eSNuno Antunes {
2100147868eSNuno Antunes const struct ng_parse_struct_field *field;
2110147868eSNuno Antunes int align = 0;
2120147868eSNuno Antunes
2130147868eSNuno Antunes for (field = type->info; field->name != NULL; field++) {
2140147868eSNuno Antunes int falign = ALIGNMENT(field->type);
2150147868eSNuno Antunes
2160147868eSNuno Antunes if (falign > align)
2170147868eSNuno Antunes align = falign;
2180147868eSNuno Antunes }
2190147868eSNuno Antunes return align;
2200147868eSNuno Antunes }
2210147868eSNuno Antunes
2220147868eSNuno Antunes const struct ng_parse_type ng_parse_struct_type = {
2230147868eSNuno Antunes NULL,
2240147868eSNuno Antunes NULL,
2250147868eSNuno Antunes NULL,
2260147868eSNuno Antunes ng_struct_parse,
2270147868eSNuno Antunes ng_struct_unparse,
2280147868eSNuno Antunes ng_struct_getDefault,
2290147868eSNuno Antunes ng_struct_getAlign
2300147868eSNuno Antunes };
2310147868eSNuno Antunes
2320147868eSNuno Antunes /************************************************************************
2330147868eSNuno Antunes FIXED LENGTH ARRAY TYPE
2340147868eSNuno Antunes ************************************************************************/
2350147868eSNuno Antunes
2360147868eSNuno Antunes static int
ng_fixedarray_parse(const struct ng_parse_type * type,const char * s,int * off,const u_char * const start,u_char * const buf,int * buflen)2370147868eSNuno Antunes ng_fixedarray_parse(const struct ng_parse_type *type,
2380147868eSNuno Antunes const char *s, int *off, const u_char *const start,
2390147868eSNuno Antunes u_char *const buf, int *buflen)
2400147868eSNuno Antunes {
2410147868eSNuno Antunes return ng_parse_composite(type,
2420147868eSNuno Antunes s, off, start, buf, buflen, CT_FIXEDARRAY);
2430147868eSNuno Antunes }
2440147868eSNuno Antunes
2450147868eSNuno Antunes static int
ng_fixedarray_unparse(const struct ng_parse_type * type,const u_char * data,int * off,char * cbuf,int cbuflen)2460147868eSNuno Antunes ng_fixedarray_unparse(const struct ng_parse_type *type,
2470147868eSNuno Antunes const u_char *data, int *off, char *cbuf, int cbuflen)
2480147868eSNuno Antunes {
2490147868eSNuno Antunes return ng_unparse_composite(type,
2500147868eSNuno Antunes data, off, cbuf, cbuflen, CT_FIXEDARRAY);
2510147868eSNuno Antunes }
2520147868eSNuno Antunes
2530147868eSNuno Antunes static int
ng_fixedarray_getDefault(const struct ng_parse_type * type,const u_char * const start,u_char * buf,int * buflen)2540147868eSNuno Antunes ng_fixedarray_getDefault(const struct ng_parse_type *type,
2550147868eSNuno Antunes const u_char *const start, u_char *buf, int *buflen)
2560147868eSNuno Antunes {
2570147868eSNuno Antunes int off = 0;
2580147868eSNuno Antunes
2590147868eSNuno Antunes return ng_parse_composite(type,
2600147868eSNuno Antunes "[]", &off, start, buf, buflen, CT_FIXEDARRAY);
2610147868eSNuno Antunes }
2620147868eSNuno Antunes
2630147868eSNuno Antunes static int
ng_fixedarray_getAlign(const struct ng_parse_type * type)2640147868eSNuno Antunes ng_fixedarray_getAlign(const struct ng_parse_type *type)
2650147868eSNuno Antunes {
2660147868eSNuno Antunes const struct ng_parse_fixedarray_info *fi = type->info;
2670147868eSNuno Antunes
2680147868eSNuno Antunes return ALIGNMENT(fi->elementType);
2690147868eSNuno Antunes }
2700147868eSNuno Antunes
2710147868eSNuno Antunes const struct ng_parse_type ng_parse_fixedarray_type = {
2720147868eSNuno Antunes NULL,
2730147868eSNuno Antunes NULL,
2740147868eSNuno Antunes NULL,
2750147868eSNuno Antunes ng_fixedarray_parse,
2760147868eSNuno Antunes ng_fixedarray_unparse,
2770147868eSNuno Antunes ng_fixedarray_getDefault,
2780147868eSNuno Antunes ng_fixedarray_getAlign
2790147868eSNuno Antunes };
2800147868eSNuno Antunes
2810147868eSNuno Antunes /************************************************************************
2820147868eSNuno Antunes VARIABLE LENGTH ARRAY TYPE
2830147868eSNuno Antunes ************************************************************************/
2840147868eSNuno Antunes
2850147868eSNuno Antunes static int
ng_array_parse(const struct ng_parse_type * type,const char * s,int * off,const u_char * const start,u_char * const buf,int * buflen)2860147868eSNuno Antunes ng_array_parse(const struct ng_parse_type *type,
2870147868eSNuno Antunes const char *s, int *off, const u_char *const start,
2880147868eSNuno Antunes u_char *const buf, int *buflen)
2890147868eSNuno Antunes {
2900147868eSNuno Antunes return ng_parse_composite(type, s, off, start, buf, buflen, CT_ARRAY);
2910147868eSNuno Antunes }
2920147868eSNuno Antunes
2930147868eSNuno Antunes static int
ng_array_unparse(const struct ng_parse_type * type,const u_char * data,int * off,char * cbuf,int cbuflen)2940147868eSNuno Antunes ng_array_unparse(const struct ng_parse_type *type,
2950147868eSNuno Antunes const u_char *data, int *off, char *cbuf, int cbuflen)
2960147868eSNuno Antunes {
2970147868eSNuno Antunes return ng_unparse_composite(type, data, off, cbuf, cbuflen, CT_ARRAY);
2980147868eSNuno Antunes }
2990147868eSNuno Antunes
3000147868eSNuno Antunes static int
ng_array_getDefault(const struct ng_parse_type * type,const u_char * const start,u_char * buf,int * buflen)3010147868eSNuno Antunes ng_array_getDefault(const struct ng_parse_type *type,
3020147868eSNuno Antunes const u_char *const start, u_char *buf, int *buflen)
3030147868eSNuno Antunes {
3040147868eSNuno Antunes int off = 0;
3050147868eSNuno Antunes
3060147868eSNuno Antunes return ng_parse_composite(type,
3070147868eSNuno Antunes "[]", &off, start, buf, buflen, CT_ARRAY);
3080147868eSNuno Antunes }
3090147868eSNuno Antunes
3100147868eSNuno Antunes static int
ng_array_getAlign(const struct ng_parse_type * type)3110147868eSNuno Antunes ng_array_getAlign(const struct ng_parse_type *type)
3120147868eSNuno Antunes {
3130147868eSNuno Antunes const struct ng_parse_array_info *ai = type->info;
3140147868eSNuno Antunes
3150147868eSNuno Antunes return ALIGNMENT(ai->elementType);
3160147868eSNuno Antunes }
3170147868eSNuno Antunes
3180147868eSNuno Antunes const struct ng_parse_type ng_parse_array_type = {
3190147868eSNuno Antunes NULL,
3200147868eSNuno Antunes NULL,
3210147868eSNuno Antunes NULL,
3220147868eSNuno Antunes ng_array_parse,
3230147868eSNuno Antunes ng_array_unparse,
3240147868eSNuno Antunes ng_array_getDefault,
3250147868eSNuno Antunes ng_array_getAlign
3260147868eSNuno Antunes };
3270147868eSNuno Antunes
3280147868eSNuno Antunes /************************************************************************
3290147868eSNuno Antunes INT8 TYPE
3300147868eSNuno Antunes ************************************************************************/
3310147868eSNuno Antunes
3320147868eSNuno Antunes static int
ng_int8_parse(const struct ng_parse_type * type,const char * s,int * off,const u_char * const start,u_char * const buf,int * buflen)3330147868eSNuno Antunes ng_int8_parse(const struct ng_parse_type *type,
3340147868eSNuno Antunes const char *s, int *off, const u_char *const start,
3350147868eSNuno Antunes u_char *const buf, int *buflen)
3360147868eSNuno Antunes {
3370147868eSNuno Antunes long val;
3380147868eSNuno Antunes int8_t val8;
3390147868eSNuno Antunes char *eptr;
3400147868eSNuno Antunes
3410147868eSNuno Antunes val = strtol(s + *off, &eptr, 0);
3420147868eSNuno Antunes if (val < (int8_t)0x80 || val > (u_int8_t)0xff || eptr == s + *off)
3430147868eSNuno Antunes return (EINVAL);
3440147868eSNuno Antunes *off = eptr - s;
3450147868eSNuno Antunes val8 = (int8_t)val;
3460147868eSNuno Antunes bcopy(&val8, buf, sizeof(int8_t));
3470147868eSNuno Antunes *buflen = sizeof(int8_t);
3480147868eSNuno Antunes return (0);
3490147868eSNuno Antunes }
3500147868eSNuno Antunes
3510147868eSNuno Antunes static int
ng_int8_unparse(const struct ng_parse_type * type,const u_char * data,int * off,char * cbuf,int cbuflen)3520147868eSNuno Antunes ng_int8_unparse(const struct ng_parse_type *type,
3530147868eSNuno Antunes const u_char *data, int *off, char *cbuf, int cbuflen)
3540147868eSNuno Antunes {
3550147868eSNuno Antunes const char *fmt;
3560147868eSNuno Antunes int fval;
3570147868eSNuno Antunes int error;
3580147868eSNuno Antunes int8_t val;
3590147868eSNuno Antunes
3600147868eSNuno Antunes bcopy(data + *off, &val, sizeof(int8_t));
3610147868eSNuno Antunes switch ((intptr_t)type->info) {
3620147868eSNuno Antunes case INT_SIGNED:
3630147868eSNuno Antunes fmt = "%d";
3640147868eSNuno Antunes fval = val;
3650147868eSNuno Antunes break;
3660147868eSNuno Antunes case INT_UNSIGNED:
3670147868eSNuno Antunes fmt = "%u";
3680147868eSNuno Antunes fval = (u_int8_t)val;
3690147868eSNuno Antunes break;
3700147868eSNuno Antunes case INT_HEX:
3710147868eSNuno Antunes fmt = "0x%x";
3720147868eSNuno Antunes fval = (u_int8_t)val;
3730147868eSNuno Antunes break;
3740147868eSNuno Antunes default:
3750147868eSNuno Antunes panic("%s: unknown type", __func__);
3760147868eSNuno Antunes #ifdef RESTARTABLE_PANICS
3770147868eSNuno Antunes return(0);
3780147868eSNuno Antunes #endif
3790147868eSNuno Antunes }
3800147868eSNuno Antunes if ((error = ng_parse_append(&cbuf, &cbuflen, fmt, fval)) != 0)
3810147868eSNuno Antunes return (error);
3820147868eSNuno Antunes *off += sizeof(int8_t);
3830147868eSNuno Antunes return (0);
3840147868eSNuno Antunes }
3850147868eSNuno Antunes
3860147868eSNuno Antunes static int
ng_int8_getDefault(const struct ng_parse_type * type,const u_char * const start,u_char * buf,int * buflen)3870147868eSNuno Antunes ng_int8_getDefault(const struct ng_parse_type *type,
3880147868eSNuno Antunes const u_char *const start, u_char *buf, int *buflen)
3890147868eSNuno Antunes {
3900147868eSNuno Antunes int8_t val;
3910147868eSNuno Antunes
3920147868eSNuno Antunes if (*buflen < sizeof(int8_t))
3930147868eSNuno Antunes return (ERANGE);
3940147868eSNuno Antunes val = 0;
3950147868eSNuno Antunes bcopy(&val, buf, sizeof(int8_t));
3960147868eSNuno Antunes *buflen = sizeof(int8_t);
3970147868eSNuno Antunes return (0);
3980147868eSNuno Antunes }
3990147868eSNuno Antunes
4000147868eSNuno Antunes static int
ng_int8_getAlign(const struct ng_parse_type * type)4010147868eSNuno Antunes ng_int8_getAlign(const struct ng_parse_type *type)
4020147868eSNuno Antunes {
4030147868eSNuno Antunes return INT8_ALIGNMENT;
4040147868eSNuno Antunes }
4050147868eSNuno Antunes
4060147868eSNuno Antunes const struct ng_parse_type ng_parse_int8_type = {
4070147868eSNuno Antunes NULL,
4080147868eSNuno Antunes (void *)INT_SIGNED,
4090147868eSNuno Antunes NULL,
4100147868eSNuno Antunes ng_int8_parse,
4110147868eSNuno Antunes ng_int8_unparse,
4120147868eSNuno Antunes ng_int8_getDefault,
4130147868eSNuno Antunes ng_int8_getAlign
4140147868eSNuno Antunes };
4150147868eSNuno Antunes
4160147868eSNuno Antunes const struct ng_parse_type ng_parse_uint8_type = {
4170147868eSNuno Antunes &ng_parse_int8_type,
4180147868eSNuno Antunes (void *)INT_UNSIGNED
4190147868eSNuno Antunes };
4200147868eSNuno Antunes
4210147868eSNuno Antunes const struct ng_parse_type ng_parse_hint8_type = {
4220147868eSNuno Antunes &ng_parse_int8_type,
4230147868eSNuno Antunes (void *)INT_HEX
4240147868eSNuno Antunes };
4250147868eSNuno Antunes
4260147868eSNuno Antunes /************************************************************************
4270147868eSNuno Antunes INT16 TYPE
4280147868eSNuno Antunes ************************************************************************/
4290147868eSNuno Antunes
4300147868eSNuno Antunes static int
ng_int16_parse(const struct ng_parse_type * type,const char * s,int * off,const u_char * const start,u_char * const buf,int * buflen)4310147868eSNuno Antunes ng_int16_parse(const struct ng_parse_type *type,
4320147868eSNuno Antunes const char *s, int *off, const u_char *const start,
4330147868eSNuno Antunes u_char *const buf, int *buflen)
4340147868eSNuno Antunes {
4350147868eSNuno Antunes long val;
4360147868eSNuno Antunes int16_t val16;
4370147868eSNuno Antunes char *eptr;
4380147868eSNuno Antunes
4390147868eSNuno Antunes val = strtol(s + *off, &eptr, 0);
4400147868eSNuno Antunes if (val < (int16_t)0x8000
4410147868eSNuno Antunes || val > (u_int16_t)0xffff || eptr == s + *off)
4420147868eSNuno Antunes return (EINVAL);
4430147868eSNuno Antunes *off = eptr - s;
4440147868eSNuno Antunes val16 = (int16_t)val;
4450147868eSNuno Antunes bcopy(&val16, buf, sizeof(int16_t));
4460147868eSNuno Antunes *buflen = sizeof(int16_t);
4470147868eSNuno Antunes return (0);
4480147868eSNuno Antunes }
4490147868eSNuno Antunes
4500147868eSNuno Antunes static int
ng_int16_unparse(const struct ng_parse_type * type,const u_char * data,int * off,char * cbuf,int cbuflen)4510147868eSNuno Antunes ng_int16_unparse(const struct ng_parse_type *type,
4520147868eSNuno Antunes const u_char *data, int *off, char *cbuf, int cbuflen)
4530147868eSNuno Antunes {
4540147868eSNuno Antunes const char *fmt;
4550147868eSNuno Antunes int fval;
4560147868eSNuno Antunes int error;
4570147868eSNuno Antunes int16_t val;
4580147868eSNuno Antunes
4590147868eSNuno Antunes bcopy(data + *off, &val, sizeof(int16_t));
4600147868eSNuno Antunes switch ((intptr_t)type->info) {
4610147868eSNuno Antunes case INT_SIGNED:
4620147868eSNuno Antunes fmt = "%d";
4630147868eSNuno Antunes fval = val;
4640147868eSNuno Antunes break;
4650147868eSNuno Antunes case INT_UNSIGNED:
4660147868eSNuno Antunes fmt = "%u";
4670147868eSNuno Antunes fval = (u_int16_t)val;
4680147868eSNuno Antunes break;
4690147868eSNuno Antunes case INT_HEX:
4700147868eSNuno Antunes fmt = "0x%x";
4710147868eSNuno Antunes fval = (u_int16_t)val;
4720147868eSNuno Antunes break;
4730147868eSNuno Antunes default:
4740147868eSNuno Antunes panic("%s: unknown type", __func__);
4750147868eSNuno Antunes #ifdef RESTARTABLE_PANICS
4760147868eSNuno Antunes return(0);
4770147868eSNuno Antunes #endif
4780147868eSNuno Antunes }
4790147868eSNuno Antunes if ((error = ng_parse_append(&cbuf, &cbuflen, fmt, fval)) != 0)
4800147868eSNuno Antunes return (error);
4810147868eSNuno Antunes *off += sizeof(int16_t);
4820147868eSNuno Antunes return (0);
4830147868eSNuno Antunes }
4840147868eSNuno Antunes
4850147868eSNuno Antunes static int
ng_int16_getDefault(const struct ng_parse_type * type,const u_char * const start,u_char * buf,int * buflen)4860147868eSNuno Antunes ng_int16_getDefault(const struct ng_parse_type *type,
4870147868eSNuno Antunes const u_char *const start, u_char *buf, int *buflen)
4880147868eSNuno Antunes {
4890147868eSNuno Antunes int16_t val;
4900147868eSNuno Antunes
4910147868eSNuno Antunes if (*buflen < sizeof(int16_t))
4920147868eSNuno Antunes return (ERANGE);
4930147868eSNuno Antunes val = 0;
4940147868eSNuno Antunes bcopy(&val, buf, sizeof(int16_t));
4950147868eSNuno Antunes *buflen = sizeof(int16_t);
4960147868eSNuno Antunes return (0);
4970147868eSNuno Antunes }
4980147868eSNuno Antunes
4990147868eSNuno Antunes static int
ng_int16_getAlign(const struct ng_parse_type * type)5000147868eSNuno Antunes ng_int16_getAlign(const struct ng_parse_type *type)
5010147868eSNuno Antunes {
5020147868eSNuno Antunes return INT16_ALIGNMENT;
5030147868eSNuno Antunes }
5040147868eSNuno Antunes
5050147868eSNuno Antunes const struct ng_parse_type ng_parse_int16_type = {
5060147868eSNuno Antunes NULL,
5070147868eSNuno Antunes (void *)INT_SIGNED,
5080147868eSNuno Antunes NULL,
5090147868eSNuno Antunes ng_int16_parse,
5100147868eSNuno Antunes ng_int16_unparse,
5110147868eSNuno Antunes ng_int16_getDefault,
5120147868eSNuno Antunes ng_int16_getAlign
5130147868eSNuno Antunes };
5140147868eSNuno Antunes
5150147868eSNuno Antunes const struct ng_parse_type ng_parse_uint16_type = {
5160147868eSNuno Antunes &ng_parse_int16_type,
5170147868eSNuno Antunes (void *)INT_UNSIGNED
5180147868eSNuno Antunes };
5190147868eSNuno Antunes
5200147868eSNuno Antunes const struct ng_parse_type ng_parse_hint16_type = {
5210147868eSNuno Antunes &ng_parse_int16_type,
5220147868eSNuno Antunes (void *)INT_HEX
5230147868eSNuno Antunes };
5240147868eSNuno Antunes
5250147868eSNuno Antunes /************************************************************************
5260147868eSNuno Antunes INT32 TYPE
5270147868eSNuno Antunes ************************************************************************/
5280147868eSNuno Antunes
5290147868eSNuno Antunes static int
ng_int32_parse(const struct ng_parse_type * type,const char * s,int * off,const u_char * const start,u_char * const buf,int * buflen)5300147868eSNuno Antunes ng_int32_parse(const struct ng_parse_type *type,
5310147868eSNuno Antunes const char *s, int *off, const u_char *const start,
5320147868eSNuno Antunes u_char *const buf, int *buflen)
5330147868eSNuno Antunes {
5340147868eSNuno Antunes long val; /* assumes long is at least 32 bits */
5350147868eSNuno Antunes int32_t val32;
5360147868eSNuno Antunes char *eptr;
5370147868eSNuno Antunes
5380147868eSNuno Antunes if ((intptr_t)type->info == INT_SIGNED)
5390147868eSNuno Antunes val = strtol(s + *off, &eptr, 0);
5400147868eSNuno Antunes else
5410147868eSNuno Antunes val = strtoul(s + *off, &eptr, 0);
5420147868eSNuno Antunes if (val < (int32_t)0x80000000
5430147868eSNuno Antunes || val > (u_int32_t)0xffffffff || eptr == s + *off)
5440147868eSNuno Antunes return (EINVAL);
5450147868eSNuno Antunes *off = eptr - s;
5460147868eSNuno Antunes val32 = (int32_t)val;
5470147868eSNuno Antunes bcopy(&val32, buf, sizeof(int32_t));
5480147868eSNuno Antunes *buflen = sizeof(int32_t);
5490147868eSNuno Antunes return (0);
5500147868eSNuno Antunes }
5510147868eSNuno Antunes
5520147868eSNuno Antunes static int
ng_int32_unparse(const struct ng_parse_type * type,const u_char * data,int * off,char * cbuf,int cbuflen)5530147868eSNuno Antunes ng_int32_unparse(const struct ng_parse_type *type,
5540147868eSNuno Antunes const u_char *data, int *off, char *cbuf, int cbuflen)
5550147868eSNuno Antunes {
5560147868eSNuno Antunes const char *fmt;
5570147868eSNuno Antunes long fval;
5580147868eSNuno Antunes int error;
5590147868eSNuno Antunes int32_t val;
5600147868eSNuno Antunes
5610147868eSNuno Antunes bcopy(data + *off, &val, sizeof(int32_t));
5620147868eSNuno Antunes switch ((intptr_t)type->info) {
5630147868eSNuno Antunes case INT_SIGNED:
5640147868eSNuno Antunes fmt = "%ld";
5650147868eSNuno Antunes fval = val;
5660147868eSNuno Antunes break;
5670147868eSNuno Antunes case INT_UNSIGNED:
5680147868eSNuno Antunes fmt = "%lu";
5690147868eSNuno Antunes fval = (u_int32_t)val;
5700147868eSNuno Antunes break;
5710147868eSNuno Antunes case INT_HEX:
5720147868eSNuno Antunes fmt = "0x%lx";
5730147868eSNuno Antunes fval = (u_int32_t)val;
5740147868eSNuno Antunes break;
5750147868eSNuno Antunes default:
5760147868eSNuno Antunes panic("%s: unknown type", __func__);
5770147868eSNuno Antunes #ifdef RESTARTABLE_PANICS
5780147868eSNuno Antunes return(0);
5790147868eSNuno Antunes #endif
5800147868eSNuno Antunes }
5810147868eSNuno Antunes if ((error = ng_parse_append(&cbuf, &cbuflen, fmt, fval)) != 0)
5820147868eSNuno Antunes return (error);
5830147868eSNuno Antunes *off += sizeof(int32_t);
5840147868eSNuno Antunes return (0);
5850147868eSNuno Antunes }
5860147868eSNuno Antunes
5870147868eSNuno Antunes static int
ng_int32_getDefault(const struct ng_parse_type * type,const u_char * const start,u_char * buf,int * buflen)5880147868eSNuno Antunes ng_int32_getDefault(const struct ng_parse_type *type,
5890147868eSNuno Antunes const u_char *const start, u_char *buf, int *buflen)
5900147868eSNuno Antunes {
5910147868eSNuno Antunes int32_t val;
5920147868eSNuno Antunes
5930147868eSNuno Antunes if (*buflen < sizeof(int32_t))
5940147868eSNuno Antunes return (ERANGE);
5950147868eSNuno Antunes val = 0;
5960147868eSNuno Antunes bcopy(&val, buf, sizeof(int32_t));
5970147868eSNuno Antunes *buflen = sizeof(int32_t);
5980147868eSNuno Antunes return (0);
5990147868eSNuno Antunes }
6000147868eSNuno Antunes
6010147868eSNuno Antunes static int
ng_int32_getAlign(const struct ng_parse_type * type)6020147868eSNuno Antunes ng_int32_getAlign(const struct ng_parse_type *type)
6030147868eSNuno Antunes {
6040147868eSNuno Antunes return INT32_ALIGNMENT;
6050147868eSNuno Antunes }
6060147868eSNuno Antunes
6070147868eSNuno Antunes const struct ng_parse_type ng_parse_int32_type = {
6080147868eSNuno Antunes NULL,
6090147868eSNuno Antunes (void *)INT_SIGNED,
6100147868eSNuno Antunes NULL,
6110147868eSNuno Antunes ng_int32_parse,
6120147868eSNuno Antunes ng_int32_unparse,
6130147868eSNuno Antunes ng_int32_getDefault,
6140147868eSNuno Antunes ng_int32_getAlign
6150147868eSNuno Antunes };
6160147868eSNuno Antunes
6170147868eSNuno Antunes const struct ng_parse_type ng_parse_uint32_type = {
6180147868eSNuno Antunes &ng_parse_int32_type,
6190147868eSNuno Antunes (void *)INT_UNSIGNED
6200147868eSNuno Antunes };
6210147868eSNuno Antunes
6220147868eSNuno Antunes const struct ng_parse_type ng_parse_hint32_type = {
6230147868eSNuno Antunes &ng_parse_int32_type,
6240147868eSNuno Antunes (void *)INT_HEX
6250147868eSNuno Antunes };
6260147868eSNuno Antunes
6270147868eSNuno Antunes /************************************************************************
6280147868eSNuno Antunes INT64 TYPE
6290147868eSNuno Antunes ************************************************************************/
6300147868eSNuno Antunes
6310147868eSNuno Antunes static int
ng_int64_parse(const struct ng_parse_type * type,const char * s,int * off,const u_char * const start,u_char * const buf,int * buflen)6320147868eSNuno Antunes ng_int64_parse(const struct ng_parse_type *type,
6330147868eSNuno Antunes const char *s, int *off, const u_char *const start,
6340147868eSNuno Antunes u_char *const buf, int *buflen)
6350147868eSNuno Antunes {
6360147868eSNuno Antunes quad_t val;
6370147868eSNuno Antunes int64_t val64;
6380147868eSNuno Antunes char *eptr;
6390147868eSNuno Antunes
6400147868eSNuno Antunes val = strtoq(s + *off, &eptr, 0);
6410147868eSNuno Antunes if (eptr == s + *off)
6420147868eSNuno Antunes return (EINVAL);
6430147868eSNuno Antunes *off = eptr - s;
6440147868eSNuno Antunes val64 = (int64_t)val;
6450147868eSNuno Antunes bcopy(&val64, buf, sizeof(int64_t));
6460147868eSNuno Antunes *buflen = sizeof(int64_t);
6470147868eSNuno Antunes return (0);
6480147868eSNuno Antunes }
6490147868eSNuno Antunes
6500147868eSNuno Antunes static int
ng_int64_unparse(const struct ng_parse_type * type,const u_char * data,int * off,char * cbuf,int cbuflen)6510147868eSNuno Antunes ng_int64_unparse(const struct ng_parse_type *type,
6520147868eSNuno Antunes const u_char *data, int *off, char *cbuf, int cbuflen)
6530147868eSNuno Antunes {
6540147868eSNuno Antunes const char *fmt;
6550147868eSNuno Antunes long long fval;
6560147868eSNuno Antunes int64_t val;
6570147868eSNuno Antunes int error;
6580147868eSNuno Antunes
6590147868eSNuno Antunes bcopy(data + *off, &val, sizeof(int64_t));
6600147868eSNuno Antunes switch ((intptr_t)type->info) {
6610147868eSNuno Antunes case INT_SIGNED:
6620147868eSNuno Antunes fmt = "%lld";
6630147868eSNuno Antunes fval = val;
6640147868eSNuno Antunes break;
6650147868eSNuno Antunes case INT_UNSIGNED:
6660147868eSNuno Antunes fmt = "%llu";
6670147868eSNuno Antunes fval = (u_int64_t)val;
6680147868eSNuno Antunes break;
6690147868eSNuno Antunes case INT_HEX:
6700147868eSNuno Antunes fmt = "0x%llx";
6710147868eSNuno Antunes fval = (u_int64_t)val;
6720147868eSNuno Antunes break;
6730147868eSNuno Antunes default:
6740147868eSNuno Antunes panic("%s: unknown type", __func__);
6750147868eSNuno Antunes #ifdef RESTARTABLE_PANICS
6760147868eSNuno Antunes return(0);
6770147868eSNuno Antunes #endif
6780147868eSNuno Antunes }
6790147868eSNuno Antunes if ((error = ng_parse_append(&cbuf, &cbuflen, fmt, fval)) != 0)
6800147868eSNuno Antunes return (error);
6810147868eSNuno Antunes *off += sizeof(int64_t);
6820147868eSNuno Antunes return (0);
6830147868eSNuno Antunes }
6840147868eSNuno Antunes
6850147868eSNuno Antunes static int
ng_int64_getDefault(const struct ng_parse_type * type,const u_char * const start,u_char * buf,int * buflen)6860147868eSNuno Antunes ng_int64_getDefault(const struct ng_parse_type *type,
6870147868eSNuno Antunes const u_char *const start, u_char *buf, int *buflen)
6880147868eSNuno Antunes {
6890147868eSNuno Antunes int64_t val;
6900147868eSNuno Antunes
6910147868eSNuno Antunes if (*buflen < sizeof(int64_t))
6920147868eSNuno Antunes return (ERANGE);
6930147868eSNuno Antunes val = 0;
6940147868eSNuno Antunes bcopy(&val, buf, sizeof(int64_t));
6950147868eSNuno Antunes *buflen = sizeof(int64_t);
6960147868eSNuno Antunes return (0);
6970147868eSNuno Antunes }
6980147868eSNuno Antunes
6990147868eSNuno Antunes static int
ng_int64_getAlign(const struct ng_parse_type * type)7000147868eSNuno Antunes ng_int64_getAlign(const struct ng_parse_type *type)
7010147868eSNuno Antunes {
7020147868eSNuno Antunes return INT64_ALIGNMENT;
7030147868eSNuno Antunes }
7040147868eSNuno Antunes
7050147868eSNuno Antunes const struct ng_parse_type ng_parse_int64_type = {
7060147868eSNuno Antunes NULL,
7070147868eSNuno Antunes (void *)INT_SIGNED,
7080147868eSNuno Antunes NULL,
7090147868eSNuno Antunes ng_int64_parse,
7100147868eSNuno Antunes ng_int64_unparse,
7110147868eSNuno Antunes ng_int64_getDefault,
7120147868eSNuno Antunes ng_int64_getAlign
7130147868eSNuno Antunes };
7140147868eSNuno Antunes
7150147868eSNuno Antunes const struct ng_parse_type ng_parse_uint64_type = {
7160147868eSNuno Antunes &ng_parse_int64_type,
7170147868eSNuno Antunes (void *)INT_UNSIGNED
7180147868eSNuno Antunes };
7190147868eSNuno Antunes
7200147868eSNuno Antunes const struct ng_parse_type ng_parse_hint64_type = {
7210147868eSNuno Antunes &ng_parse_int64_type,
7220147868eSNuno Antunes (void *)INT_HEX
7230147868eSNuno Antunes };
7240147868eSNuno Antunes
7250147868eSNuno Antunes /************************************************************************
7260147868eSNuno Antunes STRING TYPE
7270147868eSNuno Antunes ************************************************************************/
7280147868eSNuno Antunes
7290147868eSNuno Antunes static int
ng_string_parse(const struct ng_parse_type * type,const char * s,int * off,const u_char * const start,u_char * const buf,int * buflen)7300147868eSNuno Antunes ng_string_parse(const struct ng_parse_type *type,
7310147868eSNuno Antunes const char *s, int *off, const u_char *const start,
7320147868eSNuno Antunes u_char *const buf, int *buflen)
7330147868eSNuno Antunes {
7340147868eSNuno Antunes char *sval;
7350147868eSNuno Antunes int len;
7360147868eSNuno Antunes int slen;
7370147868eSNuno Antunes
7380147868eSNuno Antunes if ((sval = ng_get_string_token(s, off, &len, &slen)) == NULL)
7390147868eSNuno Antunes return (EINVAL);
7400147868eSNuno Antunes *off += len;
7410147868eSNuno Antunes bcopy(sval, buf, slen + 1);
7420147868eSNuno Antunes kfree(sval, M_NETGRAPH_PARSE);
7430147868eSNuno Antunes *buflen = slen + 1;
7440147868eSNuno Antunes return (0);
7450147868eSNuno Antunes }
7460147868eSNuno Antunes
7470147868eSNuno Antunes static int
ng_string_unparse(const struct ng_parse_type * type,const u_char * data,int * off,char * cbuf,int cbuflen)7480147868eSNuno Antunes ng_string_unparse(const struct ng_parse_type *type,
7490147868eSNuno Antunes const u_char *data, int *off, char *cbuf, int cbuflen)
7500147868eSNuno Antunes {
7510147868eSNuno Antunes const char *const raw = (const char *)data + *off;
7520147868eSNuno Antunes char *const s = ng_encode_string(raw, strlen(raw));
7530147868eSNuno Antunes int error;
7540147868eSNuno Antunes
7550147868eSNuno Antunes if (s == NULL)
7560147868eSNuno Antunes return (ENOMEM);
7570147868eSNuno Antunes if ((error = ng_parse_append(&cbuf, &cbuflen, "%s", s)) != 0) {
7580147868eSNuno Antunes kfree(s, M_NETGRAPH_PARSE);
7590147868eSNuno Antunes return (error);
7600147868eSNuno Antunes }
7610147868eSNuno Antunes *off += strlen(raw) + 1;
7620147868eSNuno Antunes kfree(s, M_NETGRAPH_PARSE);
7630147868eSNuno Antunes return (0);
7640147868eSNuno Antunes }
7650147868eSNuno Antunes
7660147868eSNuno Antunes static int
ng_string_getDefault(const struct ng_parse_type * type,const u_char * const start,u_char * buf,int * buflen)7670147868eSNuno Antunes ng_string_getDefault(const struct ng_parse_type *type,
7680147868eSNuno Antunes const u_char *const start, u_char *buf, int *buflen)
7690147868eSNuno Antunes {
7700147868eSNuno Antunes
7710147868eSNuno Antunes if (*buflen < 1)
7720147868eSNuno Antunes return (ERANGE);
7730147868eSNuno Antunes buf[0] = (u_char)'\0';
7740147868eSNuno Antunes *buflen = 1;
7750147868eSNuno Antunes return (0);
7760147868eSNuno Antunes }
7770147868eSNuno Antunes
7780147868eSNuno Antunes const struct ng_parse_type ng_parse_string_type = {
7790147868eSNuno Antunes NULL,
7800147868eSNuno Antunes NULL,
7810147868eSNuno Antunes NULL,
7820147868eSNuno Antunes ng_string_parse,
7830147868eSNuno Antunes ng_string_unparse,
7840147868eSNuno Antunes ng_string_getDefault,
7850147868eSNuno Antunes NULL
7860147868eSNuno Antunes };
7870147868eSNuno Antunes
7880147868eSNuno Antunes /************************************************************************
7890147868eSNuno Antunes FIXED BUFFER STRING TYPE
7900147868eSNuno Antunes ************************************************************************/
7910147868eSNuno Antunes
7920147868eSNuno Antunes static int
ng_fixedstring_parse(const struct ng_parse_type * type,const char * s,int * off,const u_char * const start,u_char * const buf,int * buflen)7930147868eSNuno Antunes ng_fixedstring_parse(const struct ng_parse_type *type,
7940147868eSNuno Antunes const char *s, int *off, const u_char *const start,
7950147868eSNuno Antunes u_char *const buf, int *buflen)
7960147868eSNuno Antunes {
7970147868eSNuno Antunes const struct ng_parse_fixedstring_info *const fi = type->info;
7980147868eSNuno Antunes char *sval;
7990147868eSNuno Antunes int len;
8000147868eSNuno Antunes int slen;
8010147868eSNuno Antunes
8020147868eSNuno Antunes if ((sval = ng_get_string_token(s, off, &len, &slen)) == NULL)
8030147868eSNuno Antunes return (EINVAL);
8040147868eSNuno Antunes if (slen + 1 > fi->bufSize) {
8050147868eSNuno Antunes kfree(sval, M_NETGRAPH_PARSE);
8060147868eSNuno Antunes return (E2BIG);
8070147868eSNuno Antunes }
8080147868eSNuno Antunes *off += len;
8090147868eSNuno Antunes bcopy(sval, buf, slen);
8100147868eSNuno Antunes kfree(sval, M_NETGRAPH_PARSE);
8110147868eSNuno Antunes bzero(buf + slen, fi->bufSize - slen);
8120147868eSNuno Antunes *buflen = fi->bufSize;
8130147868eSNuno Antunes return (0);
8140147868eSNuno Antunes }
8150147868eSNuno Antunes
8160147868eSNuno Antunes static int
ng_fixedstring_unparse(const struct ng_parse_type * type,const u_char * data,int * off,char * cbuf,int cbuflen)8170147868eSNuno Antunes ng_fixedstring_unparse(const struct ng_parse_type *type,
8180147868eSNuno Antunes const u_char *data, int *off, char *cbuf, int cbuflen)
8190147868eSNuno Antunes {
8200147868eSNuno Antunes const struct ng_parse_fixedstring_info *const fi = type->info;
8210147868eSNuno Antunes int error, temp = *off;
8220147868eSNuno Antunes
8230147868eSNuno Antunes if ((error = ng_string_unparse(type, data, &temp, cbuf, cbuflen)) != 0)
8240147868eSNuno Antunes return (error);
8250147868eSNuno Antunes *off += fi->bufSize;
8260147868eSNuno Antunes return (0);
8270147868eSNuno Antunes }
8280147868eSNuno Antunes
8290147868eSNuno Antunes static int
ng_fixedstring_getDefault(const struct ng_parse_type * type,const u_char * const start,u_char * buf,int * buflen)8300147868eSNuno Antunes ng_fixedstring_getDefault(const struct ng_parse_type *type,
8310147868eSNuno Antunes const u_char *const start, u_char *buf, int *buflen)
8320147868eSNuno Antunes {
8330147868eSNuno Antunes const struct ng_parse_fixedstring_info *const fi = type->info;
8340147868eSNuno Antunes
8350147868eSNuno Antunes if (*buflen < fi->bufSize)
8360147868eSNuno Antunes return (ERANGE);
8370147868eSNuno Antunes bzero(buf, fi->bufSize);
8380147868eSNuno Antunes *buflen = fi->bufSize;
8390147868eSNuno Antunes return (0);
8400147868eSNuno Antunes }
8410147868eSNuno Antunes
8420147868eSNuno Antunes const struct ng_parse_type ng_parse_fixedstring_type = {
8430147868eSNuno Antunes NULL,
8440147868eSNuno Antunes NULL,
8450147868eSNuno Antunes NULL,
8460147868eSNuno Antunes ng_fixedstring_parse,
8470147868eSNuno Antunes ng_fixedstring_unparse,
8480147868eSNuno Antunes ng_fixedstring_getDefault,
8490147868eSNuno Antunes NULL
8500147868eSNuno Antunes };
8510147868eSNuno Antunes
8520147868eSNuno Antunes const struct ng_parse_fixedstring_info ng_parse_nodebuf_info = {
8530147868eSNuno Antunes NG_NODESIZ
8540147868eSNuno Antunes };
8550147868eSNuno Antunes const struct ng_parse_type ng_parse_nodebuf_type = {
8560147868eSNuno Antunes &ng_parse_fixedstring_type,
8570147868eSNuno Antunes &ng_parse_nodebuf_info
8580147868eSNuno Antunes };
8590147868eSNuno Antunes
8600147868eSNuno Antunes const struct ng_parse_fixedstring_info ng_parse_hookbuf_info = {
8610147868eSNuno Antunes NG_HOOKSIZ
8620147868eSNuno Antunes };
8630147868eSNuno Antunes const struct ng_parse_type ng_parse_hookbuf_type = {
8640147868eSNuno Antunes &ng_parse_fixedstring_type,
8650147868eSNuno Antunes &ng_parse_hookbuf_info
8660147868eSNuno Antunes };
8670147868eSNuno Antunes
8680147868eSNuno Antunes const struct ng_parse_fixedstring_info ng_parse_pathbuf_info = {
8690147868eSNuno Antunes NG_PATHSIZ
8700147868eSNuno Antunes };
8710147868eSNuno Antunes const struct ng_parse_type ng_parse_pathbuf_type = {
8720147868eSNuno Antunes &ng_parse_fixedstring_type,
8730147868eSNuno Antunes &ng_parse_pathbuf_info
8740147868eSNuno Antunes };
8750147868eSNuno Antunes
8760147868eSNuno Antunes const struct ng_parse_fixedstring_info ng_parse_typebuf_info = {
8770147868eSNuno Antunes NG_TYPESIZ
8780147868eSNuno Antunes };
8790147868eSNuno Antunes const struct ng_parse_type ng_parse_typebuf_type = {
8800147868eSNuno Antunes &ng_parse_fixedstring_type,
8810147868eSNuno Antunes &ng_parse_typebuf_info
8820147868eSNuno Antunes };
8830147868eSNuno Antunes
8840147868eSNuno Antunes const struct ng_parse_fixedstring_info ng_parse_cmdbuf_info = {
8850147868eSNuno Antunes NG_CMDSTRSIZ
8860147868eSNuno Antunes };
8870147868eSNuno Antunes const struct ng_parse_type ng_parse_cmdbuf_type = {
8880147868eSNuno Antunes &ng_parse_fixedstring_type,
8890147868eSNuno Antunes &ng_parse_cmdbuf_info
8900147868eSNuno Antunes };
8910147868eSNuno Antunes
8920147868eSNuno Antunes /************************************************************************
8930147868eSNuno Antunes EXPLICITLY SIZED STRING TYPE
8940147868eSNuno Antunes ************************************************************************/
8950147868eSNuno Antunes
8960147868eSNuno Antunes static int
ng_sizedstring_parse(const struct ng_parse_type * type,const char * s,int * off,const u_char * const start,u_char * const buf,int * buflen)8970147868eSNuno Antunes ng_sizedstring_parse(const struct ng_parse_type *type,
8980147868eSNuno Antunes const char *s, int *off, const u_char *const start,
8990147868eSNuno Antunes u_char *const buf, int *buflen)
9000147868eSNuno Antunes {
9010147868eSNuno Antunes char *sval;
9020147868eSNuno Antunes int len;
9030147868eSNuno Antunes int slen;
9040147868eSNuno Antunes
9050147868eSNuno Antunes if ((sval = ng_get_string_token(s, off, &len, &slen)) == NULL)
9060147868eSNuno Antunes return (EINVAL);
9070147868eSNuno Antunes if (slen > USHRT_MAX) {
9080147868eSNuno Antunes kfree(sval, M_NETGRAPH_PARSE);
9090147868eSNuno Antunes return (EINVAL);
9100147868eSNuno Antunes }
9110147868eSNuno Antunes *off += len;
9120147868eSNuno Antunes *((u_int16_t *)buf) = (u_int16_t)slen;
9130147868eSNuno Antunes bcopy(sval, buf + 2, slen);
9140147868eSNuno Antunes kfree(sval, M_NETGRAPH_PARSE);
9150147868eSNuno Antunes *buflen = 2 + slen;
9160147868eSNuno Antunes return (0);
9170147868eSNuno Antunes }
9180147868eSNuno Antunes
9190147868eSNuno Antunes static int
ng_sizedstring_unparse(const struct ng_parse_type * type,const u_char * data,int * off,char * cbuf,int cbuflen)9200147868eSNuno Antunes ng_sizedstring_unparse(const struct ng_parse_type *type,
9210147868eSNuno Antunes const u_char *data, int *off, char *cbuf, int cbuflen)
9220147868eSNuno Antunes {
9230147868eSNuno Antunes const char *const raw = (const char *)data + *off + 2;
9240147868eSNuno Antunes const int slen = *((const u_int16_t *)(data + *off));
9250147868eSNuno Antunes char *const s = ng_encode_string(raw, slen);
9260147868eSNuno Antunes int error;
9270147868eSNuno Antunes
9280147868eSNuno Antunes if (s == NULL)
9290147868eSNuno Antunes return (ENOMEM);
9300147868eSNuno Antunes if ((error = ng_parse_append(&cbuf, &cbuflen, "%s", s)) != 0) {
9310147868eSNuno Antunes kfree(s, M_NETGRAPH_PARSE);
9320147868eSNuno Antunes return (error);
9330147868eSNuno Antunes }
9340147868eSNuno Antunes kfree(s, M_NETGRAPH_PARSE);
9350147868eSNuno Antunes *off += slen + 2;
9360147868eSNuno Antunes return (0);
9370147868eSNuno Antunes }
9380147868eSNuno Antunes
9390147868eSNuno Antunes static int
ng_sizedstring_getDefault(const struct ng_parse_type * type,const u_char * const start,u_char * buf,int * buflen)9400147868eSNuno Antunes ng_sizedstring_getDefault(const struct ng_parse_type *type,
9410147868eSNuno Antunes const u_char *const start, u_char *buf, int *buflen)
9420147868eSNuno Antunes {
9430147868eSNuno Antunes if (*buflen < 2)
9440147868eSNuno Antunes return (ERANGE);
9450147868eSNuno Antunes bzero(buf, 2);
9460147868eSNuno Antunes *buflen = 2;
9470147868eSNuno Antunes return (0);
9480147868eSNuno Antunes }
9490147868eSNuno Antunes
9500147868eSNuno Antunes const struct ng_parse_type ng_parse_sizedstring_type = {
9510147868eSNuno Antunes NULL,
9520147868eSNuno Antunes NULL,
9530147868eSNuno Antunes NULL,
9540147868eSNuno Antunes ng_sizedstring_parse,
9550147868eSNuno Antunes ng_sizedstring_unparse,
9560147868eSNuno Antunes ng_sizedstring_getDefault,
9570147868eSNuno Antunes NULL
9580147868eSNuno Antunes };
9590147868eSNuno Antunes
9600147868eSNuno Antunes /************************************************************************
9610147868eSNuno Antunes IP ADDRESS TYPE
9620147868eSNuno Antunes ************************************************************************/
9630147868eSNuno Antunes
9640147868eSNuno Antunes static int
ng_ipaddr_parse(const struct ng_parse_type * type,const char * s,int * off,const u_char * const start,u_char * const buf,int * buflen)9650147868eSNuno Antunes ng_ipaddr_parse(const struct ng_parse_type *type,
9660147868eSNuno Antunes const char *s, int *off, const u_char *const start,
9670147868eSNuno Antunes u_char *const buf, int *buflen)
9680147868eSNuno Antunes {
9690147868eSNuno Antunes int i, error;
9700147868eSNuno Antunes
9710147868eSNuno Antunes for (i = 0; i < 4; i++) {
9720147868eSNuno Antunes if ((error = ng_int8_parse(&ng_parse_int8_type,
9730147868eSNuno Antunes s, off, start, buf + i, buflen)) != 0)
9740147868eSNuno Antunes return (error);
9750147868eSNuno Antunes if (i < 3 && s[*off] != '.')
9760147868eSNuno Antunes return (EINVAL);
9770147868eSNuno Antunes (*off)++;
9780147868eSNuno Antunes }
9790147868eSNuno Antunes *buflen = 4;
9800147868eSNuno Antunes return (0);
9810147868eSNuno Antunes }
9820147868eSNuno Antunes
9830147868eSNuno Antunes static int
ng_ipaddr_unparse(const struct ng_parse_type * type,const u_char * data,int * off,char * cbuf,int cbuflen)9840147868eSNuno Antunes ng_ipaddr_unparse(const struct ng_parse_type *type,
9850147868eSNuno Antunes const u_char *data, int *off, char *cbuf, int cbuflen)
9860147868eSNuno Antunes {
9870147868eSNuno Antunes struct in_addr ip;
9880147868eSNuno Antunes int error;
9890147868eSNuno Antunes
9900147868eSNuno Antunes bcopy(data + *off, &ip, sizeof(ip));
9910147868eSNuno Antunes if ((error = ng_parse_append(&cbuf, &cbuflen, "%d.%d.%d.%d",
9920147868eSNuno Antunes ((u_char *)&ip)[0], ((u_char *)&ip)[1],
9930147868eSNuno Antunes ((u_char *)&ip)[2], ((u_char *)&ip)[3])) != 0)
9940147868eSNuno Antunes return (error);
9950147868eSNuno Antunes *off += sizeof(ip);
9960147868eSNuno Antunes return (0);
9970147868eSNuno Antunes }
9980147868eSNuno Antunes
9990147868eSNuno Antunes static int
ng_ipaddr_getDefault(const struct ng_parse_type * type,const u_char * const start,u_char * buf,int * buflen)10000147868eSNuno Antunes ng_ipaddr_getDefault(const struct ng_parse_type *type,
10010147868eSNuno Antunes const u_char *const start, u_char *buf, int *buflen)
10020147868eSNuno Antunes {
10030147868eSNuno Antunes struct in_addr ip = { 0 };
10040147868eSNuno Antunes
10050147868eSNuno Antunes if (*buflen < sizeof(ip))
10060147868eSNuno Antunes return (ERANGE);
10070147868eSNuno Antunes bcopy(&ip, buf, sizeof(ip));
10080147868eSNuno Antunes *buflen = sizeof(ip);
10090147868eSNuno Antunes return (0);
10100147868eSNuno Antunes }
10110147868eSNuno Antunes
10120147868eSNuno Antunes const struct ng_parse_type ng_parse_ipaddr_type = {
10130147868eSNuno Antunes NULL,
10140147868eSNuno Antunes NULL,
10150147868eSNuno Antunes NULL,
10160147868eSNuno Antunes ng_ipaddr_parse,
10170147868eSNuno Antunes ng_ipaddr_unparse,
10180147868eSNuno Antunes ng_ipaddr_getDefault,
10190147868eSNuno Antunes ng_int32_getAlign
10200147868eSNuno Antunes };
10210147868eSNuno Antunes
10220147868eSNuno Antunes /************************************************************************
10230147868eSNuno Antunes ETHERNET ADDRESS TYPE
10240147868eSNuno Antunes ************************************************************************/
10250147868eSNuno Antunes
10260147868eSNuno Antunes static int
ng_enaddr_parse(const struct ng_parse_type * type,const char * s,int * const off,const u_char * const start,u_char * const buf,int * const buflen)10270147868eSNuno Antunes ng_enaddr_parse(const struct ng_parse_type *type,
10280147868eSNuno Antunes const char *s, int *const off, const u_char *const start,
10290147868eSNuno Antunes u_char *const buf, int *const buflen)
10300147868eSNuno Antunes {
10310147868eSNuno Antunes char *eptr;
10320147868eSNuno Antunes u_long val;
10330147868eSNuno Antunes int i;
10340147868eSNuno Antunes
10350147868eSNuno Antunes if (*buflen < ETHER_ADDR_LEN)
10360147868eSNuno Antunes return (ERANGE);
10370147868eSNuno Antunes for (i = 0; i < ETHER_ADDR_LEN; i++) {
10380147868eSNuno Antunes val = strtoul(s + *off, &eptr, 16);
10390147868eSNuno Antunes if (val > 0xff || eptr == s + *off)
10400147868eSNuno Antunes return (EINVAL);
10410147868eSNuno Antunes buf[i] = (u_char)val;
10420147868eSNuno Antunes *off = (eptr - s);
10430147868eSNuno Antunes if (i < ETHER_ADDR_LEN - 1) {
10440147868eSNuno Antunes if (*eptr != ':')
10450147868eSNuno Antunes return (EINVAL);
10460147868eSNuno Antunes (*off)++;
10470147868eSNuno Antunes }
10480147868eSNuno Antunes }
10490147868eSNuno Antunes *buflen = ETHER_ADDR_LEN;
10500147868eSNuno Antunes return (0);
10510147868eSNuno Antunes }
10520147868eSNuno Antunes
10530147868eSNuno Antunes static int
ng_enaddr_unparse(const struct ng_parse_type * type,const u_char * data,int * off,char * cbuf,int cbuflen)10540147868eSNuno Antunes ng_enaddr_unparse(const struct ng_parse_type *type,
10550147868eSNuno Antunes const u_char *data, int *off, char *cbuf, int cbuflen)
10560147868eSNuno Antunes {
10570147868eSNuno Antunes int len;
10580147868eSNuno Antunes
1059a62226e4SSascha Wildner len = ksnprintf(cbuf, cbuflen, "%02x:%02x:%02x:%02x:%02x:%02x",
10600147868eSNuno Antunes data[*off], data[*off + 1], data[*off + 2],
10610147868eSNuno Antunes data[*off + 3], data[*off + 4], data[*off + 5]);
10620147868eSNuno Antunes if (len >= cbuflen)
10630147868eSNuno Antunes return (ERANGE);
10640147868eSNuno Antunes *off += ETHER_ADDR_LEN;
10650147868eSNuno Antunes return (0);
10660147868eSNuno Antunes }
10670147868eSNuno Antunes
10680147868eSNuno Antunes const struct ng_parse_type ng_parse_enaddr_type = {
10690147868eSNuno Antunes NULL,
10700147868eSNuno Antunes NULL,
10710147868eSNuno Antunes NULL,
10720147868eSNuno Antunes ng_enaddr_parse,
10730147868eSNuno Antunes ng_enaddr_unparse,
10740147868eSNuno Antunes NULL,
10750147868eSNuno Antunes 0
10760147868eSNuno Antunes };
10770147868eSNuno Antunes
10780147868eSNuno Antunes /************************************************************************
10790147868eSNuno Antunes BYTE ARRAY TYPE
10800147868eSNuno Antunes ************************************************************************/
10810147868eSNuno Antunes
10820147868eSNuno Antunes /* Get the length of a byte array */
10830147868eSNuno Antunes static int
ng_parse_bytearray_subtype_getLength(const struct ng_parse_type * type,const u_char * start,const u_char * buf)10840147868eSNuno Antunes ng_parse_bytearray_subtype_getLength(const struct ng_parse_type *type,
10850147868eSNuno Antunes const u_char *start, const u_char *buf)
10860147868eSNuno Antunes {
10870147868eSNuno Antunes ng_parse_array_getLength_t *const getLength = type->private;
10880147868eSNuno Antunes
10890147868eSNuno Antunes return (*getLength)(type, start, buf);
10900147868eSNuno Antunes }
10910147868eSNuno Antunes
10920147868eSNuno Antunes /* Byte array element type is hex int8 */
10930147868eSNuno Antunes static const struct ng_parse_array_info ng_parse_bytearray_subtype_info = {
10940147868eSNuno Antunes &ng_parse_hint8_type,
10950147868eSNuno Antunes &ng_parse_bytearray_subtype_getLength,
10960147868eSNuno Antunes NULL
10970147868eSNuno Antunes };
10980147868eSNuno Antunes static const struct ng_parse_type ng_parse_bytearray_subtype = {
10990147868eSNuno Antunes &ng_parse_array_type,
11000147868eSNuno Antunes &ng_parse_bytearray_subtype_info
11010147868eSNuno Antunes };
11020147868eSNuno Antunes
11030147868eSNuno Antunes static int
ng_bytearray_parse(const struct ng_parse_type * type,const char * s,int * off,const u_char * const start,u_char * const buf,int * buflen)11040147868eSNuno Antunes ng_bytearray_parse(const struct ng_parse_type *type,
11050147868eSNuno Antunes const char *s, int *off, const u_char *const start,
11060147868eSNuno Antunes u_char *const buf, int *buflen)
11070147868eSNuno Antunes {
11080147868eSNuno Antunes char *str;
11090147868eSNuno Antunes int toklen;
11100147868eSNuno Antunes int slen;
11110147868eSNuno Antunes
11120147868eSNuno Antunes /* We accept either an array of bytes or a string constant */
11130147868eSNuno Antunes if ((str = ng_get_string_token(s, off, &toklen, &slen)) != NULL) {
11140147868eSNuno Antunes ng_parse_array_getLength_t *const getLength = type->info;
11150147868eSNuno Antunes int arraylen;
11160147868eSNuno Antunes
11170147868eSNuno Antunes arraylen = (*getLength)(type, start, buf);
11180147868eSNuno Antunes if (arraylen > *buflen) {
11190147868eSNuno Antunes kfree(str, M_NETGRAPH_PARSE);
11200147868eSNuno Antunes return (ERANGE);
11210147868eSNuno Antunes }
11220147868eSNuno Antunes if (slen > arraylen) {
11230147868eSNuno Antunes kfree(str, M_NETGRAPH_PARSE);
11240147868eSNuno Antunes return (E2BIG);
11250147868eSNuno Antunes }
11260147868eSNuno Antunes bcopy(str, buf, slen);
11270147868eSNuno Antunes bzero(buf + slen, arraylen - slen);
11280147868eSNuno Antunes kfree(str, M_NETGRAPH_PARSE);
11290147868eSNuno Antunes *off += toklen;
11300147868eSNuno Antunes *buflen = arraylen;
11310147868eSNuno Antunes return (0);
11320147868eSNuno Antunes } else {
11330147868eSNuno Antunes struct ng_parse_type subtype;
11340147868eSNuno Antunes
11350147868eSNuno Antunes subtype = ng_parse_bytearray_subtype;
1136051e9f04SSascha Wildner *(const void **)(void *)&subtype.private = type->info;
11370147868eSNuno Antunes return ng_array_parse(&subtype, s, off, start, buf, buflen);
11380147868eSNuno Antunes }
11390147868eSNuno Antunes }
11400147868eSNuno Antunes
11410147868eSNuno Antunes static int
ng_bytearray_unparse(const struct ng_parse_type * type,const u_char * data,int * off,char * cbuf,int cbuflen)11420147868eSNuno Antunes ng_bytearray_unparse(const struct ng_parse_type *type,
11430147868eSNuno Antunes const u_char *data, int *off, char *cbuf, int cbuflen)
11440147868eSNuno Antunes {
11450147868eSNuno Antunes struct ng_parse_type subtype;
11460147868eSNuno Antunes
11470147868eSNuno Antunes subtype = ng_parse_bytearray_subtype;
1148051e9f04SSascha Wildner *(const void **)(void *)&subtype.private = type->info;
11490147868eSNuno Antunes return ng_array_unparse(&subtype, data, off, cbuf, cbuflen);
11500147868eSNuno Antunes }
11510147868eSNuno Antunes
11520147868eSNuno Antunes static int
ng_bytearray_getDefault(const struct ng_parse_type * type,const u_char * const start,u_char * buf,int * buflen)11530147868eSNuno Antunes ng_bytearray_getDefault(const struct ng_parse_type *type,
11540147868eSNuno Antunes const u_char *const start, u_char *buf, int *buflen)
11550147868eSNuno Antunes {
11560147868eSNuno Antunes struct ng_parse_type subtype;
11570147868eSNuno Antunes
11580147868eSNuno Antunes subtype = ng_parse_bytearray_subtype;
1159051e9f04SSascha Wildner *(const void **)(void *)&subtype.private = type->info;
11600147868eSNuno Antunes return ng_array_getDefault(&subtype, start, buf, buflen);
11610147868eSNuno Antunes }
11620147868eSNuno Antunes
11630147868eSNuno Antunes const struct ng_parse_type ng_parse_bytearray_type = {
11640147868eSNuno Antunes NULL,
11650147868eSNuno Antunes NULL,
11660147868eSNuno Antunes NULL,
11670147868eSNuno Antunes ng_bytearray_parse,
11680147868eSNuno Antunes ng_bytearray_unparse,
11690147868eSNuno Antunes ng_bytearray_getDefault,
11700147868eSNuno Antunes NULL
11710147868eSNuno Antunes };
11720147868eSNuno Antunes
11730147868eSNuno Antunes /************************************************************************
11740147868eSNuno Antunes STRUCT NG_MESG TYPE
11750147868eSNuno Antunes ************************************************************************/
11760147868eSNuno Antunes
11770147868eSNuno Antunes /* Get msg->header.arglen when "buf" is pointing to msg->data */
11780147868eSNuno Antunes static int
ng_parse_ng_mesg_getLength(const struct ng_parse_type * type,const u_char * start,const u_char * buf)11790147868eSNuno Antunes ng_parse_ng_mesg_getLength(const struct ng_parse_type *type,
11800147868eSNuno Antunes const u_char *start, const u_char *buf)
11810147868eSNuno Antunes {
11820147868eSNuno Antunes const struct ng_mesg *msg;
11830147868eSNuno Antunes
11840147868eSNuno Antunes msg = (const struct ng_mesg *)(buf - sizeof(*msg));
11850147868eSNuno Antunes return msg->header.arglen;
11860147868eSNuno Antunes }
11870147868eSNuno Antunes
11880147868eSNuno Antunes /* Type for the variable length data portion of a struct ng_mesg */
11890147868eSNuno Antunes static const struct ng_parse_type ng_msg_data_type = {
11900147868eSNuno Antunes &ng_parse_bytearray_type,
11910147868eSNuno Antunes &ng_parse_ng_mesg_getLength
11920147868eSNuno Antunes };
11930147868eSNuno Antunes
11940147868eSNuno Antunes /* Type for the entire struct ng_mesg header with data section */
11950147868eSNuno Antunes static const struct ng_parse_struct_field ng_parse_ng_mesg_type_fields[]
11960147868eSNuno Antunes = NG_GENERIC_NG_MESG_INFO(&ng_msg_data_type);
11970147868eSNuno Antunes const struct ng_parse_type ng_parse_ng_mesg_type = {
11980147868eSNuno Antunes &ng_parse_struct_type,
11990147868eSNuno Antunes &ng_parse_ng_mesg_type_fields,
12000147868eSNuno Antunes };
12010147868eSNuno Antunes
12020147868eSNuno Antunes /************************************************************************
12030147868eSNuno Antunes COMPOSITE HELPER ROUTINES
12040147868eSNuno Antunes ************************************************************************/
12050147868eSNuno Antunes
12060147868eSNuno Antunes /*
12070147868eSNuno Antunes * Convert a structure or array from ASCII to binary
12080147868eSNuno Antunes */
12090147868eSNuno Antunes static int
ng_parse_composite(const struct ng_parse_type * type,const char * s,int * off,const u_char * const start,u_char * const buf,int * buflen,const enum comptype ctype)12100147868eSNuno Antunes ng_parse_composite(const struct ng_parse_type *type, const char *s,
12110147868eSNuno Antunes int *off, const u_char *const start, u_char *const buf, int *buflen,
12120147868eSNuno Antunes const enum comptype ctype)
12130147868eSNuno Antunes {
12140147868eSNuno Antunes const int num = ng_get_composite_len(type, start, buf, ctype);
12150147868eSNuno Antunes int nextIndex = 0; /* next implicit array index */
12160147868eSNuno Antunes u_int index; /* field or element index */
12170147868eSNuno Antunes int *foff; /* field value offsets in string */
12180147868eSNuno Antunes int align, len, blen, error = 0;
12190147868eSNuno Antunes
12200147868eSNuno Antunes /* Initialize */
12210147868eSNuno Antunes foff = kmalloc(num * sizeof(*foff), M_NETGRAPH_PARSE,
12220147868eSNuno Antunes M_WAITOK | M_NULLOK | M_ZERO);
12230147868eSNuno Antunes if (foff == NULL) {
12240147868eSNuno Antunes error = ENOMEM;
12250147868eSNuno Antunes goto done;
12260147868eSNuno Antunes }
12270147868eSNuno Antunes
12280147868eSNuno Antunes /* Get opening brace/bracket */
12290147868eSNuno Antunes if (ng_parse_get_token(s, off, &len)
12300147868eSNuno Antunes != (ctype == CT_STRUCT ? T_LBRACE : T_LBRACKET)) {
12310147868eSNuno Antunes error = EINVAL;
12320147868eSNuno Antunes goto done;
12330147868eSNuno Antunes }
12340147868eSNuno Antunes *off += len;
12350147868eSNuno Antunes
12360147868eSNuno Antunes /* Get individual element value positions in the string */
12370147868eSNuno Antunes for (;;) {
12380147868eSNuno Antunes enum ng_parse_token tok;
12390147868eSNuno Antunes
12400147868eSNuno Antunes /* Check for closing brace/bracket */
12410147868eSNuno Antunes tok = ng_parse_get_token(s, off, &len);
12420147868eSNuno Antunes if (tok == (ctype == CT_STRUCT ? T_RBRACE : T_RBRACKET)) {
12430147868eSNuno Antunes *off += len;
12440147868eSNuno Antunes break;
12450147868eSNuno Antunes }
12460147868eSNuno Antunes
12470147868eSNuno Antunes /* For arrays, the 'name' (ie, index) is optional, so
12480147868eSNuno Antunes distinguish name from values by seeing if the next
12490147868eSNuno Antunes token is an equals sign */
12500147868eSNuno Antunes if (ctype != CT_STRUCT) {
12510147868eSNuno Antunes int len2, off2;
12520147868eSNuno Antunes char *eptr;
12530147868eSNuno Antunes
12540147868eSNuno Antunes /* If an opening brace/bracket, index is implied */
12550147868eSNuno Antunes if (tok == T_LBRACE || tok == T_LBRACKET) {
12560147868eSNuno Antunes index = nextIndex++;
12570147868eSNuno Antunes goto gotIndex;
12580147868eSNuno Antunes }
12590147868eSNuno Antunes
12600147868eSNuno Antunes /* Might be an index, might be a value, either way... */
12610147868eSNuno Antunes if (tok != T_WORD) {
12620147868eSNuno Antunes error = EINVAL;
12630147868eSNuno Antunes goto done;
12640147868eSNuno Antunes }
12650147868eSNuno Antunes
12660147868eSNuno Antunes /* If no equals sign follows, index is implied */
12670147868eSNuno Antunes off2 = *off + len;
12680147868eSNuno Antunes if (ng_parse_get_token(s, &off2, &len2) != T_EQUALS) {
12690147868eSNuno Antunes index = nextIndex++;
12700147868eSNuno Antunes goto gotIndex;
12710147868eSNuno Antunes }
12720147868eSNuno Antunes
12730147868eSNuno Antunes /* Index was specified explicitly; parse it */
12740147868eSNuno Antunes index = (u_int)strtoul(s + *off, &eptr, 0);
12750147868eSNuno Antunes if (index < 0 || eptr - (s + *off) != len) {
12760147868eSNuno Antunes error = EINVAL;
12770147868eSNuno Antunes goto done;
12780147868eSNuno Antunes }
12790147868eSNuno Antunes nextIndex = index + 1;
12800147868eSNuno Antunes *off += len + len2;
12810147868eSNuno Antunes } else { /* a structure field */
12820147868eSNuno Antunes const struct ng_parse_struct_field *const
12830147868eSNuno Antunes fields = type->info;
12840147868eSNuno Antunes
12850147868eSNuno Antunes /* Find the field by name (required) in field list */
12860147868eSNuno Antunes if (tok != T_WORD) {
12870147868eSNuno Antunes error = EINVAL;
12880147868eSNuno Antunes goto done;
12890147868eSNuno Antunes }
12900147868eSNuno Antunes for (index = 0; index < num; index++) {
12910147868eSNuno Antunes const struct ng_parse_struct_field *const
12920147868eSNuno Antunes field = &fields[index];
12930147868eSNuno Antunes
12940147868eSNuno Antunes if (strncmp(&s[*off], field->name, len) == 0
12950147868eSNuno Antunes && field->name[len] == '\0')
12960147868eSNuno Antunes break;
12970147868eSNuno Antunes }
12980147868eSNuno Antunes if (index == num) {
12990147868eSNuno Antunes error = ENOENT;
13000147868eSNuno Antunes goto done;
13010147868eSNuno Antunes }
13020147868eSNuno Antunes *off += len;
13030147868eSNuno Antunes
13040147868eSNuno Antunes /* Get equals sign */
13050147868eSNuno Antunes if (ng_parse_get_token(s, off, &len) != T_EQUALS) {
13060147868eSNuno Antunes error = EINVAL;
13070147868eSNuno Antunes goto done;
13080147868eSNuno Antunes }
13090147868eSNuno Antunes *off += len;
13100147868eSNuno Antunes }
13110147868eSNuno Antunes gotIndex:
13120147868eSNuno Antunes
13130147868eSNuno Antunes /* Check array index */
13140147868eSNuno Antunes if (index >= num) {
13150147868eSNuno Antunes error = E2BIG;
13160147868eSNuno Antunes goto done;
13170147868eSNuno Antunes }
13180147868eSNuno Antunes
13190147868eSNuno Antunes /* Save value's position and skip over it for now */
13200147868eSNuno Antunes if (foff[index] != 0) {
13210147868eSNuno Antunes error = EALREADY; /* duplicate */
13220147868eSNuno Antunes goto done;
13230147868eSNuno Antunes }
13240147868eSNuno Antunes while (isspace(s[*off]))
13250147868eSNuno Antunes (*off)++;
13260147868eSNuno Antunes foff[index] = *off;
13270147868eSNuno Antunes if ((error = ng_parse_skip_value(s, *off, &len)) != 0)
13280147868eSNuno Antunes goto done;
13290147868eSNuno Antunes *off += len;
13300147868eSNuno Antunes }
13310147868eSNuno Antunes
13320147868eSNuno Antunes /* Now build binary structure from supplied values and defaults */
13330147868eSNuno Antunes for (blen = index = 0; index < num; index++) {
13340147868eSNuno Antunes const struct ng_parse_type *const
13350147868eSNuno Antunes etype = ng_get_composite_etype(type, index, ctype);
13360147868eSNuno Antunes int k, pad, vlen;
13370147868eSNuno Antunes
13380147868eSNuno Antunes /* Zero-pad any alignment bytes */
13390147868eSNuno Antunes pad = ng_parse_get_elem_pad(type, index, ctype, blen);
13400147868eSNuno Antunes for (k = 0; k < pad; k++) {
13410147868eSNuno Antunes if (blen >= *buflen) {
13420147868eSNuno Antunes error = ERANGE;
13430147868eSNuno Antunes goto done;
13440147868eSNuno Antunes }
13450147868eSNuno Antunes buf[blen++] = 0;
13460147868eSNuno Antunes }
13470147868eSNuno Antunes
13480147868eSNuno Antunes /* Get value */
13490147868eSNuno Antunes vlen = *buflen - blen;
13500147868eSNuno Antunes if (foff[index] == 0) { /* use default value */
13510147868eSNuno Antunes error = ng_get_composite_elem_default(type, index,
13520147868eSNuno Antunes start, buf + blen, &vlen, ctype);
13530147868eSNuno Antunes } else { /* parse given value */
13540147868eSNuno Antunes *off = foff[index];
13550147868eSNuno Antunes error = INVOKE(etype, parse)(etype,
13560147868eSNuno Antunes s, off, start, buf + blen, &vlen);
13570147868eSNuno Antunes }
13580147868eSNuno Antunes if (error != 0)
13590147868eSNuno Antunes goto done;
13600147868eSNuno Antunes blen += vlen;
13610147868eSNuno Antunes }
13620147868eSNuno Antunes
13630147868eSNuno Antunes /* Make total composite structure size a multiple of its alignment */
13640147868eSNuno Antunes if ((align = ALIGNMENT(type)) != 0) {
13650147868eSNuno Antunes while (blen % align != 0) {
13660147868eSNuno Antunes if (blen >= *buflen) {
13670147868eSNuno Antunes error = ERANGE;
13680147868eSNuno Antunes goto done;
13690147868eSNuno Antunes }
13700147868eSNuno Antunes buf[blen++] = 0;
13710147868eSNuno Antunes }
13720147868eSNuno Antunes }
13730147868eSNuno Antunes
13740147868eSNuno Antunes /* Done */
13750147868eSNuno Antunes *buflen = blen;
13760147868eSNuno Antunes done:
13770147868eSNuno Antunes if (foff != NULL)
13780147868eSNuno Antunes kfree(foff, M_NETGRAPH_PARSE);
13790147868eSNuno Antunes return (error);
13800147868eSNuno Antunes }
13810147868eSNuno Antunes
13820147868eSNuno Antunes /*
13830147868eSNuno Antunes * Convert an array or structure from binary to ASCII
13840147868eSNuno Antunes */
13850147868eSNuno Antunes static int
ng_unparse_composite(const struct ng_parse_type * type,const u_char * data,int * off,char * cbuf,int cbuflen,const enum comptype ctype)13860147868eSNuno Antunes ng_unparse_composite(const struct ng_parse_type *type, const u_char *data,
13870147868eSNuno Antunes int *off, char *cbuf, int cbuflen, const enum comptype ctype)
13880147868eSNuno Antunes {
13890147868eSNuno Antunes const struct ng_mesg *const hdr
13900147868eSNuno Antunes = (const struct ng_mesg *)(data - sizeof(*hdr));
13910147868eSNuno Antunes const int num = ng_get_composite_len(type, data, data + *off, ctype);
13920147868eSNuno Antunes const int workSize = 20 * 1024; /* XXX hard coded constant */
13930147868eSNuno Antunes int nextIndex = 0, didOne = 0;
13940147868eSNuno Antunes int error, index;
13950147868eSNuno Antunes u_char *workBuf;
13960147868eSNuno Antunes
13970147868eSNuno Antunes /* Get workspace for checking default values */
13980147868eSNuno Antunes workBuf = kmalloc(workSize, M_NETGRAPH_PARSE, M_WAITOK | M_NULLOK);
13990147868eSNuno Antunes if (workBuf == NULL)
14000147868eSNuno Antunes return (ENOMEM);
14010147868eSNuno Antunes
14020147868eSNuno Antunes /* Opening brace/bracket */
14030147868eSNuno Antunes if ((error = ng_parse_append(&cbuf, &cbuflen, "%c",
14040147868eSNuno Antunes (ctype == CT_STRUCT) ? '{' : '[')) != 0)
14050147868eSNuno Antunes goto fail;
14060147868eSNuno Antunes
14070147868eSNuno Antunes /* Do each item */
14080147868eSNuno Antunes for (index = 0; index < num; index++) {
14090147868eSNuno Antunes const struct ng_parse_type *const
14100147868eSNuno Antunes etype = ng_get_composite_etype(type, index, ctype);
14110147868eSNuno Antunes
14120147868eSNuno Antunes /* Skip any alignment pad bytes */
14130147868eSNuno Antunes *off += ng_parse_get_elem_pad(type, index, ctype, *off);
14140147868eSNuno Antunes
14150147868eSNuno Antunes /*
14160147868eSNuno Antunes * See if element is equal to its default value; skip if so.
14170147868eSNuno Antunes * Copy struct ng_mesg header for types that peek into it.
14180147868eSNuno Antunes */
14190147868eSNuno Antunes if (sizeof(*hdr) + *off < workSize) {
14200147868eSNuno Antunes int tempsize = workSize - sizeof(*hdr) - *off;
14210147868eSNuno Antunes
14220147868eSNuno Antunes bcopy(hdr, workBuf, sizeof(*hdr) + *off);
14230147868eSNuno Antunes if (ng_get_composite_elem_default(type, index, workBuf
14240147868eSNuno Antunes + sizeof(*hdr), workBuf + sizeof(*hdr) + *off,
14250147868eSNuno Antunes &tempsize, ctype) == 0
14260147868eSNuno Antunes && bcmp(workBuf + sizeof(*hdr) + *off,
14270147868eSNuno Antunes data + *off, tempsize) == 0) {
14280147868eSNuno Antunes *off += tempsize;
14290147868eSNuno Antunes continue;
14300147868eSNuno Antunes }
14310147868eSNuno Antunes }
14320147868eSNuno Antunes
14330147868eSNuno Antunes /* Print name= */
14340147868eSNuno Antunes if ((error = ng_parse_append(&cbuf, &cbuflen, " ")) != 0)
14350147868eSNuno Antunes goto fail;
14360147868eSNuno Antunes if (ctype != CT_STRUCT) {
14370147868eSNuno Antunes if (index != nextIndex) {
14380147868eSNuno Antunes nextIndex = index;
14390147868eSNuno Antunes if ((error = ng_parse_append(&cbuf,
14400147868eSNuno Antunes &cbuflen, "%d=", index)) != 0)
14410147868eSNuno Antunes goto fail;
14420147868eSNuno Antunes }
14430147868eSNuno Antunes nextIndex++;
14440147868eSNuno Antunes } else {
14450147868eSNuno Antunes const struct ng_parse_struct_field *const
14460147868eSNuno Antunes fields = type->info;
14470147868eSNuno Antunes
14480147868eSNuno Antunes if ((error = ng_parse_append(&cbuf,
14490147868eSNuno Antunes &cbuflen, "%s=", fields[index].name)) != 0)
14500147868eSNuno Antunes goto fail;
14510147868eSNuno Antunes }
14520147868eSNuno Antunes
14530147868eSNuno Antunes /* Print value */
14540147868eSNuno Antunes if ((error = INVOKE(etype, unparse)
14550147868eSNuno Antunes (etype, data, off, cbuf, cbuflen)) != 0) {
14560147868eSNuno Antunes kfree(workBuf, M_NETGRAPH_PARSE);
14570147868eSNuno Antunes return (error);
14580147868eSNuno Antunes }
14590147868eSNuno Antunes cbuflen -= strlen(cbuf);
14600147868eSNuno Antunes cbuf += strlen(cbuf);
14610147868eSNuno Antunes didOne = 1;
14620147868eSNuno Antunes }
14630147868eSNuno Antunes
14640147868eSNuno Antunes /* Closing brace/bracket */
14650147868eSNuno Antunes error = ng_parse_append(&cbuf, &cbuflen, "%s%c",
14660147868eSNuno Antunes didOne ? " " : "", (ctype == CT_STRUCT) ? '}' : ']');
14670147868eSNuno Antunes
14680147868eSNuno Antunes fail:
14690147868eSNuno Antunes /* Clean up after failure */
14700147868eSNuno Antunes kfree(workBuf, M_NETGRAPH_PARSE);
14710147868eSNuno Antunes return (error);
14720147868eSNuno Antunes }
14730147868eSNuno Antunes
14740147868eSNuno Antunes /*
14750147868eSNuno Antunes * Generate the default value for an element of an array or structure
14760147868eSNuno Antunes * Returns EOPNOTSUPP if default value is unspecified.
14770147868eSNuno Antunes */
14780147868eSNuno Antunes static int
ng_get_composite_elem_default(const struct ng_parse_type * type,int index,const u_char * const start,u_char * buf,int * buflen,const enum comptype ctype)14790147868eSNuno Antunes ng_get_composite_elem_default(const struct ng_parse_type *type,
14800147868eSNuno Antunes int index, const u_char *const start, u_char *buf, int *buflen,
14810147868eSNuno Antunes const enum comptype ctype)
14820147868eSNuno Antunes {
14830147868eSNuno Antunes const struct ng_parse_type *etype;
14840147868eSNuno Antunes ng_getDefault_t *func;
14850147868eSNuno Antunes
14860147868eSNuno Antunes switch (ctype) {
14870147868eSNuno Antunes case CT_STRUCT:
14880147868eSNuno Antunes break;
14890147868eSNuno Antunes case CT_ARRAY:
14900147868eSNuno Antunes {
14910147868eSNuno Antunes const struct ng_parse_array_info *const ai = type->info;
14920147868eSNuno Antunes
14930147868eSNuno Antunes if (ai->getDefault != NULL) {
14940147868eSNuno Antunes return (*ai->getDefault)(type,
14950147868eSNuno Antunes index, start, buf, buflen);
14960147868eSNuno Antunes }
14970147868eSNuno Antunes break;
14980147868eSNuno Antunes }
14990147868eSNuno Antunes case CT_FIXEDARRAY:
15000147868eSNuno Antunes {
15010147868eSNuno Antunes const struct ng_parse_fixedarray_info *const fi = type->info;
15020147868eSNuno Antunes
15030147868eSNuno Antunes if (*fi->getDefault != NULL) {
15040147868eSNuno Antunes return (*fi->getDefault)(type,
15050147868eSNuno Antunes index, start, buf, buflen);
15060147868eSNuno Antunes }
15070147868eSNuno Antunes break;
15080147868eSNuno Antunes }
15090147868eSNuno Antunes default:
15100147868eSNuno Antunes panic("%s", __func__);
15110147868eSNuno Antunes }
15120147868eSNuno Antunes
15130147868eSNuno Antunes /* Default to element type default */
15140147868eSNuno Antunes etype = ng_get_composite_etype(type, index, ctype);
15150147868eSNuno Antunes func = METHOD(etype, getDefault);
15160147868eSNuno Antunes if (func == NULL)
15170147868eSNuno Antunes return (EOPNOTSUPP);
15180147868eSNuno Antunes return (*func)(etype, start, buf, buflen);
15190147868eSNuno Antunes }
15200147868eSNuno Antunes
15210147868eSNuno Antunes /*
15220147868eSNuno Antunes * Get the number of elements in a struct, variable or fixed array.
15230147868eSNuno Antunes */
15240147868eSNuno Antunes static int
ng_get_composite_len(const struct ng_parse_type * type,const u_char * const start,const u_char * buf,const enum comptype ctype)15250147868eSNuno Antunes ng_get_composite_len(const struct ng_parse_type *type,
15260147868eSNuno Antunes const u_char *const start, const u_char *buf,
15270147868eSNuno Antunes const enum comptype ctype)
15280147868eSNuno Antunes {
15290147868eSNuno Antunes switch (ctype) {
15300147868eSNuno Antunes case CT_STRUCT:
15310147868eSNuno Antunes {
15320147868eSNuno Antunes const struct ng_parse_struct_field *const fields = type->info;
15330147868eSNuno Antunes int numFields = 0;
15340147868eSNuno Antunes
15350147868eSNuno Antunes for (numFields = 0; ; numFields++) {
15360147868eSNuno Antunes const struct ng_parse_struct_field *const
15370147868eSNuno Antunes fi = &fields[numFields];
15380147868eSNuno Antunes
15390147868eSNuno Antunes if (fi->name == NULL)
15400147868eSNuno Antunes break;
15410147868eSNuno Antunes }
15420147868eSNuno Antunes return (numFields);
15430147868eSNuno Antunes }
15440147868eSNuno Antunes case CT_ARRAY:
15450147868eSNuno Antunes {
15460147868eSNuno Antunes const struct ng_parse_array_info *const ai = type->info;
15470147868eSNuno Antunes
15480147868eSNuno Antunes return (*ai->getLength)(type, start, buf);
15490147868eSNuno Antunes }
15500147868eSNuno Antunes case CT_FIXEDARRAY:
15510147868eSNuno Antunes {
15520147868eSNuno Antunes const struct ng_parse_fixedarray_info *const fi = type->info;
15530147868eSNuno Antunes
15540147868eSNuno Antunes return fi->length;
15550147868eSNuno Antunes }
15560147868eSNuno Antunes default:
15570147868eSNuno Antunes panic("%s", __func__);
15580147868eSNuno Antunes }
15590147868eSNuno Antunes return (0);
15600147868eSNuno Antunes }
15610147868eSNuno Antunes
15620147868eSNuno Antunes /*
15630147868eSNuno Antunes * Return the type of the index'th element of a composite structure
15640147868eSNuno Antunes */
15650147868eSNuno Antunes static const struct ng_parse_type *
ng_get_composite_etype(const struct ng_parse_type * type,int index,const enum comptype ctype)15660147868eSNuno Antunes ng_get_composite_etype(const struct ng_parse_type *type,
15670147868eSNuno Antunes int index, const enum comptype ctype)
15680147868eSNuno Antunes {
15690147868eSNuno Antunes const struct ng_parse_type *etype = NULL;
15700147868eSNuno Antunes
15710147868eSNuno Antunes switch (ctype) {
15720147868eSNuno Antunes case CT_STRUCT:
15730147868eSNuno Antunes {
15740147868eSNuno Antunes const struct ng_parse_struct_field *const fields = type->info;
15750147868eSNuno Antunes
15760147868eSNuno Antunes etype = fields[index].type;
15770147868eSNuno Antunes break;
15780147868eSNuno Antunes }
15790147868eSNuno Antunes case CT_ARRAY:
15800147868eSNuno Antunes {
15810147868eSNuno Antunes const struct ng_parse_array_info *const ai = type->info;
15820147868eSNuno Antunes
15830147868eSNuno Antunes etype = ai->elementType;
15840147868eSNuno Antunes break;
15850147868eSNuno Antunes }
15860147868eSNuno Antunes case CT_FIXEDARRAY:
15870147868eSNuno Antunes {
15880147868eSNuno Antunes const struct ng_parse_fixedarray_info *const fi = type->info;
15890147868eSNuno Antunes
15900147868eSNuno Antunes etype = fi->elementType;
15910147868eSNuno Antunes break;
15920147868eSNuno Antunes }
15930147868eSNuno Antunes default:
15940147868eSNuno Antunes panic("%s", __func__);
15950147868eSNuno Antunes }
15960147868eSNuno Antunes return (etype);
15970147868eSNuno Antunes }
15980147868eSNuno Antunes
15990147868eSNuno Antunes /*
16000147868eSNuno Antunes * Get the number of bytes to skip to align for the next
16010147868eSNuno Antunes * element in a composite structure.
16020147868eSNuno Antunes */
16030147868eSNuno Antunes static int
ng_parse_get_elem_pad(const struct ng_parse_type * type,int index,enum comptype ctype,int posn)16040147868eSNuno Antunes ng_parse_get_elem_pad(const struct ng_parse_type *type,
16050147868eSNuno Antunes int index, enum comptype ctype, int posn)
16060147868eSNuno Antunes {
16070147868eSNuno Antunes const struct ng_parse_type *const
16080147868eSNuno Antunes etype = ng_get_composite_etype(type, index, ctype);
16090147868eSNuno Antunes int align;
16100147868eSNuno Antunes
16110147868eSNuno Antunes /* Get element's alignment, and possibly override */
16120147868eSNuno Antunes align = ALIGNMENT(etype);
16130147868eSNuno Antunes if (ctype == CT_STRUCT) {
16140147868eSNuno Antunes const struct ng_parse_struct_field *const fields = type->info;
16150147868eSNuno Antunes
16160147868eSNuno Antunes if (fields[index].alignment != 0)
16170147868eSNuno Antunes align = fields[index].alignment;
16180147868eSNuno Antunes }
16190147868eSNuno Antunes
16200147868eSNuno Antunes /* Return number of bytes to skip to align */
16210147868eSNuno Antunes return (align ? (align - (posn % align)) % align : 0);
16220147868eSNuno Antunes }
16230147868eSNuno Antunes
16240147868eSNuno Antunes /************************************************************************
16250147868eSNuno Antunes PARSING HELPER ROUTINES
16260147868eSNuno Antunes ************************************************************************/
16270147868eSNuno Antunes
16280147868eSNuno Antunes /*
16290147868eSNuno Antunes * Append to a fixed length string buffer.
16300147868eSNuno Antunes */
16310147868eSNuno Antunes static int
ng_parse_append(char ** cbufp,int * cbuflenp,const char * fmt,...)16320147868eSNuno Antunes ng_parse_append(char **cbufp, int *cbuflenp, const char *fmt, ...)
16330147868eSNuno Antunes {
16340147868eSNuno Antunes va_list args;
16350147868eSNuno Antunes int len;
16360147868eSNuno Antunes
16370147868eSNuno Antunes va_start(args, fmt);
1638a62226e4SSascha Wildner len = kvsnprintf(*cbufp, *cbuflenp, fmt, args);
16390147868eSNuno Antunes va_end(args);
16400147868eSNuno Antunes if (len >= *cbuflenp)
16410147868eSNuno Antunes return ERANGE;
16420147868eSNuno Antunes *cbufp += len;
16430147868eSNuno Antunes *cbuflenp -= len;
16440147868eSNuno Antunes
16450147868eSNuno Antunes return (0);
16460147868eSNuno Antunes }
16470147868eSNuno Antunes
16480147868eSNuno Antunes /*
16490147868eSNuno Antunes * Skip over a value
16500147868eSNuno Antunes */
16510147868eSNuno Antunes static int
ng_parse_skip_value(const char * s,int off0,int * lenp)16520147868eSNuno Antunes ng_parse_skip_value(const char *s, int off0, int *lenp)
16530147868eSNuno Antunes {
16540147868eSNuno Antunes int len, nbracket, nbrace;
16550147868eSNuno Antunes int off = off0;
16560147868eSNuno Antunes
16570147868eSNuno Antunes len = nbracket = nbrace = 0;
16580147868eSNuno Antunes do {
16590147868eSNuno Antunes switch (ng_parse_get_token(s, &off, &len)) {
16600147868eSNuno Antunes case T_LBRACKET:
16610147868eSNuno Antunes nbracket++;
16620147868eSNuno Antunes break;
16630147868eSNuno Antunes case T_LBRACE:
16640147868eSNuno Antunes nbrace++;
16650147868eSNuno Antunes break;
16660147868eSNuno Antunes case T_RBRACKET:
16670147868eSNuno Antunes if (nbracket-- == 0)
16680147868eSNuno Antunes return (EINVAL);
16690147868eSNuno Antunes break;
16700147868eSNuno Antunes case T_RBRACE:
16710147868eSNuno Antunes if (nbrace-- == 0)
16720147868eSNuno Antunes return (EINVAL);
16730147868eSNuno Antunes break;
16740147868eSNuno Antunes case T_EOF:
16750147868eSNuno Antunes return (EINVAL);
16760147868eSNuno Antunes default:
16770147868eSNuno Antunes break;
16780147868eSNuno Antunes }
16790147868eSNuno Antunes off += len;
16800147868eSNuno Antunes } while (nbracket > 0 || nbrace > 0);
16810147868eSNuno Antunes *lenp = off - off0;
16820147868eSNuno Antunes return (0);
16830147868eSNuno Antunes }
16840147868eSNuno Antunes
16850147868eSNuno Antunes /*
16860147868eSNuno Antunes * Find the next token in the string, starting at offset *startp.
16870147868eSNuno Antunes * Returns the token type, with *startp pointing to the first char
16880147868eSNuno Antunes * and *lenp the length.
16890147868eSNuno Antunes */
16900147868eSNuno Antunes enum ng_parse_token
ng_parse_get_token(const char * s,int * startp,int * lenp)16910147868eSNuno Antunes ng_parse_get_token(const char *s, int *startp, int *lenp)
16920147868eSNuno Antunes {
16930147868eSNuno Antunes char *t;
16940147868eSNuno Antunes int i;
16950147868eSNuno Antunes
16960147868eSNuno Antunes while (isspace(s[*startp]))
16970147868eSNuno Antunes (*startp)++;
16980147868eSNuno Antunes switch (s[*startp]) {
16990147868eSNuno Antunes case '\0':
17000147868eSNuno Antunes *lenp = 0;
17010147868eSNuno Antunes return T_EOF;
17020147868eSNuno Antunes case '{':
17030147868eSNuno Antunes *lenp = 1;
17040147868eSNuno Antunes return T_LBRACE;
17050147868eSNuno Antunes case '}':
17060147868eSNuno Antunes *lenp = 1;
17070147868eSNuno Antunes return T_RBRACE;
17080147868eSNuno Antunes case '[':
17090147868eSNuno Antunes *lenp = 1;
17100147868eSNuno Antunes return T_LBRACKET;
17110147868eSNuno Antunes case ']':
17120147868eSNuno Antunes *lenp = 1;
17130147868eSNuno Antunes return T_RBRACKET;
17140147868eSNuno Antunes case '=':
17150147868eSNuno Antunes *lenp = 1;
17160147868eSNuno Antunes return T_EQUALS;
17170147868eSNuno Antunes case '"':
17180147868eSNuno Antunes if ((t = ng_get_string_token(s, startp, lenp, NULL)) == NULL)
17190147868eSNuno Antunes return T_ERROR;
17200147868eSNuno Antunes kfree(t, M_NETGRAPH_PARSE);
17210147868eSNuno Antunes return T_STRING;
17220147868eSNuno Antunes default:
17230147868eSNuno Antunes for (i = *startp + 1; s[i] != '\0' && !isspace(s[i])
17240147868eSNuno Antunes && s[i] != '{' && s[i] != '}' && s[i] != '['
17250147868eSNuno Antunes && s[i] != ']' && s[i] != '=' && s[i] != '"'; i++)
17260147868eSNuno Antunes ;
17270147868eSNuno Antunes *lenp = i - *startp;
17280147868eSNuno Antunes return T_WORD;
17290147868eSNuno Antunes }
17300147868eSNuno Antunes }
17310147868eSNuno Antunes
17320147868eSNuno Antunes /*
17330147868eSNuno Antunes * Get a string token, which must be enclosed in double quotes.
17340147868eSNuno Antunes * The normal C backslash escapes are recognized.
17350147868eSNuno Antunes */
17360147868eSNuno Antunes char *
ng_get_string_token(const char * s,int * startp,int * lenp,int * slenp)17370147868eSNuno Antunes ng_get_string_token(const char *s, int *startp, int *lenp, int *slenp)
17380147868eSNuno Antunes {
17390147868eSNuno Antunes char *cbuf, *p;
17400147868eSNuno Antunes int start, off;
17410147868eSNuno Antunes int slen;
17420147868eSNuno Antunes
17430147868eSNuno Antunes while (isspace(s[*startp]))
17440147868eSNuno Antunes (*startp)++;
17450147868eSNuno Antunes start = *startp;
17460147868eSNuno Antunes if (s[*startp] != '"')
17470147868eSNuno Antunes return (NULL);
17480147868eSNuno Antunes cbuf = kmalloc(strlen(s + start), M_NETGRAPH_PARSE,
17490147868eSNuno Antunes M_WAITOK | M_NULLOK);
17500147868eSNuno Antunes if (cbuf == NULL)
17510147868eSNuno Antunes return (NULL);
17520147868eSNuno Antunes strcpy(cbuf, s + start + 1);
17530147868eSNuno Antunes for (slen = 0, off = 1, p = cbuf; *p != '\0'; slen++, off++, p++) {
17540147868eSNuno Antunes if (*p == '"') {
17550147868eSNuno Antunes *p = '\0';
17560147868eSNuno Antunes *lenp = off + 1;
17570147868eSNuno Antunes if (slenp != NULL)
17580147868eSNuno Antunes *slenp = slen;
17590147868eSNuno Antunes return (cbuf);
17600147868eSNuno Antunes } else if (p[0] == '\\' && p[1] != '\0') {
17610147868eSNuno Antunes int x, k;
17620147868eSNuno Antunes char *v;
17630147868eSNuno Antunes
17640147868eSNuno Antunes strcpy(p, p + 1);
17650147868eSNuno Antunes v = p;
17660147868eSNuno Antunes switch (*p) {
17670147868eSNuno Antunes case 't':
17680147868eSNuno Antunes *v = '\t';
17690147868eSNuno Antunes off++;
17700147868eSNuno Antunes continue;
17710147868eSNuno Antunes case 'n':
17720147868eSNuno Antunes *v = '\n';
17730147868eSNuno Antunes off++;
17740147868eSNuno Antunes continue;
17750147868eSNuno Antunes case 'r':
17760147868eSNuno Antunes *v = '\r';
17770147868eSNuno Antunes off++;
17780147868eSNuno Antunes continue;
17790147868eSNuno Antunes case 'v':
17800147868eSNuno Antunes *v = '\v';
17810147868eSNuno Antunes off++;
17820147868eSNuno Antunes continue;
17830147868eSNuno Antunes case 'f':
17840147868eSNuno Antunes *v = '\f';
17850147868eSNuno Antunes off++;
17860147868eSNuno Antunes continue;
17870147868eSNuno Antunes case '"':
17880147868eSNuno Antunes *v = '"';
17890147868eSNuno Antunes off++;
17900147868eSNuno Antunes continue;
17910147868eSNuno Antunes case '0': case '1': case '2': case '3':
17920147868eSNuno Antunes case '4': case '5': case '6': case '7':
17930147868eSNuno Antunes for (x = k = 0;
17940147868eSNuno Antunes k < 3 && *v >= '0' && *v <= '7'; v++) {
17950147868eSNuno Antunes x = (x << 3) + (*v - '0');
17960147868eSNuno Antunes off++;
17970147868eSNuno Antunes }
17980147868eSNuno Antunes *--v = (char)x;
17990147868eSNuno Antunes break;
18000147868eSNuno Antunes case 'x':
18010147868eSNuno Antunes for (v++, x = k = 0;
18020147868eSNuno Antunes k < 2 && isxdigit(*v); v++) {
18030147868eSNuno Antunes x = (x << 4) + (isdigit(*v) ?
18040147868eSNuno Antunes (*v - '0') :
18050147868eSNuno Antunes (tolower(*v) - 'a' + 10));
18060147868eSNuno Antunes off++;
18070147868eSNuno Antunes }
18080147868eSNuno Antunes *--v = (char)x;
18090147868eSNuno Antunes break;
18100147868eSNuno Antunes default:
18110147868eSNuno Antunes continue;
18120147868eSNuno Antunes }
18130147868eSNuno Antunes strcpy(p, v);
18140147868eSNuno Antunes }
18150147868eSNuno Antunes }
18160147868eSNuno Antunes kfree(cbuf, M_NETGRAPH_PARSE);
18170147868eSNuno Antunes return (NULL); /* no closing quote */
18180147868eSNuno Antunes }
18190147868eSNuno Antunes
18200147868eSNuno Antunes /*
18210147868eSNuno Antunes * Encode a string so it can be safely put in double quotes.
18220147868eSNuno Antunes * Caller must free the result. Exactly "slen" characters
18230147868eSNuno Antunes * are encoded.
18240147868eSNuno Antunes */
18250147868eSNuno Antunes char *
ng_encode_string(const char * raw,int slen)18260147868eSNuno Antunes ng_encode_string(const char *raw, int slen)
18270147868eSNuno Antunes {
18280147868eSNuno Antunes char *cbuf;
18290147868eSNuno Antunes int off = 0;
18300147868eSNuno Antunes int i;
18310147868eSNuno Antunes
18320147868eSNuno Antunes cbuf = kmalloc(strlen(raw) * 4 + 3, M_NETGRAPH_PARSE,
18330147868eSNuno Antunes M_WAITOK | M_NULLOK);
18340147868eSNuno Antunes if (cbuf == NULL)
18350147868eSNuno Antunes return (NULL);
18360147868eSNuno Antunes cbuf[off++] = '"';
18370147868eSNuno Antunes for (i = 0; i < slen; i++, raw++) {
18380147868eSNuno Antunes switch (*raw) {
18390147868eSNuno Antunes case '\t':
18400147868eSNuno Antunes cbuf[off++] = '\\';
18410147868eSNuno Antunes cbuf[off++] = 't';
18420147868eSNuno Antunes break;
18430147868eSNuno Antunes case '\f':
18440147868eSNuno Antunes cbuf[off++] = '\\';
18450147868eSNuno Antunes cbuf[off++] = 'f';
18460147868eSNuno Antunes break;
18470147868eSNuno Antunes case '\n':
18480147868eSNuno Antunes cbuf[off++] = '\\';
18490147868eSNuno Antunes cbuf[off++] = 'n';
18500147868eSNuno Antunes break;
18510147868eSNuno Antunes case '\r':
18520147868eSNuno Antunes cbuf[off++] = '\\';
18530147868eSNuno Antunes cbuf[off++] = 'r';
18540147868eSNuno Antunes break;
18550147868eSNuno Antunes case '\v':
18560147868eSNuno Antunes cbuf[off++] = '\\';
18570147868eSNuno Antunes cbuf[off++] = 'v';
18580147868eSNuno Antunes break;
18590147868eSNuno Antunes case '"':
18600147868eSNuno Antunes case '\\':
18610147868eSNuno Antunes cbuf[off++] = '\\';
18620147868eSNuno Antunes cbuf[off++] = *raw;
18630147868eSNuno Antunes break;
18640147868eSNuno Antunes default:
18650147868eSNuno Antunes if (*raw < 0x20 || *raw > 0x7e) {
1866a62226e4SSascha Wildner off += ksprintf(cbuf + off,
18670147868eSNuno Antunes "\\x%02x", (u_char)*raw);
18680147868eSNuno Antunes break;
18690147868eSNuno Antunes }
18700147868eSNuno Antunes cbuf[off++] = *raw;
18710147868eSNuno Antunes break;
18720147868eSNuno Antunes }
18730147868eSNuno Antunes }
18740147868eSNuno Antunes cbuf[off++] = '"';
18750147868eSNuno Antunes cbuf[off] = '\0';
18760147868eSNuno Antunes return (cbuf);
18770147868eSNuno Antunes }
18780147868eSNuno Antunes
18790147868eSNuno Antunes /************************************************************************
18800147868eSNuno Antunes VIRTUAL METHOD LOOKUP
18810147868eSNuno Antunes ************************************************************************/
18820147868eSNuno Antunes
18830147868eSNuno Antunes static ng_parse_t *
ng_get_parse_method(const struct ng_parse_type * t)18840147868eSNuno Antunes ng_get_parse_method(const struct ng_parse_type *t)
18850147868eSNuno Antunes {
18860147868eSNuno Antunes while (t != NULL && t->parse == NULL)
18870147868eSNuno Antunes t = t->supertype;
18880147868eSNuno Antunes return (t ? t->parse : NULL);
18890147868eSNuno Antunes }
18900147868eSNuno Antunes
18910147868eSNuno Antunes static ng_unparse_t *
ng_get_unparse_method(const struct ng_parse_type * t)18920147868eSNuno Antunes ng_get_unparse_method(const struct ng_parse_type *t)
18930147868eSNuno Antunes {
18940147868eSNuno Antunes while (t != NULL && t->unparse == NULL)
18950147868eSNuno Antunes t = t->supertype;
18960147868eSNuno Antunes return (t ? t->unparse : NULL);
18970147868eSNuno Antunes }
18980147868eSNuno Antunes
18990147868eSNuno Antunes static ng_getDefault_t *
ng_get_getDefault_method(const struct ng_parse_type * t)19000147868eSNuno Antunes ng_get_getDefault_method(const struct ng_parse_type *t)
19010147868eSNuno Antunes {
19020147868eSNuno Antunes while (t != NULL && t->getDefault == NULL)
19030147868eSNuno Antunes t = t->supertype;
19040147868eSNuno Antunes return (t ? t->getDefault : NULL);
19050147868eSNuno Antunes }
19060147868eSNuno Antunes
19070147868eSNuno Antunes static ng_getAlign_t *
ng_get_getAlign_method(const struct ng_parse_type * t)19080147868eSNuno Antunes ng_get_getAlign_method(const struct ng_parse_type *t)
19090147868eSNuno Antunes {
19100147868eSNuno Antunes while (t != NULL && t->getAlign == NULL)
19110147868eSNuno Antunes t = t->supertype;
19120147868eSNuno Antunes return (t ? t->getAlign : NULL);
19130147868eSNuno Antunes }
19140147868eSNuno Antunes
1915