ng_parse.c revision 123600
153913Sarchie 253913Sarchie/* 353913Sarchie * ng_parse.c 453913Sarchie * 553913Sarchie * Copyright (c) 1999 Whistle Communications, Inc. 653913Sarchie * All rights reserved. 753913Sarchie * 853913Sarchie * Subject to the following obligations and disclaimer of warranty, use and 953913Sarchie * redistribution of this software, in source or object code forms, with or 1053913Sarchie * without modifications are expressly permitted by Whistle Communications; 1153913Sarchie * provided, however, that: 1253913Sarchie * 1. Any and all reproductions of the source or object code must include the 1353913Sarchie * copyright notice above and the following disclaimer of warranties; and 1453913Sarchie * 2. No rights are granted, in any manner or form, to use Whistle 1553913Sarchie * Communications, Inc. trademarks, including the mark "WHISTLE 1653913Sarchie * COMMUNICATIONS" on advertising, endorsements, or otherwise except as 1753913Sarchie * such appears in the above copyright notice or in the software. 1853913Sarchie * 1953913Sarchie * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND 2053913Sarchie * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO 2153913Sarchie * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, 2253913Sarchie * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF 2353913Sarchie * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 2453913Sarchie * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY 2553913Sarchie * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS 2653913Sarchie * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. 2753913Sarchie * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES 2853913Sarchie * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING 2953913Sarchie * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 3053913Sarchie * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR 3153913Sarchie * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY 3253913Sarchie * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3353913Sarchie * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 3453913Sarchie * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY 3553913Sarchie * OF SUCH DAMAGE. 3653913Sarchie * 3767506Sjulian * Author: Archie Cobbs <archie@freebsd.org> 3853913Sarchie * 3953913Sarchie * $Whistle: ng_parse.c,v 1.3 1999/11/29 01:43:48 archie Exp $ 4053913Sarchie * $FreeBSD: head/sys/netgraph/ng_parse.c 123600 2003-12-17 12:40:34Z ru $ 4153913Sarchie */ 4253913Sarchie 4353913Sarchie#include <sys/types.h> 4453913Sarchie#include <sys/param.h> 4553913Sarchie#include <sys/systm.h> 4670870Sjulian#include <sys/kernel.h> 4753913Sarchie#include <sys/errno.h> 4853913Sarchie#include <sys/malloc.h> 4953913Sarchie#include <sys/ctype.h> 5053913Sarchie 51123600Sru#include <net/ethernet.h> 52123600Sru 5353913Sarchie#include <netinet/in.h> 5453913Sarchie 5553913Sarchie#include <netgraph/ng_message.h> 5653913Sarchie#include <netgraph/netgraph.h> 5753913Sarchie#include <netgraph/ng_parse.h> 5853913Sarchie 5970870Sjulian#ifdef NG_SEPARATE_MALLOC 6070870SjulianMALLOC_DEFINE(M_NETGRAPH_PARSE, "netgraph_parse", "netgraph parse info"); 6170870Sjulian#else 6270870Sjulian#define M_NETGRAPH_PARSE M_NETGRAPH 6370870Sjulian#endif 6470870Sjulian 6553913Sarchie/* Compute alignment for primitive integral types */ 6653913Sarchiestruct int16_temp { 6753913Sarchie char x; 6853913Sarchie int16_t y; 6953913Sarchie}; 7053913Sarchie 7153913Sarchiestruct int32_temp { 7253913Sarchie char x; 7353913Sarchie int32_t y; 7453913Sarchie}; 7553913Sarchie 7653913Sarchiestruct int64_temp { 7753913Sarchie char x; 7853913Sarchie int64_t y; 7953913Sarchie}; 8053913Sarchie 8153913Sarchie#define INT8_ALIGNMENT 1 8253913Sarchie#define INT16_ALIGNMENT ((int)&((struct int16_temp *)0)->y) 8353913Sarchie#define INT32_ALIGNMENT ((int)&((struct int32_temp *)0)->y) 8453913Sarchie#define INT64_ALIGNMENT ((int)&((struct int64_temp *)0)->y) 8553913Sarchie 8664505Sarchie/* Output format for integral types */ 8764505Sarchie#define INT_UNSIGNED 0 8864505Sarchie#define INT_SIGNED 1 8964505Sarchie#define INT_HEX 2 9064505Sarchie 9153913Sarchie/* Type of composite object: struct, array, or fixedarray */ 9253913Sarchieenum comptype { 9353913Sarchie CT_STRUCT, 9453913Sarchie CT_ARRAY, 9553913Sarchie CT_FIXEDARRAY, 9653913Sarchie}; 9753913Sarchie 9853913Sarchie/* Composite types helper functions */ 9953913Sarchiestatic int ng_parse_composite(const struct ng_parse_type *type, 10053913Sarchie const char *s, int *off, const u_char *start, 10153913Sarchie u_char *const buf, int *buflen, enum comptype ctype); 10253913Sarchiestatic int ng_unparse_composite(const struct ng_parse_type *type, 10353913Sarchie const u_char *data, int *off, char *cbuf, int cbuflen, 10453913Sarchie enum comptype ctype); 10553913Sarchiestatic int ng_get_composite_elem_default(const struct ng_parse_type *type, 10653913Sarchie int index, const u_char *start, u_char *buf, 10753913Sarchie int *buflen, enum comptype ctype); 10853913Sarchiestatic int ng_get_composite_len(const struct ng_parse_type *type, 10953913Sarchie const u_char *start, const u_char *buf, 11053913Sarchie enum comptype ctype); 11153913Sarchiestatic const struct ng_parse_type *ng_get_composite_etype(const struct 11253913Sarchie ng_parse_type *type, int index, enum comptype ctype); 11353913Sarchiestatic int ng_parse_get_elem_pad(const struct ng_parse_type *type, 11453913Sarchie int index, enum comptype ctype, int posn); 11553913Sarchie 11653913Sarchie/* Parsing helper functions */ 11753913Sarchiestatic int ng_parse_skip_value(const char *s, int off, int *lenp); 11853913Sarchie 11953913Sarchie/* Poor man's virtual method calls */ 12053913Sarchie#define METHOD(t,m) (ng_get_ ## m ## _method(t)) 12153913Sarchie#define INVOKE(t,m) (*METHOD(t,m)) 12253913Sarchie 12353913Sarchiestatic ng_parse_t *ng_get_parse_method(const struct ng_parse_type *t); 12453913Sarchiestatic ng_unparse_t *ng_get_unparse_method(const struct ng_parse_type *t); 12553913Sarchiestatic ng_getDefault_t *ng_get_getDefault_method(const 12653913Sarchie struct ng_parse_type *t); 12753913Sarchiestatic ng_getAlign_t *ng_get_getAlign_method(const struct ng_parse_type *t); 12853913Sarchie 12953913Sarchie#define ALIGNMENT(t) (METHOD(t, getAlign) == NULL ? \ 13053913Sarchie 0 : INVOKE(t, getAlign)(t)) 13153913Sarchie 13253913Sarchie/* For converting binary to string */ 13353913Sarchie#define NG_PARSE_APPEND(fmt, args...) \ 13453913Sarchie do { \ 13553913Sarchie int len; \ 13653913Sarchie \ 13753913Sarchie len = snprintf((cbuf), (cbuflen), \ 13853913Sarchie fmt , ## args); \ 13953913Sarchie if (len >= (cbuflen)) \ 14053913Sarchie return (ERANGE); \ 14153913Sarchie (cbuf) += len; \ 14253913Sarchie (cbuflen) -= len; \ 14353913Sarchie } while (0) 14453913Sarchie 14553913Sarchie/************************************************************************ 14653913Sarchie PUBLIC FUNCTIONS 14753913Sarchie ************************************************************************/ 14853913Sarchie 14953913Sarchie/* 15053913Sarchie * Convert an ASCII string to binary according to the supplied type descriptor 15153913Sarchie */ 15253913Sarchieint 15353913Sarchieng_parse(const struct ng_parse_type *type, 15453913Sarchie const char *string, int *off, u_char *buf, int *buflen) 15553913Sarchie{ 15653913Sarchie return INVOKE(type, parse)(type, string, off, buf, buf, buflen); 15753913Sarchie} 15853913Sarchie 15953913Sarchie/* 16053913Sarchie * Convert binary to an ASCII string according to the supplied type descriptor 16153913Sarchie */ 16253913Sarchieint 16353913Sarchieng_unparse(const struct ng_parse_type *type, 16453913Sarchie const u_char *data, char *cbuf, int cbuflen) 16553913Sarchie{ 16653913Sarchie int off = 0; 16753913Sarchie 16853913Sarchie return INVOKE(type, unparse)(type, data, &off, cbuf, cbuflen); 16953913Sarchie} 17053913Sarchie 17153913Sarchie/* 17253913Sarchie * Fill in the default value according to the supplied type descriptor 17353913Sarchie */ 17453913Sarchieint 17553913Sarchieng_parse_getDefault(const struct ng_parse_type *type, u_char *buf, int *buflen) 17653913Sarchie{ 17753913Sarchie ng_getDefault_t *const func = METHOD(type, getDefault); 17853913Sarchie 17953913Sarchie if (func == NULL) 18053913Sarchie return (EOPNOTSUPP); 18153913Sarchie return (*func)(type, buf, buf, buflen); 18253913Sarchie} 18353913Sarchie 18453913Sarchie 18553913Sarchie/************************************************************************ 18653913Sarchie STRUCTURE TYPE 18753913Sarchie ************************************************************************/ 18853913Sarchie 18953913Sarchiestatic int 19053913Sarchieng_struct_parse(const struct ng_parse_type *type, 19153913Sarchie const char *s, int *off, const u_char *const start, 19253913Sarchie u_char *const buf, int *buflen) 19353913Sarchie{ 19453913Sarchie return ng_parse_composite(type, s, off, start, buf, buflen, CT_STRUCT); 19553913Sarchie} 19653913Sarchie 19753913Sarchiestatic int 19853913Sarchieng_struct_unparse(const struct ng_parse_type *type, 19953913Sarchie const u_char *data, int *off, char *cbuf, int cbuflen) 20053913Sarchie{ 20153913Sarchie return ng_unparse_composite(type, data, off, cbuf, cbuflen, CT_STRUCT); 20253913Sarchie} 20353913Sarchie 20453913Sarchiestatic int 20553913Sarchieng_struct_getDefault(const struct ng_parse_type *type, 20653913Sarchie const u_char *const start, u_char *buf, int *buflen) 20753913Sarchie{ 20853913Sarchie int off = 0; 20953913Sarchie 21053913Sarchie return ng_parse_composite(type, 21153913Sarchie "{}", &off, start, buf, buflen, CT_STRUCT); 21253913Sarchie} 21353913Sarchie 21453913Sarchiestatic int 21553913Sarchieng_struct_getAlign(const struct ng_parse_type *type) 21653913Sarchie{ 21753913Sarchie const struct ng_parse_struct_field *field; 21853913Sarchie int align = 0; 21953913Sarchie 22097685Sarchie for (field = type->info; field->name != NULL; field++) { 22153913Sarchie int falign = ALIGNMENT(field->type); 22253913Sarchie 22353913Sarchie if (falign > align) 22453913Sarchie align = falign; 22553913Sarchie } 22653913Sarchie return align; 22753913Sarchie} 22853913Sarchie 22953913Sarchieconst struct ng_parse_type ng_parse_struct_type = { 23053913Sarchie NULL, 23153913Sarchie NULL, 23253913Sarchie NULL, 23353913Sarchie ng_struct_parse, 23453913Sarchie ng_struct_unparse, 23553913Sarchie ng_struct_getDefault, 23653913Sarchie ng_struct_getAlign 23753913Sarchie}; 23853913Sarchie 23953913Sarchie/************************************************************************ 24053913Sarchie FIXED LENGTH ARRAY TYPE 24153913Sarchie ************************************************************************/ 24253913Sarchie 24353913Sarchiestatic int 24453913Sarchieng_fixedarray_parse(const struct ng_parse_type *type, 24553913Sarchie const char *s, int *off, const u_char *const start, 24653913Sarchie u_char *const buf, int *buflen) 24753913Sarchie{ 24853913Sarchie return ng_parse_composite(type, 24953913Sarchie s, off, start, buf, buflen, CT_FIXEDARRAY); 25053913Sarchie} 25153913Sarchie 25253913Sarchiestatic int 25353913Sarchieng_fixedarray_unparse(const struct ng_parse_type *type, 25453913Sarchie const u_char *data, int *off, char *cbuf, int cbuflen) 25553913Sarchie{ 25653913Sarchie return ng_unparse_composite(type, 25753913Sarchie data, off, cbuf, cbuflen, CT_FIXEDARRAY); 25853913Sarchie} 25953913Sarchie 26053913Sarchiestatic int 26153913Sarchieng_fixedarray_getDefault(const struct ng_parse_type *type, 26253913Sarchie const u_char *const start, u_char *buf, int *buflen) 26353913Sarchie{ 26453913Sarchie int off = 0; 26553913Sarchie 26653913Sarchie return ng_parse_composite(type, 26753913Sarchie "[]", &off, start, buf, buflen, CT_FIXEDARRAY); 26853913Sarchie} 26953913Sarchie 27053913Sarchiestatic int 27153913Sarchieng_fixedarray_getAlign(const struct ng_parse_type *type) 27253913Sarchie{ 27353913Sarchie const struct ng_parse_fixedarray_info *fi = type->info; 27453913Sarchie 27553913Sarchie return ALIGNMENT(fi->elementType); 27653913Sarchie} 27753913Sarchie 27853913Sarchieconst struct ng_parse_type ng_parse_fixedarray_type = { 27953913Sarchie NULL, 28053913Sarchie NULL, 28153913Sarchie NULL, 28253913Sarchie ng_fixedarray_parse, 28353913Sarchie ng_fixedarray_unparse, 28453913Sarchie ng_fixedarray_getDefault, 28553913Sarchie ng_fixedarray_getAlign 28653913Sarchie}; 28753913Sarchie 28853913Sarchie/************************************************************************ 28953913Sarchie VARIABLE LENGTH ARRAY TYPE 29053913Sarchie ************************************************************************/ 29153913Sarchie 29253913Sarchiestatic int 29353913Sarchieng_array_parse(const struct ng_parse_type *type, 29453913Sarchie const char *s, int *off, const u_char *const start, 29553913Sarchie u_char *const buf, int *buflen) 29653913Sarchie{ 29753913Sarchie return ng_parse_composite(type, s, off, start, buf, buflen, CT_ARRAY); 29853913Sarchie} 29953913Sarchie 30053913Sarchiestatic int 30153913Sarchieng_array_unparse(const struct ng_parse_type *type, 30253913Sarchie const u_char *data, int *off, char *cbuf, int cbuflen) 30353913Sarchie{ 30453913Sarchie return ng_unparse_composite(type, data, off, cbuf, cbuflen, CT_ARRAY); 30553913Sarchie} 30653913Sarchie 30753913Sarchiestatic int 30853913Sarchieng_array_getDefault(const struct ng_parse_type *type, 30953913Sarchie const u_char *const start, u_char *buf, int *buflen) 31053913Sarchie{ 31153913Sarchie int off = 0; 31253913Sarchie 31353913Sarchie return ng_parse_composite(type, 31453913Sarchie "[]", &off, start, buf, buflen, CT_ARRAY); 31553913Sarchie} 31653913Sarchie 31753913Sarchiestatic int 31853913Sarchieng_array_getAlign(const struct ng_parse_type *type) 31953913Sarchie{ 32053913Sarchie const struct ng_parse_array_info *ai = type->info; 32153913Sarchie 32253913Sarchie return ALIGNMENT(ai->elementType); 32353913Sarchie} 32453913Sarchie 32553913Sarchieconst struct ng_parse_type ng_parse_array_type = { 32653913Sarchie NULL, 32753913Sarchie NULL, 32853913Sarchie NULL, 32953913Sarchie ng_array_parse, 33053913Sarchie ng_array_unparse, 33153913Sarchie ng_array_getDefault, 33253913Sarchie ng_array_getAlign 33353913Sarchie}; 33453913Sarchie 33553913Sarchie/************************************************************************ 33653913Sarchie INT8 TYPE 33753913Sarchie ************************************************************************/ 33853913Sarchie 33953913Sarchiestatic int 34053913Sarchieng_int8_parse(const struct ng_parse_type *type, 34153913Sarchie const char *s, int *off, const u_char *const start, 34253913Sarchie u_char *const buf, int *buflen) 34353913Sarchie{ 34453913Sarchie long val; 34553913Sarchie int8_t val8; 34653913Sarchie char *eptr; 34753913Sarchie 34853913Sarchie val = strtol(s + *off, &eptr, 0); 34976860Sjdp if (val < (int8_t)0x80 || val > (u_int8_t)0xff || eptr == s + *off) 35053913Sarchie return (EINVAL); 35153913Sarchie *off = eptr - s; 35253913Sarchie val8 = (int8_t)val; 35353913Sarchie bcopy(&val8, buf, sizeof(int8_t)); 35453913Sarchie *buflen = sizeof(int8_t); 35553913Sarchie return (0); 35653913Sarchie} 35753913Sarchie 35853913Sarchiestatic int 35953913Sarchieng_int8_unparse(const struct ng_parse_type *type, 36053913Sarchie const u_char *data, int *off, char *cbuf, int cbuflen) 36153913Sarchie{ 36264505Sarchie const char *fmt; 36364505Sarchie int fval; 36453913Sarchie int8_t val; 36553913Sarchie 36653913Sarchie bcopy(data + *off, &val, sizeof(int8_t)); 367106665Sjhb switch ((intptr_t)type->info) { 36864505Sarchie case INT_SIGNED: 36964505Sarchie fmt = "%d"; 37064505Sarchie fval = val; 37164505Sarchie break; 37264505Sarchie case INT_UNSIGNED: 37364505Sarchie fmt = "%u"; 37464505Sarchie fval = (u_int8_t)val; 37564505Sarchie break; 37664505Sarchie case INT_HEX: 37764505Sarchie fmt = "0x%x"; 37864505Sarchie fval = (u_int8_t)val; 37964505Sarchie break; 38064505Sarchie default: 38187599Sobrien panic("%s: unknown type", __func__); 38283366Sjulian#ifdef RESTARTABLE_PANICS 38383366Sjulian return(0); 38483366Sjulian#endif 38564505Sarchie } 38664505Sarchie NG_PARSE_APPEND(fmt, fval); 38753913Sarchie *off += sizeof(int8_t); 38853913Sarchie return (0); 38953913Sarchie} 39053913Sarchie 39153913Sarchiestatic int 39253913Sarchieng_int8_getDefault(const struct ng_parse_type *type, 39353913Sarchie const u_char *const start, u_char *buf, int *buflen) 39453913Sarchie{ 39553913Sarchie int8_t val; 39653913Sarchie 39753913Sarchie if (*buflen < sizeof(int8_t)) 39853913Sarchie return (ERANGE); 39953913Sarchie val = 0; 40053913Sarchie bcopy(&val, buf, sizeof(int8_t)); 40153913Sarchie *buflen = sizeof(int8_t); 40253913Sarchie return (0); 40353913Sarchie} 40453913Sarchie 40553913Sarchiestatic int 40653913Sarchieng_int8_getAlign(const struct ng_parse_type *type) 40753913Sarchie{ 40853913Sarchie return INT8_ALIGNMENT; 40953913Sarchie} 41053913Sarchie 41153913Sarchieconst struct ng_parse_type ng_parse_int8_type = { 41253913Sarchie NULL, 41364505Sarchie (void *)INT_SIGNED, 41453913Sarchie NULL, 41553913Sarchie ng_int8_parse, 41653913Sarchie ng_int8_unparse, 41753913Sarchie ng_int8_getDefault, 41853913Sarchie ng_int8_getAlign 41953913Sarchie}; 42053913Sarchie 42164505Sarchieconst struct ng_parse_type ng_parse_uint8_type = { 42264505Sarchie &ng_parse_int8_type, 42364505Sarchie (void *)INT_UNSIGNED 42464505Sarchie}; 42564505Sarchie 42664505Sarchieconst struct ng_parse_type ng_parse_hint8_type = { 42764505Sarchie &ng_parse_int8_type, 42864505Sarchie (void *)INT_HEX 42964505Sarchie}; 43064505Sarchie 43153913Sarchie/************************************************************************ 43253913Sarchie INT16 TYPE 43353913Sarchie ************************************************************************/ 43453913Sarchie 43553913Sarchiestatic int 43653913Sarchieng_int16_parse(const struct ng_parse_type *type, 43753913Sarchie const char *s, int *off, const u_char *const start, 43853913Sarchie u_char *const buf, int *buflen) 43953913Sarchie{ 44053913Sarchie long val; 44153913Sarchie int16_t val16; 44253913Sarchie char *eptr; 44353913Sarchie 44453913Sarchie val = strtol(s + *off, &eptr, 0); 44576860Sjdp if (val < (int16_t)0x8000 44676860Sjdp || val > (u_int16_t)0xffff || eptr == s + *off) 44753913Sarchie return (EINVAL); 44853913Sarchie *off = eptr - s; 44953913Sarchie val16 = (int16_t)val; 45053913Sarchie bcopy(&val16, buf, sizeof(int16_t)); 45153913Sarchie *buflen = sizeof(int16_t); 45253913Sarchie return (0); 45353913Sarchie} 45453913Sarchie 45553913Sarchiestatic int 45653913Sarchieng_int16_unparse(const struct ng_parse_type *type, 45753913Sarchie const u_char *data, int *off, char *cbuf, int cbuflen) 45853913Sarchie{ 45964505Sarchie const char *fmt; 46064505Sarchie int fval; 46153913Sarchie int16_t val; 46253913Sarchie 46353913Sarchie bcopy(data + *off, &val, sizeof(int16_t)); 464106665Sjhb switch ((intptr_t)type->info) { 46564505Sarchie case INT_SIGNED: 46664505Sarchie fmt = "%d"; 46764505Sarchie fval = val; 46864505Sarchie break; 46964505Sarchie case INT_UNSIGNED: 47064505Sarchie fmt = "%u"; 47164505Sarchie fval = (u_int16_t)val; 47264505Sarchie break; 47364505Sarchie case INT_HEX: 47464505Sarchie fmt = "0x%x"; 47564505Sarchie fval = (u_int16_t)val; 47664505Sarchie break; 47764505Sarchie default: 47887599Sobrien panic("%s: unknown type", __func__); 47983366Sjulian#ifdef RESTARTABLE_PANICS 48083366Sjulian return(0); 48183366Sjulian#endif 48264505Sarchie } 48364505Sarchie NG_PARSE_APPEND(fmt, fval); 48453913Sarchie *off += sizeof(int16_t); 48553913Sarchie return (0); 48653913Sarchie} 48753913Sarchie 48853913Sarchiestatic int 48953913Sarchieng_int16_getDefault(const struct ng_parse_type *type, 49053913Sarchie const u_char *const start, u_char *buf, int *buflen) 49153913Sarchie{ 49253913Sarchie int16_t val; 49353913Sarchie 49453913Sarchie if (*buflen < sizeof(int16_t)) 49553913Sarchie return (ERANGE); 49653913Sarchie val = 0; 49753913Sarchie bcopy(&val, buf, sizeof(int16_t)); 49853913Sarchie *buflen = sizeof(int16_t); 49953913Sarchie return (0); 50053913Sarchie} 50153913Sarchie 50253913Sarchiestatic int 50353913Sarchieng_int16_getAlign(const struct ng_parse_type *type) 50453913Sarchie{ 50553913Sarchie return INT16_ALIGNMENT; 50653913Sarchie} 50753913Sarchie 50853913Sarchieconst struct ng_parse_type ng_parse_int16_type = { 50953913Sarchie NULL, 51064505Sarchie (void *)INT_SIGNED, 51153913Sarchie NULL, 51253913Sarchie ng_int16_parse, 51353913Sarchie ng_int16_unparse, 51453913Sarchie ng_int16_getDefault, 51553913Sarchie ng_int16_getAlign 51653913Sarchie}; 51753913Sarchie 51864505Sarchieconst struct ng_parse_type ng_parse_uint16_type = { 51964505Sarchie &ng_parse_int16_type, 52064505Sarchie (void *)INT_UNSIGNED 52164505Sarchie}; 52264505Sarchie 52364505Sarchieconst struct ng_parse_type ng_parse_hint16_type = { 52464505Sarchie &ng_parse_int16_type, 52564505Sarchie (void *)INT_HEX 52664505Sarchie}; 52764505Sarchie 52853913Sarchie/************************************************************************ 52953913Sarchie INT32 TYPE 53053913Sarchie ************************************************************************/ 53153913Sarchie 53253913Sarchiestatic int 53353913Sarchieng_int32_parse(const struct ng_parse_type *type, 53453913Sarchie const char *s, int *off, const u_char *const start, 53553913Sarchie u_char *const buf, int *buflen) 53653913Sarchie{ 53753913Sarchie long val; /* assumes long is at least 32 bits */ 53853913Sarchie int32_t val32; 53953913Sarchie char *eptr; 54053913Sarchie 54153913Sarchie val = strtol(s + *off, &eptr, 0); 54276860Sjdp if (val < (int32_t)0x80000000 54376860Sjdp || val > (u_int32_t)0xffffffff || eptr == s + *off) 54453913Sarchie return (EINVAL); 54553913Sarchie *off = eptr - s; 54653913Sarchie val32 = (int32_t)val; 54753913Sarchie bcopy(&val32, buf, sizeof(int32_t)); 54853913Sarchie *buflen = sizeof(int32_t); 54953913Sarchie return (0); 55053913Sarchie} 55153913Sarchie 55253913Sarchiestatic int 55353913Sarchieng_int32_unparse(const struct ng_parse_type *type, 55453913Sarchie const u_char *data, int *off, char *cbuf, int cbuflen) 55553913Sarchie{ 55664505Sarchie const char *fmt; 55764505Sarchie long fval; 55853913Sarchie int32_t val; 55953913Sarchie 56053913Sarchie bcopy(data + *off, &val, sizeof(int32_t)); 561106665Sjhb switch ((intptr_t)type->info) { 56264505Sarchie case INT_SIGNED: 56364505Sarchie fmt = "%ld"; 56464505Sarchie fval = val; 56564505Sarchie break; 56664505Sarchie case INT_UNSIGNED: 56764505Sarchie fmt = "%lu"; 56864505Sarchie fval = (u_int32_t)val; 56964505Sarchie break; 57064505Sarchie case INT_HEX: 57164505Sarchie fmt = "0x%lx"; 57264505Sarchie fval = (u_int32_t)val; 57364505Sarchie break; 57464505Sarchie default: 57587599Sobrien panic("%s: unknown type", __func__); 57683366Sjulian#ifdef RESTARTABLE_PANICS 57783366Sjulian return(0); 57883366Sjulian#endif 57964505Sarchie } 58064505Sarchie NG_PARSE_APPEND(fmt, fval); 58153913Sarchie *off += sizeof(int32_t); 58253913Sarchie return (0); 58353913Sarchie} 58453913Sarchie 58553913Sarchiestatic int 58653913Sarchieng_int32_getDefault(const struct ng_parse_type *type, 58753913Sarchie const u_char *const start, u_char *buf, int *buflen) 58853913Sarchie{ 58953913Sarchie int32_t val; 59053913Sarchie 59153913Sarchie if (*buflen < sizeof(int32_t)) 59253913Sarchie return (ERANGE); 59353913Sarchie val = 0; 59453913Sarchie bcopy(&val, buf, sizeof(int32_t)); 59553913Sarchie *buflen = sizeof(int32_t); 59653913Sarchie return (0); 59753913Sarchie} 59853913Sarchie 59953913Sarchiestatic int 60053913Sarchieng_int32_getAlign(const struct ng_parse_type *type) 60153913Sarchie{ 60253913Sarchie return INT32_ALIGNMENT; 60353913Sarchie} 60453913Sarchie 60553913Sarchieconst struct ng_parse_type ng_parse_int32_type = { 60653913Sarchie NULL, 60764505Sarchie (void *)INT_SIGNED, 60853913Sarchie NULL, 60953913Sarchie ng_int32_parse, 61053913Sarchie ng_int32_unparse, 61153913Sarchie ng_int32_getDefault, 61253913Sarchie ng_int32_getAlign 61353913Sarchie}; 61453913Sarchie 61564505Sarchieconst struct ng_parse_type ng_parse_uint32_type = { 61664505Sarchie &ng_parse_int32_type, 61764505Sarchie (void *)INT_UNSIGNED 61864505Sarchie}; 61964505Sarchie 62064505Sarchieconst struct ng_parse_type ng_parse_hint32_type = { 62164505Sarchie &ng_parse_int32_type, 62264505Sarchie (void *)INT_HEX 62364505Sarchie}; 62464505Sarchie 62553913Sarchie/************************************************************************ 62653913Sarchie INT64 TYPE 62753913Sarchie ************************************************************************/ 62853913Sarchie 62953913Sarchiestatic int 63053913Sarchieng_int64_parse(const struct ng_parse_type *type, 63153913Sarchie const char *s, int *off, const u_char *const start, 63253913Sarchie u_char *const buf, int *buflen) 63353913Sarchie{ 63453913Sarchie quad_t val; 63553913Sarchie int64_t val64; 63653913Sarchie char *eptr; 63753913Sarchie 63853913Sarchie val = strtoq(s + *off, &eptr, 0); 63953913Sarchie if (eptr == s + *off) 64053913Sarchie return (EINVAL); 64153913Sarchie *off = eptr - s; 64253913Sarchie val64 = (int64_t)val; 64353913Sarchie bcopy(&val64, buf, sizeof(int64_t)); 64453913Sarchie *buflen = sizeof(int64_t); 64553913Sarchie return (0); 64653913Sarchie} 64753913Sarchie 64853913Sarchiestatic int 64953913Sarchieng_int64_unparse(const struct ng_parse_type *type, 65053913Sarchie const u_char *data, int *off, char *cbuf, int cbuflen) 65153913Sarchie{ 65264505Sarchie const char *fmt; 65364505Sarchie long long fval; 65453913Sarchie int64_t val; 65553913Sarchie 65653913Sarchie bcopy(data + *off, &val, sizeof(int64_t)); 657106665Sjhb switch ((intptr_t)type->info) { 65864505Sarchie case INT_SIGNED: 65964505Sarchie fmt = "%lld"; 66064505Sarchie fval = val; 66164505Sarchie break; 66264505Sarchie case INT_UNSIGNED: 66364505Sarchie fmt = "%llu"; 66464505Sarchie fval = (u_int64_t)val; 66564505Sarchie break; 66664505Sarchie case INT_HEX: 66764505Sarchie fmt = "0x%llx"; 66864505Sarchie fval = (u_int64_t)val; 66964505Sarchie break; 67064505Sarchie default: 67187599Sobrien panic("%s: unknown type", __func__); 67283366Sjulian#ifdef RESTARTABLE_PANICS 67383366Sjulian return(0); 67483366Sjulian#endif 67564505Sarchie } 67664505Sarchie NG_PARSE_APPEND(fmt, fval); 67753913Sarchie *off += sizeof(int64_t); 67853913Sarchie return (0); 67953913Sarchie} 68053913Sarchie 68153913Sarchiestatic int 68253913Sarchieng_int64_getDefault(const struct ng_parse_type *type, 68353913Sarchie const u_char *const start, u_char *buf, int *buflen) 68453913Sarchie{ 68553913Sarchie int64_t val; 68653913Sarchie 68753913Sarchie if (*buflen < sizeof(int64_t)) 68853913Sarchie return (ERANGE); 68953913Sarchie val = 0; 69053913Sarchie bcopy(&val, buf, sizeof(int64_t)); 69153913Sarchie *buflen = sizeof(int64_t); 69253913Sarchie return (0); 69353913Sarchie} 69453913Sarchie 69553913Sarchiestatic int 69653913Sarchieng_int64_getAlign(const struct ng_parse_type *type) 69753913Sarchie{ 69853913Sarchie return INT64_ALIGNMENT; 69953913Sarchie} 70053913Sarchie 70153913Sarchieconst struct ng_parse_type ng_parse_int64_type = { 70253913Sarchie NULL, 70364505Sarchie (void *)INT_SIGNED, 70453913Sarchie NULL, 70553913Sarchie ng_int64_parse, 70653913Sarchie ng_int64_unparse, 70753913Sarchie ng_int64_getDefault, 70853913Sarchie ng_int64_getAlign 70953913Sarchie}; 71053913Sarchie 71164505Sarchieconst struct ng_parse_type ng_parse_uint64_type = { 71264505Sarchie &ng_parse_int64_type, 71364505Sarchie (void *)INT_UNSIGNED 71464505Sarchie}; 71564505Sarchie 71664505Sarchieconst struct ng_parse_type ng_parse_hint64_type = { 71764505Sarchie &ng_parse_int64_type, 71864505Sarchie (void *)INT_HEX 71964505Sarchie}; 72064505Sarchie 72153913Sarchie/************************************************************************ 72253913Sarchie STRING TYPE 72353913Sarchie ************************************************************************/ 72453913Sarchie 72553913Sarchiestatic int 72653913Sarchieng_string_parse(const struct ng_parse_type *type, 72753913Sarchie const char *s, int *off, const u_char *const start, 72853913Sarchie u_char *const buf, int *buflen) 72953913Sarchie{ 73053913Sarchie char *sval; 73153913Sarchie int len; 73268845Sbrian int slen; 73353913Sarchie 73468845Sbrian if ((sval = ng_get_string_token(s, off, &len, &slen)) == NULL) 73553913Sarchie return (EINVAL); 73653913Sarchie *off += len; 73768845Sbrian bcopy(sval, buf, slen + 1); 73870870Sjulian FREE(sval, M_NETGRAPH_PARSE); 73968845Sbrian *buflen = slen + 1; 74053913Sarchie return (0); 74153913Sarchie} 74253913Sarchie 74353913Sarchiestatic int 74453913Sarchieng_string_unparse(const struct ng_parse_type *type, 74553913Sarchie const u_char *data, int *off, char *cbuf, int cbuflen) 74653913Sarchie{ 74753913Sarchie const char *const raw = (const char *)data + *off; 74868845Sbrian char *const s = ng_encode_string(raw, strlen(raw)); 74953913Sarchie 75053913Sarchie if (s == NULL) 75153913Sarchie return (ENOMEM); 75253913Sarchie NG_PARSE_APPEND("%s", s); 75353913Sarchie *off += strlen(raw) + 1; 75470870Sjulian FREE(s, M_NETGRAPH_PARSE); 75553913Sarchie return (0); 75653913Sarchie} 75753913Sarchie 75853913Sarchiestatic int 75953913Sarchieng_string_getDefault(const struct ng_parse_type *type, 76053913Sarchie const u_char *const start, u_char *buf, int *buflen) 76153913Sarchie{ 76253913Sarchie 76353913Sarchie if (*buflen < 1) 76453913Sarchie return (ERANGE); 76553913Sarchie buf[0] = (u_char)'\0'; 76653913Sarchie *buflen = 1; 76753913Sarchie return (0); 76853913Sarchie} 76953913Sarchie 77053913Sarchieconst struct ng_parse_type ng_parse_string_type = { 77153913Sarchie NULL, 77253913Sarchie NULL, 77353913Sarchie NULL, 77453913Sarchie ng_string_parse, 77553913Sarchie ng_string_unparse, 77653913Sarchie ng_string_getDefault, 77753913Sarchie NULL 77853913Sarchie}; 77953913Sarchie 78053913Sarchie/************************************************************************ 78153913Sarchie FIXED BUFFER STRING TYPE 78253913Sarchie ************************************************************************/ 78353913Sarchie 78453913Sarchiestatic int 78553913Sarchieng_fixedstring_parse(const struct ng_parse_type *type, 78653913Sarchie const char *s, int *off, const u_char *const start, 78753913Sarchie u_char *const buf, int *buflen) 78853913Sarchie{ 78958011Sarchie const struct ng_parse_fixedstring_info *const fi = type->info; 79053913Sarchie char *sval; 79153913Sarchie int len; 79268845Sbrian int slen; 79353913Sarchie 79468845Sbrian if ((sval = ng_get_string_token(s, off, &len, &slen)) == NULL) 79553913Sarchie return (EINVAL); 79668845Sbrian if (slen + 1 > fi->bufSize) 79753913Sarchie return (E2BIG); 79853913Sarchie *off += len; 79968845Sbrian bcopy(sval, buf, slen); 80070870Sjulian FREE(sval, M_NETGRAPH_PARSE); 80168845Sbrian bzero(buf + slen, fi->bufSize - slen); 80253913Sarchie *buflen = fi->bufSize; 80353913Sarchie return (0); 80453913Sarchie} 80553913Sarchie 80653913Sarchiestatic int 80753913Sarchieng_fixedstring_unparse(const struct ng_parse_type *type, 80853913Sarchie const u_char *data, int *off, char *cbuf, int cbuflen) 80953913Sarchie{ 81058011Sarchie const struct ng_parse_fixedstring_info *const fi = type->info; 81153913Sarchie int error, temp = *off; 81253913Sarchie 81353913Sarchie if ((error = ng_string_unparse(type, data, &temp, cbuf, cbuflen)) != 0) 81453913Sarchie return (error); 81553913Sarchie *off += fi->bufSize; 81653913Sarchie return (0); 81753913Sarchie} 81853913Sarchie 81953913Sarchiestatic int 82053913Sarchieng_fixedstring_getDefault(const struct ng_parse_type *type, 82153913Sarchie const u_char *const start, u_char *buf, int *buflen) 82253913Sarchie{ 82358011Sarchie const struct ng_parse_fixedstring_info *const fi = type->info; 82453913Sarchie 82553913Sarchie if (*buflen < fi->bufSize) 82653913Sarchie return (ERANGE); 82753913Sarchie bzero(buf, fi->bufSize); 82853913Sarchie *buflen = fi->bufSize; 82953913Sarchie return (0); 83053913Sarchie} 83153913Sarchie 83253913Sarchieconst struct ng_parse_type ng_parse_fixedstring_type = { 83353913Sarchie NULL, 83453913Sarchie NULL, 83553913Sarchie NULL, 83653913Sarchie ng_fixedstring_parse, 83753913Sarchie ng_fixedstring_unparse, 83853913Sarchie ng_fixedstring_getDefault, 83953913Sarchie NULL 84053913Sarchie}; 84153913Sarchie 84258011Sarchieconst struct ng_parse_fixedstring_info ng_parse_nodebuf_info = { 84353913Sarchie NG_NODELEN + 1 84453913Sarchie}; 84553913Sarchieconst struct ng_parse_type ng_parse_nodebuf_type = { 84653913Sarchie &ng_parse_fixedstring_type, 84753913Sarchie &ng_parse_nodebuf_info 84853913Sarchie}; 84953913Sarchie 85058011Sarchieconst struct ng_parse_fixedstring_info ng_parse_hookbuf_info = { 85153913Sarchie NG_HOOKLEN + 1 85253913Sarchie}; 85353913Sarchieconst struct ng_parse_type ng_parse_hookbuf_type = { 85453913Sarchie &ng_parse_fixedstring_type, 85553913Sarchie &ng_parse_hookbuf_info 85653913Sarchie}; 85753913Sarchie 85858011Sarchieconst struct ng_parse_fixedstring_info ng_parse_pathbuf_info = { 85953913Sarchie NG_PATHLEN + 1 86053913Sarchie}; 86153913Sarchieconst struct ng_parse_type ng_parse_pathbuf_type = { 86253913Sarchie &ng_parse_fixedstring_type, 86353913Sarchie &ng_parse_pathbuf_info 86453913Sarchie}; 86553913Sarchie 86658011Sarchieconst struct ng_parse_fixedstring_info ng_parse_typebuf_info = { 86753913Sarchie NG_TYPELEN + 1 86853913Sarchie}; 86953913Sarchieconst struct ng_parse_type ng_parse_typebuf_type = { 87053913Sarchie &ng_parse_fixedstring_type, 87153913Sarchie &ng_parse_typebuf_info 87253913Sarchie}; 87353913Sarchie 87458011Sarchieconst struct ng_parse_fixedstring_info ng_parse_cmdbuf_info = { 87553913Sarchie NG_CMDSTRLEN + 1 87653913Sarchie}; 87753913Sarchieconst struct ng_parse_type ng_parse_cmdbuf_type = { 87853913Sarchie &ng_parse_fixedstring_type, 87953913Sarchie &ng_parse_cmdbuf_info 88053913Sarchie}; 88153913Sarchie 88253913Sarchie/************************************************************************ 88368845Sbrian EXPLICITLY SIZED STRING TYPE 88468845Sbrian ************************************************************************/ 88568845Sbrian 88668845Sbrianstatic int 88768845Sbrianng_sizedstring_parse(const struct ng_parse_type *type, 88868845Sbrian const char *s, int *off, const u_char *const start, 88968845Sbrian u_char *const buf, int *buflen) 89068845Sbrian{ 89168845Sbrian char *sval; 89268845Sbrian int len; 89368845Sbrian int slen; 89468845Sbrian 89568845Sbrian if ((sval = ng_get_string_token(s, off, &len, &slen)) == NULL) 89668845Sbrian return (EINVAL); 89768845Sbrian if (slen > 0xffff) 89868845Sbrian return (EINVAL); 89968845Sbrian *off += len; 90068845Sbrian *((u_int16_t *)buf) = (u_int16_t)slen; 90168845Sbrian bcopy(sval, buf + 2, slen); 90270870Sjulian FREE(sval, M_NETGRAPH_PARSE); 90368845Sbrian *buflen = 2 + slen; 90468845Sbrian return (0); 90568845Sbrian} 90668845Sbrian 90768845Sbrianstatic int 90868845Sbrianng_sizedstring_unparse(const struct ng_parse_type *type, 90968845Sbrian const u_char *data, int *off, char *cbuf, int cbuflen) 91068845Sbrian{ 91168845Sbrian const char *const raw = (const char *)data + *off + 2; 91268845Sbrian const int slen = *((const u_int16_t *)(data + *off)); 91368845Sbrian char *const s = ng_encode_string(raw, slen); 91468845Sbrian 91568845Sbrian if (s == NULL) 91668845Sbrian return (ENOMEM); 91768845Sbrian NG_PARSE_APPEND("%s", s); 91870870Sjulian FREE(s, M_NETGRAPH_PARSE); 91968845Sbrian *off += slen + 2; 92068845Sbrian return (0); 92168845Sbrian} 92268845Sbrian 92368845Sbrianstatic int 92468845Sbrianng_sizedstring_getDefault(const struct ng_parse_type *type, 92568845Sbrian const u_char *const start, u_char *buf, int *buflen) 92668845Sbrian{ 92768845Sbrian if (*buflen < 2) 92868845Sbrian return (ERANGE); 92968845Sbrian bzero(buf, 2); 93068845Sbrian *buflen = 2; 93168845Sbrian return (0); 93268845Sbrian} 93368845Sbrian 93468845Sbrianconst struct ng_parse_type ng_parse_sizedstring_type = { 93568845Sbrian NULL, 93668845Sbrian NULL, 93768845Sbrian NULL, 93868845Sbrian ng_sizedstring_parse, 93968845Sbrian ng_sizedstring_unparse, 94068845Sbrian ng_sizedstring_getDefault, 94168845Sbrian NULL 94268845Sbrian}; 94368845Sbrian 94468845Sbrian/************************************************************************ 94553913Sarchie IP ADDRESS TYPE 94653913Sarchie ************************************************************************/ 94753913Sarchie 94853913Sarchiestatic int 94953913Sarchieng_ipaddr_parse(const struct ng_parse_type *type, 95053913Sarchie const char *s, int *off, const u_char *const start, 95153913Sarchie u_char *const buf, int *buflen) 95253913Sarchie{ 95353913Sarchie int i, error; 95453913Sarchie 95553913Sarchie for (i = 0; i < 4; i++) { 95653913Sarchie if ((error = ng_int8_parse(&ng_parse_int8_type, 95753913Sarchie s, off, start, buf + i, buflen)) != 0) 95853913Sarchie return (error); 95953913Sarchie if (i < 3 && s[*off] != '.') 96053913Sarchie return (EINVAL); 96153913Sarchie (*off)++; 96253913Sarchie } 96353913Sarchie *buflen = 4; 96453913Sarchie return (0); 96553913Sarchie} 96653913Sarchie 96753913Sarchiestatic int 96853913Sarchieng_ipaddr_unparse(const struct ng_parse_type *type, 96953913Sarchie const u_char *data, int *off, char *cbuf, int cbuflen) 97053913Sarchie{ 97153913Sarchie struct in_addr ip; 97253913Sarchie 97353913Sarchie bcopy(data + *off, &ip, sizeof(ip)); 97453913Sarchie NG_PARSE_APPEND("%d.%d.%d.%d", ((u_char *)&ip)[0], 97553913Sarchie ((u_char *)&ip)[1], ((u_char *)&ip)[2], ((u_char *)&ip)[3]); 97653913Sarchie *off += sizeof(ip); 97753913Sarchie return (0); 97853913Sarchie} 97953913Sarchie 98053913Sarchiestatic int 98153913Sarchieng_ipaddr_getDefault(const struct ng_parse_type *type, 98253913Sarchie const u_char *const start, u_char *buf, int *buflen) 98353913Sarchie{ 98453913Sarchie struct in_addr ip = { 0 }; 98553913Sarchie 98653913Sarchie if (*buflen < sizeof(ip)) 98753913Sarchie return (ERANGE); 98853913Sarchie bcopy(&ip, buf, sizeof(ip)); 98953913Sarchie *buflen = sizeof(ip); 99053913Sarchie return (0); 99153913Sarchie} 99253913Sarchie 99353913Sarchieconst struct ng_parse_type ng_parse_ipaddr_type = { 99453913Sarchie NULL, 99553913Sarchie NULL, 99653913Sarchie NULL, 99753913Sarchie ng_ipaddr_parse, 99853913Sarchie ng_ipaddr_unparse, 99953913Sarchie ng_ipaddr_getDefault, 100053913Sarchie ng_int32_getAlign 100153913Sarchie}; 100253913Sarchie 100353913Sarchie/************************************************************************ 1004123600Sru ETHERNET ADDRESS TYPE 1005123600Sru ************************************************************************/ 1006123600Sru 1007123600Srustatic int 1008123600Srung_enaddr_parse(const struct ng_parse_type *type, 1009123600Sru const char *s, int *const off, const u_char *const start, 1010123600Sru u_char *const buf, int *const buflen) 1011123600Sru{ 1012123600Sru char *eptr; 1013123600Sru u_long val; 1014123600Sru int i; 1015123600Sru 1016123600Sru if (*buflen < ETHER_ADDR_LEN) 1017123600Sru return (ERANGE); 1018123600Sru for (i = 0; i < ETHER_ADDR_LEN; i++) { 1019123600Sru val = strtoul(s + *off, &eptr, 16); 1020123600Sru if (val > 0xff || eptr == s + *off) 1021123600Sru return (EINVAL); 1022123600Sru buf[i] = (u_char)val; 1023123600Sru *off = (eptr - s); 1024123600Sru if (i < ETHER_ADDR_LEN - 1) { 1025123600Sru if (*eptr != ':') 1026123600Sru return (EINVAL); 1027123600Sru (*off)++; 1028123600Sru } 1029123600Sru } 1030123600Sru *buflen = ETHER_ADDR_LEN; 1031123600Sru return (0); 1032123600Sru} 1033123600Sru 1034123600Srustatic int 1035123600Srung_enaddr_unparse(const struct ng_parse_type *type, 1036123600Sru const u_char *data, int *off, char *cbuf, int cbuflen) 1037123600Sru{ 1038123600Sru int len; 1039123600Sru 1040123600Sru len = snprintf(cbuf, cbuflen, "%02x:%02x:%02x:%02x:%02x:%02x", 1041123600Sru data[*off], data[*off + 1], data[*off + 2], 1042123600Sru data[*off + 3], data[*off + 4], data[*off + 5]); 1043123600Sru if (len >= cbuflen) 1044123600Sru return (ERANGE); 1045123600Sru *off += ETHER_ADDR_LEN; 1046123600Sru return (0); 1047123600Sru} 1048123600Sru 1049123600Sruconst struct ng_parse_type ng_parse_enaddr_type = { 1050123600Sru NULL, 1051123600Sru NULL, 1052123600Sru NULL, 1053123600Sru ng_enaddr_parse, 1054123600Sru ng_enaddr_unparse, 1055123600Sru NULL, 1056123600Sru 0 1057123600Sru}; 1058123600Sru 1059123600Sru/************************************************************************ 106053913Sarchie BYTE ARRAY TYPE 106153913Sarchie ************************************************************************/ 106253913Sarchie 106353913Sarchie/* Get the length of a byte array */ 106453913Sarchiestatic int 106553913Sarchieng_parse_bytearray_subtype_getLength(const struct ng_parse_type *type, 106653913Sarchie const u_char *start, const u_char *buf) 106753913Sarchie{ 106853913Sarchie ng_parse_array_getLength_t *const getLength = type->private; 106953913Sarchie 107053913Sarchie return (*getLength)(type, start, buf); 107153913Sarchie} 107253913Sarchie 107364505Sarchie/* Byte array element type is hex int8 */ 107453913Sarchiestatic const struct ng_parse_array_info ng_parse_bytearray_subtype_info = { 107564505Sarchie &ng_parse_hint8_type, 107653913Sarchie &ng_parse_bytearray_subtype_getLength, 107753913Sarchie NULL 107853913Sarchie}; 107953913Sarchiestatic const struct ng_parse_type ng_parse_bytearray_subtype = { 108053913Sarchie &ng_parse_array_type, 108153913Sarchie &ng_parse_bytearray_subtype_info 108253913Sarchie}; 108353913Sarchie 108453913Sarchiestatic int 108553913Sarchieng_bytearray_parse(const struct ng_parse_type *type, 108653913Sarchie const char *s, int *off, const u_char *const start, 108753913Sarchie u_char *const buf, int *buflen) 108853913Sarchie{ 108953913Sarchie char *str; 109053913Sarchie int toklen; 109168845Sbrian int slen; 109253913Sarchie 109353913Sarchie /* We accept either an array of bytes or a string constant */ 109468845Sbrian if ((str = ng_get_string_token(s, off, &toklen, &slen)) != NULL) { 109553913Sarchie ng_parse_array_getLength_t *const getLength = type->info; 109668845Sbrian int arraylen; 109753913Sarchie 109853913Sarchie arraylen = (*getLength)(type, start, buf); 109953913Sarchie if (arraylen > *buflen) { 110070870Sjulian FREE(str, M_NETGRAPH_PARSE); 110153913Sarchie return (ERANGE); 110253913Sarchie } 110353913Sarchie if (slen > arraylen) { 110470870Sjulian FREE(str, M_NETGRAPH_PARSE); 110553913Sarchie return (E2BIG); 110653913Sarchie } 110753913Sarchie bcopy(str, buf, slen); 110853913Sarchie bzero(buf + slen, arraylen - slen); 110970870Sjulian FREE(str, M_NETGRAPH_PARSE); 111053913Sarchie *off += toklen; 111153913Sarchie *buflen = arraylen; 111253913Sarchie return (0); 111353913Sarchie } else { 111453913Sarchie struct ng_parse_type subtype; 111553913Sarchie 111653913Sarchie subtype = ng_parse_bytearray_subtype; 111753913Sarchie (const void *)subtype.private = type->info; 111853913Sarchie return ng_array_parse(&subtype, s, off, start, buf, buflen); 111953913Sarchie } 112053913Sarchie} 112153913Sarchie 112253913Sarchiestatic int 112353913Sarchieng_bytearray_unparse(const struct ng_parse_type *type, 112453913Sarchie const u_char *data, int *off, char *cbuf, int cbuflen) 112553913Sarchie{ 112653913Sarchie struct ng_parse_type subtype; 112753913Sarchie 112853913Sarchie subtype = ng_parse_bytearray_subtype; 112953913Sarchie (const void *)subtype.private = type->info; 113053913Sarchie return ng_array_unparse(&subtype, data, off, cbuf, cbuflen); 113153913Sarchie} 113253913Sarchie 113353913Sarchiestatic int 113453913Sarchieng_bytearray_getDefault(const struct ng_parse_type *type, 113553913Sarchie const u_char *const start, u_char *buf, int *buflen) 113653913Sarchie{ 113753913Sarchie struct ng_parse_type subtype; 113853913Sarchie 113953913Sarchie subtype = ng_parse_bytearray_subtype; 114053913Sarchie (const void *)subtype.private = type->info; 114153913Sarchie return ng_array_getDefault(&subtype, start, buf, buflen); 114253913Sarchie} 114353913Sarchie 114453913Sarchieconst struct ng_parse_type ng_parse_bytearray_type = { 114553913Sarchie NULL, 114653913Sarchie NULL, 114753913Sarchie NULL, 114853913Sarchie ng_bytearray_parse, 114953913Sarchie ng_bytearray_unparse, 115053913Sarchie ng_bytearray_getDefault, 115153913Sarchie NULL 115253913Sarchie}; 115353913Sarchie 115453913Sarchie/************************************************************************ 115553913Sarchie STRUCT NG_MESG TYPE 115653913Sarchie ************************************************************************/ 115753913Sarchie 115853913Sarchie/* Get msg->header.arglen when "buf" is pointing to msg->data */ 115953913Sarchiestatic int 116053913Sarchieng_parse_ng_mesg_getLength(const struct ng_parse_type *type, 116153913Sarchie const u_char *start, const u_char *buf) 116253913Sarchie{ 116353913Sarchie const struct ng_mesg *msg; 116453913Sarchie 116553913Sarchie msg = (const struct ng_mesg *)(buf - sizeof(*msg)); 116653913Sarchie return msg->header.arglen; 116753913Sarchie} 116853913Sarchie 116953913Sarchie/* Type for the variable length data portion of a struct ng_mesg */ 117053913Sarchiestatic const struct ng_parse_type ng_msg_data_type = { 117153913Sarchie &ng_parse_bytearray_type, 117253913Sarchie &ng_parse_ng_mesg_getLength 117353913Sarchie}; 117453913Sarchie 117553913Sarchie/* Type for the entire struct ng_mesg header with data section */ 117697685Sarchiestatic const struct ng_parse_struct_field ng_parse_ng_mesg_type_fields[] 117797685Sarchie = NG_GENERIC_NG_MESG_INFO(&ng_msg_data_type); 117853913Sarchieconst struct ng_parse_type ng_parse_ng_mesg_type = { 117953913Sarchie &ng_parse_struct_type, 118097685Sarchie &ng_parse_ng_mesg_type_fields, 118153913Sarchie}; 118253913Sarchie 118353913Sarchie/************************************************************************ 118453913Sarchie COMPOSITE HELPER ROUTINES 118553913Sarchie ************************************************************************/ 118653913Sarchie 118753913Sarchie/* 118853913Sarchie * Convert a structure or array from ASCII to binary 118953913Sarchie */ 119053913Sarchiestatic int 119153913Sarchieng_parse_composite(const struct ng_parse_type *type, const char *s, 119253913Sarchie int *off, const u_char *const start, u_char *const buf, int *buflen, 119353913Sarchie const enum comptype ctype) 119453913Sarchie{ 119553913Sarchie const int num = ng_get_composite_len(type, start, buf, ctype); 119653913Sarchie int nextIndex = 0; /* next implicit array index */ 119753913Sarchie u_int index; /* field or element index */ 119853913Sarchie int *foff; /* field value offsets in string */ 119953913Sarchie int align, len, blen, error = 0; 120053913Sarchie 120153913Sarchie /* Initialize */ 120270870Sjulian MALLOC(foff, int *, num * sizeof(*foff), M_NETGRAPH_PARSE, M_NOWAIT | M_ZERO); 120353913Sarchie if (foff == NULL) { 120453913Sarchie error = ENOMEM; 120553913Sarchie goto done; 120653913Sarchie } 120753913Sarchie 120853913Sarchie /* Get opening brace/bracket */ 120953913Sarchie if (ng_parse_get_token(s, off, &len) 121053913Sarchie != (ctype == CT_STRUCT ? T_LBRACE : T_LBRACKET)) { 121153913Sarchie error = EINVAL; 121253913Sarchie goto done; 121353913Sarchie } 121453913Sarchie *off += len; 121553913Sarchie 121653913Sarchie /* Get individual element value positions in the string */ 121753913Sarchie for (;;) { 121853913Sarchie enum ng_parse_token tok; 121953913Sarchie 122053913Sarchie /* Check for closing brace/bracket */ 122153913Sarchie tok = ng_parse_get_token(s, off, &len); 122253913Sarchie if (tok == (ctype == CT_STRUCT ? T_RBRACE : T_RBRACKET)) { 122353913Sarchie *off += len; 122453913Sarchie break; 122553913Sarchie } 122653913Sarchie 122753913Sarchie /* For arrays, the 'name' (ie, index) is optional, so 122853913Sarchie distinguish name from values by seeing if the next 122953913Sarchie token is an equals sign */ 123053913Sarchie if (ctype != CT_STRUCT) { 123153913Sarchie int len2, off2; 123253913Sarchie char *eptr; 123353913Sarchie 123453913Sarchie /* If an opening brace/bracket, index is implied */ 123553913Sarchie if (tok == T_LBRACE || tok == T_LBRACKET) { 123653913Sarchie index = nextIndex++; 123753913Sarchie goto gotIndex; 123853913Sarchie } 123953913Sarchie 124053913Sarchie /* Might be an index, might be a value, either way... */ 124153913Sarchie if (tok != T_WORD) { 124253913Sarchie error = EINVAL; 124353913Sarchie goto done; 124453913Sarchie } 124553913Sarchie 124653913Sarchie /* If no equals sign follows, index is implied */ 124753913Sarchie off2 = *off + len; 124853913Sarchie if (ng_parse_get_token(s, &off2, &len2) != T_EQUALS) { 124953913Sarchie index = nextIndex++; 125053913Sarchie goto gotIndex; 125153913Sarchie } 125253913Sarchie 125353913Sarchie /* Index was specified explicitly; parse it */ 125453913Sarchie index = (u_int)strtoul(s + *off, &eptr, 0); 125553913Sarchie if (index < 0 || eptr - (s + *off) != len) { 125653913Sarchie error = EINVAL; 125753913Sarchie goto done; 125853913Sarchie } 125953913Sarchie nextIndex = index + 1; 126053913Sarchie *off += len + len2; 126153913Sarchie } else { /* a structure field */ 126297685Sarchie const struct ng_parse_struct_field *const 126397685Sarchie fields = type->info; 126453913Sarchie 126553913Sarchie /* Find the field by name (required) in field list */ 126653913Sarchie if (tok != T_WORD) { 126753913Sarchie error = EINVAL; 126853913Sarchie goto done; 126953913Sarchie } 127053913Sarchie for (index = 0; index < num; index++) { 127197685Sarchie const struct ng_parse_struct_field *const 127297685Sarchie field = &fields[index]; 127397685Sarchie 127453913Sarchie if (strncmp(&s[*off], field->name, len) == 0 127553913Sarchie && field->name[len] == '\0') 127653913Sarchie break; 127753913Sarchie } 127853913Sarchie if (index == num) { 127953913Sarchie error = ENOENT; 128053913Sarchie goto done; 128153913Sarchie } 128253913Sarchie *off += len; 128353913Sarchie 128453913Sarchie /* Get equals sign */ 128553913Sarchie if (ng_parse_get_token(s, off, &len) != T_EQUALS) { 128653913Sarchie error = EINVAL; 128753913Sarchie goto done; 128853913Sarchie } 128953913Sarchie *off += len; 129053913Sarchie } 129197229SpetergotIndex: 129253913Sarchie 129353913Sarchie /* Check array index */ 129453913Sarchie if (index >= num) { 129553913Sarchie error = E2BIG; 129653913Sarchie goto done; 129753913Sarchie } 129853913Sarchie 129953913Sarchie /* Save value's position and skip over it for now */ 130053913Sarchie if (foff[index] != 0) { 130153913Sarchie error = EALREADY; /* duplicate */ 130253913Sarchie goto done; 130353913Sarchie } 130453913Sarchie while (isspace(s[*off])) 130553913Sarchie (*off)++; 130653913Sarchie foff[index] = *off; 130753913Sarchie if ((error = ng_parse_skip_value(s, *off, &len)) != 0) 130853913Sarchie goto done; 130953913Sarchie *off += len; 131053913Sarchie } 131153913Sarchie 131253913Sarchie /* Now build binary structure from supplied values and defaults */ 131353913Sarchie for (blen = index = 0; index < num; index++) { 131453913Sarchie const struct ng_parse_type *const 131553913Sarchie etype = ng_get_composite_etype(type, index, ctype); 131653913Sarchie int k, pad, vlen; 131753913Sarchie 131853913Sarchie /* Zero-pad any alignment bytes */ 131953913Sarchie pad = ng_parse_get_elem_pad(type, index, ctype, blen); 132053913Sarchie for (k = 0; k < pad; k++) { 132153913Sarchie if (blen >= *buflen) { 132253913Sarchie error = ERANGE; 132353913Sarchie goto done; 132453913Sarchie } 132553913Sarchie buf[blen++] = 0; 132653913Sarchie } 132753913Sarchie 132853913Sarchie /* Get value */ 132953913Sarchie vlen = *buflen - blen; 133053913Sarchie if (foff[index] == 0) { /* use default value */ 133153913Sarchie error = ng_get_composite_elem_default(type, index, 133253913Sarchie start, buf + blen, &vlen, ctype); 133353913Sarchie } else { /* parse given value */ 133453913Sarchie *off = foff[index]; 133553913Sarchie error = INVOKE(etype, parse)(etype, 133653913Sarchie s, off, start, buf + blen, &vlen); 133753913Sarchie } 133853913Sarchie if (error != 0) 133953913Sarchie goto done; 134053913Sarchie blen += vlen; 134153913Sarchie } 134253913Sarchie 134353913Sarchie /* Make total composite structure size a multiple of its alignment */ 134453913Sarchie if ((align = ALIGNMENT(type)) != 0) { 134553913Sarchie while (blen % align != 0) { 134653913Sarchie if (blen >= *buflen) { 134753913Sarchie error = ERANGE; 134853913Sarchie goto done; 134953913Sarchie } 135053913Sarchie buf[blen++] = 0; 135153913Sarchie } 135253913Sarchie } 135353913Sarchie 135453913Sarchie /* Done */ 135553913Sarchie *buflen = blen; 135653913Sarchiedone: 135765303Sarchie if (foff != NULL) 135870870Sjulian FREE(foff, M_NETGRAPH_PARSE); 135953913Sarchie return (error); 136053913Sarchie} 136153913Sarchie 136253913Sarchie/* 136353913Sarchie * Convert an array or structure from binary to ASCII 136453913Sarchie */ 136553913Sarchiestatic int 136653913Sarchieng_unparse_composite(const struct ng_parse_type *type, const u_char *data, 136753913Sarchie int *off, char *cbuf, int cbuflen, const enum comptype ctype) 136853913Sarchie{ 136990047Sarchie const struct ng_mesg *const hdr 137090047Sarchie = (const struct ng_mesg *)(data - sizeof(*hdr)); 137153913Sarchie const int num = ng_get_composite_len(type, data, data + *off, ctype); 137264505Sarchie const int workSize = 20 * 1024; /* XXX hard coded constant */ 137353913Sarchie int nextIndex = 0, didOne = 0; 137453913Sarchie int error, index; 137564505Sarchie u_char *workBuf; 137653913Sarchie 137764505Sarchie /* Get workspace for checking default values */ 137870870Sjulian MALLOC(workBuf, u_char *, workSize, M_NETGRAPH_PARSE, M_NOWAIT); 137964505Sarchie if (workBuf == NULL) 138064505Sarchie return (ENOMEM); 138164505Sarchie 138253913Sarchie /* Opening brace/bracket */ 138353913Sarchie NG_PARSE_APPEND("%c", (ctype == CT_STRUCT) ? '{' : '['); 138453913Sarchie 138553913Sarchie /* Do each item */ 138653913Sarchie for (index = 0; index < num; index++) { 138753913Sarchie const struct ng_parse_type *const 138853913Sarchie etype = ng_get_composite_etype(type, index, ctype); 138953913Sarchie 139053913Sarchie /* Skip any alignment pad bytes */ 139153913Sarchie *off += ng_parse_get_elem_pad(type, index, ctype, *off); 139253913Sarchie 139390047Sarchie /* 139490047Sarchie * See if element is equal to its default value; skip if so. 139590047Sarchie * Copy struct ng_mesg header for types that peek into it. 139690047Sarchie */ 139790047Sarchie if (sizeof(*hdr) + *off < workSize) { 139890047Sarchie int tempsize = workSize - sizeof(*hdr) - *off; 139953913Sarchie 140090584Sarchie bcopy(hdr, workBuf, sizeof(*hdr) + *off); 140190047Sarchie if (ng_get_composite_elem_default(type, index, workBuf 140290047Sarchie + sizeof(*hdr), workBuf + sizeof(*hdr) + *off, 140390047Sarchie &tempsize, ctype) == 0 140490047Sarchie && bcmp(workBuf + sizeof(*hdr) + *off, 140564505Sarchie data + *off, tempsize) == 0) { 140653913Sarchie *off += tempsize; 140753913Sarchie continue; 140853913Sarchie } 140953913Sarchie } 141053913Sarchie 141153913Sarchie /* Print name= */ 141253913Sarchie NG_PARSE_APPEND(" "); 141353913Sarchie if (ctype != CT_STRUCT) { 141453913Sarchie if (index != nextIndex) { 141553913Sarchie nextIndex = index; 141653913Sarchie NG_PARSE_APPEND("%d=", index); 141753913Sarchie } 141853913Sarchie nextIndex++; 141953913Sarchie } else { 142097685Sarchie const struct ng_parse_struct_field *const 142197685Sarchie fields = type->info; 142253913Sarchie 142397685Sarchie NG_PARSE_APPEND("%s=", fields[index].name); 142453913Sarchie } 142553913Sarchie 142653913Sarchie /* Print value */ 142753913Sarchie if ((error = INVOKE(etype, unparse) 142864505Sarchie (etype, data, off, cbuf, cbuflen)) != 0) { 142970870Sjulian FREE(workBuf, M_NETGRAPH_PARSE); 143053913Sarchie return (error); 143164505Sarchie } 143253913Sarchie cbuflen -= strlen(cbuf); 143353913Sarchie cbuf += strlen(cbuf); 143453913Sarchie didOne = 1; 143553913Sarchie } 143670870Sjulian FREE(workBuf, M_NETGRAPH_PARSE); 143753913Sarchie 143853913Sarchie /* Closing brace/bracket */ 143953913Sarchie NG_PARSE_APPEND("%s%c", 144053913Sarchie didOne ? " " : "", (ctype == CT_STRUCT) ? '}' : ']'); 144153913Sarchie return (0); 144253913Sarchie} 144353913Sarchie 144453913Sarchie/* 144553913Sarchie * Generate the default value for an element of an array or structure 144653913Sarchie * Returns EOPNOTSUPP if default value is unspecified. 144753913Sarchie */ 144853913Sarchiestatic int 144953913Sarchieng_get_composite_elem_default(const struct ng_parse_type *type, 145053913Sarchie int index, const u_char *const start, u_char *buf, int *buflen, 145153913Sarchie const enum comptype ctype) 145253913Sarchie{ 145353913Sarchie const struct ng_parse_type *etype; 145453913Sarchie ng_getDefault_t *func; 145553913Sarchie 145653913Sarchie switch (ctype) { 145753913Sarchie case CT_STRUCT: 145853913Sarchie break; 145953913Sarchie case CT_ARRAY: 146053913Sarchie { 146153913Sarchie const struct ng_parse_array_info *const ai = type->info; 146253913Sarchie 146353913Sarchie if (ai->getDefault != NULL) { 146453913Sarchie return (*ai->getDefault)(type, 146553913Sarchie index, start, buf, buflen); 146653913Sarchie } 146753913Sarchie break; 146853913Sarchie } 146953913Sarchie case CT_FIXEDARRAY: 147053913Sarchie { 147153913Sarchie const struct ng_parse_fixedarray_info *const fi = type->info; 147253913Sarchie 147353913Sarchie if (*fi->getDefault != NULL) { 147453913Sarchie return (*fi->getDefault)(type, 147553913Sarchie index, start, buf, buflen); 147653913Sarchie } 147753913Sarchie break; 147853913Sarchie } 147953913Sarchie default: 148087599Sobrien panic("%s", __func__); 148153913Sarchie } 148253913Sarchie 148353913Sarchie /* Default to element type default */ 148453913Sarchie etype = ng_get_composite_etype(type, index, ctype); 148553913Sarchie func = METHOD(etype, getDefault); 148653913Sarchie if (func == NULL) 148753913Sarchie return (EOPNOTSUPP); 148853913Sarchie return (*func)(etype, start, buf, buflen); 148953913Sarchie} 149053913Sarchie 149153913Sarchie/* 149253913Sarchie * Get the number of elements in a struct, variable or fixed array. 149353913Sarchie */ 149453913Sarchiestatic int 149553913Sarchieng_get_composite_len(const struct ng_parse_type *type, 149653913Sarchie const u_char *const start, const u_char *buf, 149753913Sarchie const enum comptype ctype) 149853913Sarchie{ 149953913Sarchie switch (ctype) { 150053913Sarchie case CT_STRUCT: 150153913Sarchie { 150297685Sarchie const struct ng_parse_struct_field *const fields = type->info; 150353913Sarchie int numFields = 0; 150453913Sarchie 150553913Sarchie for (numFields = 0; ; numFields++) { 150653913Sarchie const struct ng_parse_struct_field *const 150797685Sarchie fi = &fields[numFields]; 150853913Sarchie 150953913Sarchie if (fi->name == NULL) 151053913Sarchie break; 151153913Sarchie } 151253913Sarchie return (numFields); 151353913Sarchie } 151453913Sarchie case CT_ARRAY: 151553913Sarchie { 151653913Sarchie const struct ng_parse_array_info *const ai = type->info; 151753913Sarchie 151853913Sarchie return (*ai->getLength)(type, start, buf); 151953913Sarchie } 152053913Sarchie case CT_FIXEDARRAY: 152153913Sarchie { 152253913Sarchie const struct ng_parse_fixedarray_info *const fi = type->info; 152353913Sarchie 152453913Sarchie return fi->length; 152553913Sarchie } 152653913Sarchie default: 152787599Sobrien panic("%s", __func__); 152853913Sarchie } 152953913Sarchie return (0); 153053913Sarchie} 153153913Sarchie 153253913Sarchie/* 153353913Sarchie * Return the type of the index'th element of a composite structure 153453913Sarchie */ 153553913Sarchiestatic const struct ng_parse_type * 153653913Sarchieng_get_composite_etype(const struct ng_parse_type *type, 153753913Sarchie int index, const enum comptype ctype) 153853913Sarchie{ 153953913Sarchie const struct ng_parse_type *etype = NULL; 154053913Sarchie 154153913Sarchie switch (ctype) { 154253913Sarchie case CT_STRUCT: 154353913Sarchie { 154497685Sarchie const struct ng_parse_struct_field *const fields = type->info; 154553913Sarchie 154697685Sarchie etype = fields[index].type; 154753913Sarchie break; 154853913Sarchie } 154953913Sarchie case CT_ARRAY: 155053913Sarchie { 155153913Sarchie const struct ng_parse_array_info *const ai = type->info; 155253913Sarchie 155353913Sarchie etype = ai->elementType; 155453913Sarchie break; 155553913Sarchie } 155653913Sarchie case CT_FIXEDARRAY: 155753913Sarchie { 155853913Sarchie const struct ng_parse_fixedarray_info *const fi = type->info; 155953913Sarchie 156053913Sarchie etype = fi->elementType; 156153913Sarchie break; 156253913Sarchie } 156353913Sarchie default: 156487599Sobrien panic("%s", __func__); 156553913Sarchie } 156653913Sarchie return (etype); 156753913Sarchie} 156853913Sarchie 156953913Sarchie/* 157053913Sarchie * Get the number of bytes to skip to align for the next 157153913Sarchie * element in a composite structure. 157253913Sarchie */ 157353913Sarchiestatic int 157453913Sarchieng_parse_get_elem_pad(const struct ng_parse_type *type, 157553913Sarchie int index, enum comptype ctype, int posn) 157653913Sarchie{ 157753913Sarchie const struct ng_parse_type *const 157853913Sarchie etype = ng_get_composite_etype(type, index, ctype); 157953913Sarchie int align; 158053913Sarchie 158153913Sarchie /* Get element's alignment, and possibly override */ 158253913Sarchie align = ALIGNMENT(etype); 158353913Sarchie if (ctype == CT_STRUCT) { 158497685Sarchie const struct ng_parse_struct_field *const fields = type->info; 158553913Sarchie 158697685Sarchie if (fields[index].alignment != 0) 158797685Sarchie align = fields[index].alignment; 158853913Sarchie } 158953913Sarchie 159053913Sarchie /* Return number of bytes to skip to align */ 159153913Sarchie return (align ? (align - (posn % align)) % align : 0); 159253913Sarchie} 159353913Sarchie 159453913Sarchie/************************************************************************ 159553913Sarchie PARSING HELPER ROUTINES 159653913Sarchie ************************************************************************/ 159753913Sarchie 159853913Sarchie/* 159953913Sarchie * Skip over a value 160053913Sarchie */ 160153913Sarchiestatic int 160253913Sarchieng_parse_skip_value(const char *s, int off0, int *lenp) 160353913Sarchie{ 160453913Sarchie int len, nbracket, nbrace; 160553913Sarchie int off = off0; 160653913Sarchie 160753913Sarchie len = nbracket = nbrace = 0; 160853913Sarchie do { 160953913Sarchie switch (ng_parse_get_token(s, &off, &len)) { 161053913Sarchie case T_LBRACKET: 161153913Sarchie nbracket++; 161253913Sarchie break; 161353913Sarchie case T_LBRACE: 161453913Sarchie nbrace++; 161553913Sarchie break; 161653913Sarchie case T_RBRACKET: 161753913Sarchie if (nbracket-- == 0) 161853913Sarchie return (EINVAL); 161953913Sarchie break; 162053913Sarchie case T_RBRACE: 162153913Sarchie if (nbrace-- == 0) 162253913Sarchie return (EINVAL); 162353913Sarchie break; 162453913Sarchie case T_EOF: 162553913Sarchie return (EINVAL); 162653913Sarchie default: 162753913Sarchie break; 162853913Sarchie } 162953913Sarchie off += len; 163053913Sarchie } while (nbracket > 0 || nbrace > 0); 163153913Sarchie *lenp = off - off0; 163253913Sarchie return (0); 163353913Sarchie} 163453913Sarchie 163553913Sarchie/* 163653913Sarchie * Find the next token in the string, starting at offset *startp. 163753913Sarchie * Returns the token type, with *startp pointing to the first char 163853913Sarchie * and *lenp the length. 163953913Sarchie */ 164053913Sarchieenum ng_parse_token 164153913Sarchieng_parse_get_token(const char *s, int *startp, int *lenp) 164253913Sarchie{ 164353913Sarchie char *t; 164453913Sarchie int i; 164553913Sarchie 164653913Sarchie while (isspace(s[*startp])) 164753913Sarchie (*startp)++; 164853913Sarchie switch (s[*startp]) { 164953913Sarchie case '\0': 165053913Sarchie *lenp = 0; 165153913Sarchie return T_EOF; 165253913Sarchie case '{': 165353913Sarchie *lenp = 1; 165453913Sarchie return T_LBRACE; 165553913Sarchie case '}': 165653913Sarchie *lenp = 1; 165753913Sarchie return T_RBRACE; 165853913Sarchie case '[': 165953913Sarchie *lenp = 1; 166053913Sarchie return T_LBRACKET; 166153913Sarchie case ']': 166253913Sarchie *lenp = 1; 166353913Sarchie return T_RBRACKET; 166453913Sarchie case '=': 166553913Sarchie *lenp = 1; 166653913Sarchie return T_EQUALS; 166753913Sarchie case '"': 166868845Sbrian if ((t = ng_get_string_token(s, startp, lenp, NULL)) == NULL) 166953913Sarchie return T_ERROR; 167070870Sjulian FREE(t, M_NETGRAPH_PARSE); 167153913Sarchie return T_STRING; 167253913Sarchie default: 167353913Sarchie for (i = *startp + 1; s[i] != '\0' && !isspace(s[i]) 167453913Sarchie && s[i] != '{' && s[i] != '}' && s[i] != '[' 167553913Sarchie && s[i] != ']' && s[i] != '=' && s[i] != '"'; i++) 167653913Sarchie ; 167753913Sarchie *lenp = i - *startp; 167853913Sarchie return T_WORD; 167953913Sarchie } 168053913Sarchie} 168153913Sarchie 168253913Sarchie/* 168353913Sarchie * Get a string token, which must be enclosed in double quotes. 168453913Sarchie * The normal C backslash escapes are recognized. 168553913Sarchie */ 168653913Sarchiechar * 168768845Sbrianng_get_string_token(const char *s, int *startp, int *lenp, int *slenp) 168853913Sarchie{ 168953913Sarchie char *cbuf, *p; 169053913Sarchie int start, off; 169168845Sbrian int slen; 169253913Sarchie 169353913Sarchie while (isspace(s[*startp])) 169453913Sarchie (*startp)++; 169553913Sarchie start = *startp; 169653913Sarchie if (s[*startp] != '"') 169753913Sarchie return (NULL); 169870870Sjulian MALLOC(cbuf, char *, strlen(s + start), M_NETGRAPH_PARSE, M_NOWAIT); 169953913Sarchie if (cbuf == NULL) 170053913Sarchie return (NULL); 170153913Sarchie strcpy(cbuf, s + start + 1); 170268845Sbrian for (slen = 0, off = 1, p = cbuf; *p != '\0'; slen++, off++, p++) { 170353913Sarchie if (*p == '"') { 170453913Sarchie *p = '\0'; 170553913Sarchie *lenp = off + 1; 170668845Sbrian if (slenp != NULL) 170768845Sbrian *slenp = slen; 170853913Sarchie return (cbuf); 170953913Sarchie } else if (p[0] == '\\' && p[1] != '\0') { 171053913Sarchie int x, k; 171153913Sarchie char *v; 171253913Sarchie 171353913Sarchie strcpy(p, p + 1); 171453913Sarchie v = p; 171553913Sarchie switch (*p) { 171653913Sarchie case 't': 171753913Sarchie *v = '\t'; 171853913Sarchie off++; 171953913Sarchie continue; 172053913Sarchie case 'n': 172153913Sarchie *v = '\n'; 172253913Sarchie off++; 172353913Sarchie continue; 172453913Sarchie case 'r': 172553913Sarchie *v = '\r'; 172653913Sarchie off++; 172753913Sarchie continue; 172853913Sarchie case 'v': 172953913Sarchie *v = '\v'; 173053913Sarchie off++; 173153913Sarchie continue; 173253913Sarchie case 'f': 173353913Sarchie *v = '\f'; 173453913Sarchie off++; 173553913Sarchie continue; 173653913Sarchie case '"': 173753913Sarchie *v = '"'; 173853913Sarchie off++; 173953913Sarchie continue; 174053913Sarchie case '0': case '1': case '2': case '3': 174153913Sarchie case '4': case '5': case '6': case '7': 174253913Sarchie for (x = k = 0; 174353913Sarchie k < 3 && *v >= '0' && *v <= '7'; v++) { 174453913Sarchie x = (x << 3) + (*v - '0'); 174553913Sarchie off++; 174653913Sarchie } 174753913Sarchie *--v = (char)x; 174853913Sarchie break; 174953913Sarchie case 'x': 175053913Sarchie for (v++, x = k = 0; 175153913Sarchie k < 2 && isxdigit(*v); v++) { 175253913Sarchie x = (x << 4) + (isdigit(*v) ? 175353913Sarchie (*v - '0') : 175453913Sarchie (tolower(*v) - 'a' + 10)); 175553913Sarchie off++; 175653913Sarchie } 175753913Sarchie *--v = (char)x; 175853913Sarchie break; 175953913Sarchie default: 176053913Sarchie continue; 176153913Sarchie } 176253913Sarchie strcpy(p, v); 176353913Sarchie } 176453913Sarchie } 176553913Sarchie return (NULL); /* no closing quote */ 176653913Sarchie} 176753913Sarchie 176853913Sarchie/* 176953913Sarchie * Encode a string so it can be safely put in double quotes. 177068845Sbrian * Caller must free the result. Exactly "slen" characters 177168845Sbrian * are encoded. 177253913Sarchie */ 177353913Sarchiechar * 177468845Sbrianng_encode_string(const char *raw, int slen) 177553913Sarchie{ 177653913Sarchie char *cbuf; 177753913Sarchie int off = 0; 177868845Sbrian int i; 177953913Sarchie 178070870Sjulian MALLOC(cbuf, char *, strlen(raw) * 4 + 3, M_NETGRAPH_PARSE, M_NOWAIT); 178153913Sarchie if (cbuf == NULL) 178253913Sarchie return (NULL); 178353913Sarchie cbuf[off++] = '"'; 178468845Sbrian for (i = 0; i < slen; i++, raw++) { 178553913Sarchie switch (*raw) { 178653913Sarchie case '\t': 178753913Sarchie cbuf[off++] = '\\'; 178853913Sarchie cbuf[off++] = 't'; 178953913Sarchie break; 179053913Sarchie case '\f': 179153913Sarchie cbuf[off++] = '\\'; 179253913Sarchie cbuf[off++] = 'f'; 179353913Sarchie break; 179453913Sarchie case '\n': 179553913Sarchie cbuf[off++] = '\\'; 179653913Sarchie cbuf[off++] = 'n'; 179753913Sarchie break; 179853913Sarchie case '\r': 179953913Sarchie cbuf[off++] = '\\'; 180053913Sarchie cbuf[off++] = 'r'; 180153913Sarchie break; 180253913Sarchie case '\v': 180353913Sarchie cbuf[off++] = '\\'; 180453913Sarchie cbuf[off++] = 'v'; 180553913Sarchie break; 180653913Sarchie case '"': 180753913Sarchie case '\\': 180853913Sarchie cbuf[off++] = '\\'; 180953913Sarchie cbuf[off++] = *raw; 181053913Sarchie break; 181153913Sarchie default: 181253913Sarchie if (*raw < 0x20 || *raw > 0x7e) { 181353913Sarchie off += sprintf(cbuf + off, 181453913Sarchie "\\x%02x", (u_char)*raw); 181553913Sarchie break; 181653913Sarchie } 181753913Sarchie cbuf[off++] = *raw; 181853913Sarchie break; 181953913Sarchie } 182053913Sarchie } 182153913Sarchie cbuf[off++] = '"'; 182253913Sarchie cbuf[off] = '\0'; 182353913Sarchie return (cbuf); 182453913Sarchie} 182553913Sarchie 182653913Sarchie/************************************************************************ 182753913Sarchie VIRTUAL METHOD LOOKUP 182853913Sarchie ************************************************************************/ 182953913Sarchie 183053913Sarchiestatic ng_parse_t * 183153913Sarchieng_get_parse_method(const struct ng_parse_type *t) 183253913Sarchie{ 183353913Sarchie while (t != NULL && t->parse == NULL) 183453913Sarchie t = t->supertype; 183553913Sarchie return (t ? t->parse : NULL); 183653913Sarchie} 183753913Sarchie 183853913Sarchiestatic ng_unparse_t * 183953913Sarchieng_get_unparse_method(const struct ng_parse_type *t) 184053913Sarchie{ 184153913Sarchie while (t != NULL && t->unparse == NULL) 184253913Sarchie t = t->supertype; 184353913Sarchie return (t ? t->unparse : NULL); 184453913Sarchie} 184553913Sarchie 184653913Sarchiestatic ng_getDefault_t * 184753913Sarchieng_get_getDefault_method(const struct ng_parse_type *t) 184853913Sarchie{ 184953913Sarchie while (t != NULL && t->getDefault == NULL) 185053913Sarchie t = t->supertype; 185153913Sarchie return (t ? t->getDefault : NULL); 185253913Sarchie} 185353913Sarchie 185453913Sarchiestatic ng_getAlign_t * 185553913Sarchieng_get_getAlign_method(const struct ng_parse_type *t) 185653913Sarchie{ 185753913Sarchie while (t != NULL && t->getAlign == NULL) 185853913Sarchie t = t->supertype; 185953913Sarchie return (t ? t->getAlign : NULL); 186053913Sarchie} 186153913Sarchie 1862