ng_parse.c revision 97685
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 97685 2002-05-31 23:48:03Z archie $ 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 5153913Sarchie#include <netinet/in.h> 5253913Sarchie 5353913Sarchie#include <netgraph/ng_message.h> 5453913Sarchie#include <netgraph/netgraph.h> 5553913Sarchie#include <netgraph/ng_parse.h> 5653913Sarchie 5770870Sjulian#ifdef NG_SEPARATE_MALLOC 5870870SjulianMALLOC_DEFINE(M_NETGRAPH_PARSE, "netgraph_parse", "netgraph parse info"); 5970870Sjulian#else 6070870Sjulian#define M_NETGRAPH_PARSE M_NETGRAPH 6170870Sjulian#endif 6270870Sjulian 6353913Sarchie/* Compute alignment for primitive integral types */ 6453913Sarchiestruct int16_temp { 6553913Sarchie char x; 6653913Sarchie int16_t y; 6753913Sarchie}; 6853913Sarchie 6953913Sarchiestruct int32_temp { 7053913Sarchie char x; 7153913Sarchie int32_t y; 7253913Sarchie}; 7353913Sarchie 7453913Sarchiestruct int64_temp { 7553913Sarchie char x; 7653913Sarchie int64_t y; 7753913Sarchie}; 7853913Sarchie 7953913Sarchie#define INT8_ALIGNMENT 1 8053913Sarchie#define INT16_ALIGNMENT ((int)&((struct int16_temp *)0)->y) 8153913Sarchie#define INT32_ALIGNMENT ((int)&((struct int32_temp *)0)->y) 8253913Sarchie#define INT64_ALIGNMENT ((int)&((struct int64_temp *)0)->y) 8353913Sarchie 8464505Sarchie/* Output format for integral types */ 8564505Sarchie#define INT_UNSIGNED 0 8664505Sarchie#define INT_SIGNED 1 8764505Sarchie#define INT_HEX 2 8864505Sarchie 8953913Sarchie/* Type of composite object: struct, array, or fixedarray */ 9053913Sarchieenum comptype { 9153913Sarchie CT_STRUCT, 9253913Sarchie CT_ARRAY, 9353913Sarchie CT_FIXEDARRAY, 9453913Sarchie}; 9553913Sarchie 9653913Sarchie/* Composite types helper functions */ 9753913Sarchiestatic int ng_parse_composite(const struct ng_parse_type *type, 9853913Sarchie const char *s, int *off, const u_char *start, 9953913Sarchie u_char *const buf, int *buflen, enum comptype ctype); 10053913Sarchiestatic int ng_unparse_composite(const struct ng_parse_type *type, 10153913Sarchie const u_char *data, int *off, char *cbuf, int cbuflen, 10253913Sarchie enum comptype ctype); 10353913Sarchiestatic int ng_get_composite_elem_default(const struct ng_parse_type *type, 10453913Sarchie int index, const u_char *start, u_char *buf, 10553913Sarchie int *buflen, enum comptype ctype); 10653913Sarchiestatic int ng_get_composite_len(const struct ng_parse_type *type, 10753913Sarchie const u_char *start, const u_char *buf, 10853913Sarchie enum comptype ctype); 10953913Sarchiestatic const struct ng_parse_type *ng_get_composite_etype(const struct 11053913Sarchie ng_parse_type *type, int index, enum comptype ctype); 11153913Sarchiestatic int ng_parse_get_elem_pad(const struct ng_parse_type *type, 11253913Sarchie int index, enum comptype ctype, int posn); 11353913Sarchie 11453913Sarchie/* Parsing helper functions */ 11553913Sarchiestatic int ng_parse_skip_value(const char *s, int off, int *lenp); 11653913Sarchie 11753913Sarchie/* Poor man's virtual method calls */ 11853913Sarchie#define METHOD(t,m) (ng_get_ ## m ## _method(t)) 11953913Sarchie#define INVOKE(t,m) (*METHOD(t,m)) 12053913Sarchie 12153913Sarchiestatic ng_parse_t *ng_get_parse_method(const struct ng_parse_type *t); 12253913Sarchiestatic ng_unparse_t *ng_get_unparse_method(const struct ng_parse_type *t); 12353913Sarchiestatic ng_getDefault_t *ng_get_getDefault_method(const 12453913Sarchie struct ng_parse_type *t); 12553913Sarchiestatic ng_getAlign_t *ng_get_getAlign_method(const struct ng_parse_type *t); 12653913Sarchie 12753913Sarchie#define ALIGNMENT(t) (METHOD(t, getAlign) == NULL ? \ 12853913Sarchie 0 : INVOKE(t, getAlign)(t)) 12953913Sarchie 13053913Sarchie/* For converting binary to string */ 13153913Sarchie#define NG_PARSE_APPEND(fmt, args...) \ 13253913Sarchie do { \ 13353913Sarchie int len; \ 13453913Sarchie \ 13553913Sarchie len = snprintf((cbuf), (cbuflen), \ 13653913Sarchie fmt , ## args); \ 13753913Sarchie if (len >= (cbuflen)) \ 13853913Sarchie return (ERANGE); \ 13953913Sarchie (cbuf) += len; \ 14053913Sarchie (cbuflen) -= len; \ 14153913Sarchie } while (0) 14253913Sarchie 14353913Sarchie/************************************************************************ 14453913Sarchie PUBLIC FUNCTIONS 14553913Sarchie ************************************************************************/ 14653913Sarchie 14753913Sarchie/* 14853913Sarchie * Convert an ASCII string to binary according to the supplied type descriptor 14953913Sarchie */ 15053913Sarchieint 15153913Sarchieng_parse(const struct ng_parse_type *type, 15253913Sarchie const char *string, int *off, u_char *buf, int *buflen) 15353913Sarchie{ 15453913Sarchie return INVOKE(type, parse)(type, string, off, buf, buf, buflen); 15553913Sarchie} 15653913Sarchie 15753913Sarchie/* 15853913Sarchie * Convert binary to an ASCII string according to the supplied type descriptor 15953913Sarchie */ 16053913Sarchieint 16153913Sarchieng_unparse(const struct ng_parse_type *type, 16253913Sarchie const u_char *data, char *cbuf, int cbuflen) 16353913Sarchie{ 16453913Sarchie int off = 0; 16553913Sarchie 16653913Sarchie return INVOKE(type, unparse)(type, data, &off, cbuf, cbuflen); 16753913Sarchie} 16853913Sarchie 16953913Sarchie/* 17053913Sarchie * Fill in the default value according to the supplied type descriptor 17153913Sarchie */ 17253913Sarchieint 17353913Sarchieng_parse_getDefault(const struct ng_parse_type *type, u_char *buf, int *buflen) 17453913Sarchie{ 17553913Sarchie ng_getDefault_t *const func = METHOD(type, getDefault); 17653913Sarchie 17753913Sarchie if (func == NULL) 17853913Sarchie return (EOPNOTSUPP); 17953913Sarchie return (*func)(type, buf, buf, buflen); 18053913Sarchie} 18153913Sarchie 18253913Sarchie 18353913Sarchie/************************************************************************ 18453913Sarchie STRUCTURE TYPE 18553913Sarchie ************************************************************************/ 18653913Sarchie 18753913Sarchiestatic int 18853913Sarchieng_struct_parse(const struct ng_parse_type *type, 18953913Sarchie const char *s, int *off, const u_char *const start, 19053913Sarchie u_char *const buf, int *buflen) 19153913Sarchie{ 19253913Sarchie return ng_parse_composite(type, s, off, start, buf, buflen, CT_STRUCT); 19353913Sarchie} 19453913Sarchie 19553913Sarchiestatic int 19653913Sarchieng_struct_unparse(const struct ng_parse_type *type, 19753913Sarchie const u_char *data, int *off, char *cbuf, int cbuflen) 19853913Sarchie{ 19953913Sarchie return ng_unparse_composite(type, data, off, cbuf, cbuflen, CT_STRUCT); 20053913Sarchie} 20153913Sarchie 20253913Sarchiestatic int 20353913Sarchieng_struct_getDefault(const struct ng_parse_type *type, 20453913Sarchie const u_char *const start, u_char *buf, int *buflen) 20553913Sarchie{ 20653913Sarchie int off = 0; 20753913Sarchie 20853913Sarchie return ng_parse_composite(type, 20953913Sarchie "{}", &off, start, buf, buflen, CT_STRUCT); 21053913Sarchie} 21153913Sarchie 21253913Sarchiestatic int 21353913Sarchieng_struct_getAlign(const struct ng_parse_type *type) 21453913Sarchie{ 21553913Sarchie const struct ng_parse_struct_field *field; 21653913Sarchie int align = 0; 21753913Sarchie 21897685Sarchie for (field = type->info; field->name != NULL; field++) { 21953913Sarchie int falign = ALIGNMENT(field->type); 22053913Sarchie 22153913Sarchie if (falign > align) 22253913Sarchie align = falign; 22353913Sarchie } 22453913Sarchie return align; 22553913Sarchie} 22653913Sarchie 22753913Sarchieconst struct ng_parse_type ng_parse_struct_type = { 22853913Sarchie NULL, 22953913Sarchie NULL, 23053913Sarchie NULL, 23153913Sarchie ng_struct_parse, 23253913Sarchie ng_struct_unparse, 23353913Sarchie ng_struct_getDefault, 23453913Sarchie ng_struct_getAlign 23553913Sarchie}; 23653913Sarchie 23753913Sarchie/************************************************************************ 23853913Sarchie FIXED LENGTH ARRAY TYPE 23953913Sarchie ************************************************************************/ 24053913Sarchie 24153913Sarchiestatic int 24253913Sarchieng_fixedarray_parse(const struct ng_parse_type *type, 24353913Sarchie const char *s, int *off, const u_char *const start, 24453913Sarchie u_char *const buf, int *buflen) 24553913Sarchie{ 24653913Sarchie return ng_parse_composite(type, 24753913Sarchie s, off, start, buf, buflen, CT_FIXEDARRAY); 24853913Sarchie} 24953913Sarchie 25053913Sarchiestatic int 25153913Sarchieng_fixedarray_unparse(const struct ng_parse_type *type, 25253913Sarchie const u_char *data, int *off, char *cbuf, int cbuflen) 25353913Sarchie{ 25453913Sarchie return ng_unparse_composite(type, 25553913Sarchie data, off, cbuf, cbuflen, CT_FIXEDARRAY); 25653913Sarchie} 25753913Sarchie 25853913Sarchiestatic int 25953913Sarchieng_fixedarray_getDefault(const struct ng_parse_type *type, 26053913Sarchie const u_char *const start, u_char *buf, int *buflen) 26153913Sarchie{ 26253913Sarchie int off = 0; 26353913Sarchie 26453913Sarchie return ng_parse_composite(type, 26553913Sarchie "[]", &off, start, buf, buflen, CT_FIXEDARRAY); 26653913Sarchie} 26753913Sarchie 26853913Sarchiestatic int 26953913Sarchieng_fixedarray_getAlign(const struct ng_parse_type *type) 27053913Sarchie{ 27153913Sarchie const struct ng_parse_fixedarray_info *fi = type->info; 27253913Sarchie 27353913Sarchie return ALIGNMENT(fi->elementType); 27453913Sarchie} 27553913Sarchie 27653913Sarchieconst struct ng_parse_type ng_parse_fixedarray_type = { 27753913Sarchie NULL, 27853913Sarchie NULL, 27953913Sarchie NULL, 28053913Sarchie ng_fixedarray_parse, 28153913Sarchie ng_fixedarray_unparse, 28253913Sarchie ng_fixedarray_getDefault, 28353913Sarchie ng_fixedarray_getAlign 28453913Sarchie}; 28553913Sarchie 28653913Sarchie/************************************************************************ 28753913Sarchie VARIABLE LENGTH ARRAY TYPE 28853913Sarchie ************************************************************************/ 28953913Sarchie 29053913Sarchiestatic int 29153913Sarchieng_array_parse(const struct ng_parse_type *type, 29253913Sarchie const char *s, int *off, const u_char *const start, 29353913Sarchie u_char *const buf, int *buflen) 29453913Sarchie{ 29553913Sarchie return ng_parse_composite(type, s, off, start, buf, buflen, CT_ARRAY); 29653913Sarchie} 29753913Sarchie 29853913Sarchiestatic int 29953913Sarchieng_array_unparse(const struct ng_parse_type *type, 30053913Sarchie const u_char *data, int *off, char *cbuf, int cbuflen) 30153913Sarchie{ 30253913Sarchie return ng_unparse_composite(type, data, off, cbuf, cbuflen, CT_ARRAY); 30353913Sarchie} 30453913Sarchie 30553913Sarchiestatic int 30653913Sarchieng_array_getDefault(const struct ng_parse_type *type, 30753913Sarchie const u_char *const start, u_char *buf, int *buflen) 30853913Sarchie{ 30953913Sarchie int off = 0; 31053913Sarchie 31153913Sarchie return ng_parse_composite(type, 31253913Sarchie "[]", &off, start, buf, buflen, CT_ARRAY); 31353913Sarchie} 31453913Sarchie 31553913Sarchiestatic int 31653913Sarchieng_array_getAlign(const struct ng_parse_type *type) 31753913Sarchie{ 31853913Sarchie const struct ng_parse_array_info *ai = type->info; 31953913Sarchie 32053913Sarchie return ALIGNMENT(ai->elementType); 32153913Sarchie} 32253913Sarchie 32353913Sarchieconst struct ng_parse_type ng_parse_array_type = { 32453913Sarchie NULL, 32553913Sarchie NULL, 32653913Sarchie NULL, 32753913Sarchie ng_array_parse, 32853913Sarchie ng_array_unparse, 32953913Sarchie ng_array_getDefault, 33053913Sarchie ng_array_getAlign 33153913Sarchie}; 33253913Sarchie 33353913Sarchie/************************************************************************ 33453913Sarchie INT8 TYPE 33553913Sarchie ************************************************************************/ 33653913Sarchie 33753913Sarchiestatic int 33853913Sarchieng_int8_parse(const struct ng_parse_type *type, 33953913Sarchie const char *s, int *off, const u_char *const start, 34053913Sarchie u_char *const buf, int *buflen) 34153913Sarchie{ 34253913Sarchie long val; 34353913Sarchie int8_t val8; 34453913Sarchie char *eptr; 34553913Sarchie 34653913Sarchie val = strtol(s + *off, &eptr, 0); 34776860Sjdp if (val < (int8_t)0x80 || val > (u_int8_t)0xff || eptr == s + *off) 34853913Sarchie return (EINVAL); 34953913Sarchie *off = eptr - s; 35053913Sarchie val8 = (int8_t)val; 35153913Sarchie bcopy(&val8, buf, sizeof(int8_t)); 35253913Sarchie *buflen = sizeof(int8_t); 35353913Sarchie return (0); 35453913Sarchie} 35553913Sarchie 35653913Sarchiestatic int 35753913Sarchieng_int8_unparse(const struct ng_parse_type *type, 35853913Sarchie const u_char *data, int *off, char *cbuf, int cbuflen) 35953913Sarchie{ 36064505Sarchie const char *fmt; 36164505Sarchie int fval; 36253913Sarchie int8_t val; 36353913Sarchie 36453913Sarchie bcopy(data + *off, &val, sizeof(int8_t)); 36564505Sarchie switch ((int)type->info) { 36664505Sarchie case INT_SIGNED: 36764505Sarchie fmt = "%d"; 36864505Sarchie fval = val; 36964505Sarchie break; 37064505Sarchie case INT_UNSIGNED: 37164505Sarchie fmt = "%u"; 37264505Sarchie fval = (u_int8_t)val; 37364505Sarchie break; 37464505Sarchie case INT_HEX: 37564505Sarchie fmt = "0x%x"; 37664505Sarchie fval = (u_int8_t)val; 37764505Sarchie break; 37864505Sarchie default: 37987599Sobrien panic("%s: unknown type", __func__); 38083366Sjulian#ifdef RESTARTABLE_PANICS 38183366Sjulian return(0); 38283366Sjulian#endif 38364505Sarchie } 38464505Sarchie NG_PARSE_APPEND(fmt, fval); 38553913Sarchie *off += sizeof(int8_t); 38653913Sarchie return (0); 38753913Sarchie} 38853913Sarchie 38953913Sarchiestatic int 39053913Sarchieng_int8_getDefault(const struct ng_parse_type *type, 39153913Sarchie const u_char *const start, u_char *buf, int *buflen) 39253913Sarchie{ 39353913Sarchie int8_t val; 39453913Sarchie 39553913Sarchie if (*buflen < sizeof(int8_t)) 39653913Sarchie return (ERANGE); 39753913Sarchie val = 0; 39853913Sarchie bcopy(&val, buf, sizeof(int8_t)); 39953913Sarchie *buflen = sizeof(int8_t); 40053913Sarchie return (0); 40153913Sarchie} 40253913Sarchie 40353913Sarchiestatic int 40453913Sarchieng_int8_getAlign(const struct ng_parse_type *type) 40553913Sarchie{ 40653913Sarchie return INT8_ALIGNMENT; 40753913Sarchie} 40853913Sarchie 40953913Sarchieconst struct ng_parse_type ng_parse_int8_type = { 41053913Sarchie NULL, 41164505Sarchie (void *)INT_SIGNED, 41253913Sarchie NULL, 41353913Sarchie ng_int8_parse, 41453913Sarchie ng_int8_unparse, 41553913Sarchie ng_int8_getDefault, 41653913Sarchie ng_int8_getAlign 41753913Sarchie}; 41853913Sarchie 41964505Sarchieconst struct ng_parse_type ng_parse_uint8_type = { 42064505Sarchie &ng_parse_int8_type, 42164505Sarchie (void *)INT_UNSIGNED 42264505Sarchie}; 42364505Sarchie 42464505Sarchieconst struct ng_parse_type ng_parse_hint8_type = { 42564505Sarchie &ng_parse_int8_type, 42664505Sarchie (void *)INT_HEX 42764505Sarchie}; 42864505Sarchie 42953913Sarchie/************************************************************************ 43053913Sarchie INT16 TYPE 43153913Sarchie ************************************************************************/ 43253913Sarchie 43353913Sarchiestatic int 43453913Sarchieng_int16_parse(const struct ng_parse_type *type, 43553913Sarchie const char *s, int *off, const u_char *const start, 43653913Sarchie u_char *const buf, int *buflen) 43753913Sarchie{ 43853913Sarchie long val; 43953913Sarchie int16_t val16; 44053913Sarchie char *eptr; 44153913Sarchie 44253913Sarchie val = strtol(s + *off, &eptr, 0); 44376860Sjdp if (val < (int16_t)0x8000 44476860Sjdp || val > (u_int16_t)0xffff || eptr == s + *off) 44553913Sarchie return (EINVAL); 44653913Sarchie *off = eptr - s; 44753913Sarchie val16 = (int16_t)val; 44853913Sarchie bcopy(&val16, buf, sizeof(int16_t)); 44953913Sarchie *buflen = sizeof(int16_t); 45053913Sarchie return (0); 45153913Sarchie} 45253913Sarchie 45353913Sarchiestatic int 45453913Sarchieng_int16_unparse(const struct ng_parse_type *type, 45553913Sarchie const u_char *data, int *off, char *cbuf, int cbuflen) 45653913Sarchie{ 45764505Sarchie const char *fmt; 45864505Sarchie int fval; 45953913Sarchie int16_t val; 46053913Sarchie 46153913Sarchie bcopy(data + *off, &val, sizeof(int16_t)); 46264505Sarchie switch ((int)type->info) { 46364505Sarchie case INT_SIGNED: 46464505Sarchie fmt = "%d"; 46564505Sarchie fval = val; 46664505Sarchie break; 46764505Sarchie case INT_UNSIGNED: 46864505Sarchie fmt = "%u"; 46964505Sarchie fval = (u_int16_t)val; 47064505Sarchie break; 47164505Sarchie case INT_HEX: 47264505Sarchie fmt = "0x%x"; 47364505Sarchie fval = (u_int16_t)val; 47464505Sarchie break; 47564505Sarchie default: 47687599Sobrien panic("%s: unknown type", __func__); 47783366Sjulian#ifdef RESTARTABLE_PANICS 47883366Sjulian return(0); 47983366Sjulian#endif 48064505Sarchie } 48164505Sarchie NG_PARSE_APPEND(fmt, fval); 48253913Sarchie *off += sizeof(int16_t); 48353913Sarchie return (0); 48453913Sarchie} 48553913Sarchie 48653913Sarchiestatic int 48753913Sarchieng_int16_getDefault(const struct ng_parse_type *type, 48853913Sarchie const u_char *const start, u_char *buf, int *buflen) 48953913Sarchie{ 49053913Sarchie int16_t val; 49153913Sarchie 49253913Sarchie if (*buflen < sizeof(int16_t)) 49353913Sarchie return (ERANGE); 49453913Sarchie val = 0; 49553913Sarchie bcopy(&val, buf, sizeof(int16_t)); 49653913Sarchie *buflen = sizeof(int16_t); 49753913Sarchie return (0); 49853913Sarchie} 49953913Sarchie 50053913Sarchiestatic int 50153913Sarchieng_int16_getAlign(const struct ng_parse_type *type) 50253913Sarchie{ 50353913Sarchie return INT16_ALIGNMENT; 50453913Sarchie} 50553913Sarchie 50653913Sarchieconst struct ng_parse_type ng_parse_int16_type = { 50753913Sarchie NULL, 50864505Sarchie (void *)INT_SIGNED, 50953913Sarchie NULL, 51053913Sarchie ng_int16_parse, 51153913Sarchie ng_int16_unparse, 51253913Sarchie ng_int16_getDefault, 51353913Sarchie ng_int16_getAlign 51453913Sarchie}; 51553913Sarchie 51664505Sarchieconst struct ng_parse_type ng_parse_uint16_type = { 51764505Sarchie &ng_parse_int16_type, 51864505Sarchie (void *)INT_UNSIGNED 51964505Sarchie}; 52064505Sarchie 52164505Sarchieconst struct ng_parse_type ng_parse_hint16_type = { 52264505Sarchie &ng_parse_int16_type, 52364505Sarchie (void *)INT_HEX 52464505Sarchie}; 52564505Sarchie 52653913Sarchie/************************************************************************ 52753913Sarchie INT32 TYPE 52853913Sarchie ************************************************************************/ 52953913Sarchie 53053913Sarchiestatic int 53153913Sarchieng_int32_parse(const struct ng_parse_type *type, 53253913Sarchie const char *s, int *off, const u_char *const start, 53353913Sarchie u_char *const buf, int *buflen) 53453913Sarchie{ 53553913Sarchie long val; /* assumes long is at least 32 bits */ 53653913Sarchie int32_t val32; 53753913Sarchie char *eptr; 53853913Sarchie 53953913Sarchie val = strtol(s + *off, &eptr, 0); 54076860Sjdp if (val < (int32_t)0x80000000 54176860Sjdp || val > (u_int32_t)0xffffffff || eptr == s + *off) 54253913Sarchie return (EINVAL); 54353913Sarchie *off = eptr - s; 54453913Sarchie val32 = (int32_t)val; 54553913Sarchie bcopy(&val32, buf, sizeof(int32_t)); 54653913Sarchie *buflen = sizeof(int32_t); 54753913Sarchie return (0); 54853913Sarchie} 54953913Sarchie 55053913Sarchiestatic int 55153913Sarchieng_int32_unparse(const struct ng_parse_type *type, 55253913Sarchie const u_char *data, int *off, char *cbuf, int cbuflen) 55353913Sarchie{ 55464505Sarchie const char *fmt; 55564505Sarchie long fval; 55653913Sarchie int32_t val; 55753913Sarchie 55853913Sarchie bcopy(data + *off, &val, sizeof(int32_t)); 55964505Sarchie switch ((int)type->info) { 56064505Sarchie case INT_SIGNED: 56164505Sarchie fmt = "%ld"; 56264505Sarchie fval = val; 56364505Sarchie break; 56464505Sarchie case INT_UNSIGNED: 56564505Sarchie fmt = "%lu"; 56664505Sarchie fval = (u_int32_t)val; 56764505Sarchie break; 56864505Sarchie case INT_HEX: 56964505Sarchie fmt = "0x%lx"; 57064505Sarchie fval = (u_int32_t)val; 57164505Sarchie break; 57264505Sarchie default: 57387599Sobrien panic("%s: unknown type", __func__); 57483366Sjulian#ifdef RESTARTABLE_PANICS 57583366Sjulian return(0); 57683366Sjulian#endif 57764505Sarchie } 57864505Sarchie NG_PARSE_APPEND(fmt, fval); 57953913Sarchie *off += sizeof(int32_t); 58053913Sarchie return (0); 58153913Sarchie} 58253913Sarchie 58353913Sarchiestatic int 58453913Sarchieng_int32_getDefault(const struct ng_parse_type *type, 58553913Sarchie const u_char *const start, u_char *buf, int *buflen) 58653913Sarchie{ 58753913Sarchie int32_t val; 58853913Sarchie 58953913Sarchie if (*buflen < sizeof(int32_t)) 59053913Sarchie return (ERANGE); 59153913Sarchie val = 0; 59253913Sarchie bcopy(&val, buf, sizeof(int32_t)); 59353913Sarchie *buflen = sizeof(int32_t); 59453913Sarchie return (0); 59553913Sarchie} 59653913Sarchie 59753913Sarchiestatic int 59853913Sarchieng_int32_getAlign(const struct ng_parse_type *type) 59953913Sarchie{ 60053913Sarchie return INT32_ALIGNMENT; 60153913Sarchie} 60253913Sarchie 60353913Sarchieconst struct ng_parse_type ng_parse_int32_type = { 60453913Sarchie NULL, 60564505Sarchie (void *)INT_SIGNED, 60653913Sarchie NULL, 60753913Sarchie ng_int32_parse, 60853913Sarchie ng_int32_unparse, 60953913Sarchie ng_int32_getDefault, 61053913Sarchie ng_int32_getAlign 61153913Sarchie}; 61253913Sarchie 61364505Sarchieconst struct ng_parse_type ng_parse_uint32_type = { 61464505Sarchie &ng_parse_int32_type, 61564505Sarchie (void *)INT_UNSIGNED 61664505Sarchie}; 61764505Sarchie 61864505Sarchieconst struct ng_parse_type ng_parse_hint32_type = { 61964505Sarchie &ng_parse_int32_type, 62064505Sarchie (void *)INT_HEX 62164505Sarchie}; 62264505Sarchie 62353913Sarchie/************************************************************************ 62453913Sarchie INT64 TYPE 62553913Sarchie ************************************************************************/ 62653913Sarchie 62753913Sarchiestatic int 62853913Sarchieng_int64_parse(const struct ng_parse_type *type, 62953913Sarchie const char *s, int *off, const u_char *const start, 63053913Sarchie u_char *const buf, int *buflen) 63153913Sarchie{ 63253913Sarchie quad_t val; 63353913Sarchie int64_t val64; 63453913Sarchie char *eptr; 63553913Sarchie 63653913Sarchie val = strtoq(s + *off, &eptr, 0); 63753913Sarchie if (eptr == s + *off) 63853913Sarchie return (EINVAL); 63953913Sarchie *off = eptr - s; 64053913Sarchie val64 = (int64_t)val; 64153913Sarchie bcopy(&val64, buf, sizeof(int64_t)); 64253913Sarchie *buflen = sizeof(int64_t); 64353913Sarchie return (0); 64453913Sarchie} 64553913Sarchie 64653913Sarchiestatic int 64753913Sarchieng_int64_unparse(const struct ng_parse_type *type, 64853913Sarchie const u_char *data, int *off, char *cbuf, int cbuflen) 64953913Sarchie{ 65064505Sarchie const char *fmt; 65164505Sarchie long long fval; 65253913Sarchie int64_t val; 65353913Sarchie 65453913Sarchie bcopy(data + *off, &val, sizeof(int64_t)); 65564505Sarchie switch ((int)type->info) { 65664505Sarchie case INT_SIGNED: 65764505Sarchie fmt = "%lld"; 65864505Sarchie fval = val; 65964505Sarchie break; 66064505Sarchie case INT_UNSIGNED: 66164505Sarchie fmt = "%llu"; 66264505Sarchie fval = (u_int64_t)val; 66364505Sarchie break; 66464505Sarchie case INT_HEX: 66564505Sarchie fmt = "0x%llx"; 66664505Sarchie fval = (u_int64_t)val; 66764505Sarchie break; 66864505Sarchie default: 66987599Sobrien panic("%s: unknown type", __func__); 67083366Sjulian#ifdef RESTARTABLE_PANICS 67183366Sjulian return(0); 67283366Sjulian#endif 67364505Sarchie } 67464505Sarchie NG_PARSE_APPEND(fmt, fval); 67553913Sarchie *off += sizeof(int64_t); 67653913Sarchie return (0); 67753913Sarchie} 67853913Sarchie 67953913Sarchiestatic int 68053913Sarchieng_int64_getDefault(const struct ng_parse_type *type, 68153913Sarchie const u_char *const start, u_char *buf, int *buflen) 68253913Sarchie{ 68353913Sarchie int64_t val; 68453913Sarchie 68553913Sarchie if (*buflen < sizeof(int64_t)) 68653913Sarchie return (ERANGE); 68753913Sarchie val = 0; 68853913Sarchie bcopy(&val, buf, sizeof(int64_t)); 68953913Sarchie *buflen = sizeof(int64_t); 69053913Sarchie return (0); 69153913Sarchie} 69253913Sarchie 69353913Sarchiestatic int 69453913Sarchieng_int64_getAlign(const struct ng_parse_type *type) 69553913Sarchie{ 69653913Sarchie return INT64_ALIGNMENT; 69753913Sarchie} 69853913Sarchie 69953913Sarchieconst struct ng_parse_type ng_parse_int64_type = { 70053913Sarchie NULL, 70164505Sarchie (void *)INT_SIGNED, 70253913Sarchie NULL, 70353913Sarchie ng_int64_parse, 70453913Sarchie ng_int64_unparse, 70553913Sarchie ng_int64_getDefault, 70653913Sarchie ng_int64_getAlign 70753913Sarchie}; 70853913Sarchie 70964505Sarchieconst struct ng_parse_type ng_parse_uint64_type = { 71064505Sarchie &ng_parse_int64_type, 71164505Sarchie (void *)INT_UNSIGNED 71264505Sarchie}; 71364505Sarchie 71464505Sarchieconst struct ng_parse_type ng_parse_hint64_type = { 71564505Sarchie &ng_parse_int64_type, 71664505Sarchie (void *)INT_HEX 71764505Sarchie}; 71864505Sarchie 71953913Sarchie/************************************************************************ 72053913Sarchie STRING TYPE 72153913Sarchie ************************************************************************/ 72253913Sarchie 72353913Sarchiestatic int 72453913Sarchieng_string_parse(const struct ng_parse_type *type, 72553913Sarchie const char *s, int *off, const u_char *const start, 72653913Sarchie u_char *const buf, int *buflen) 72753913Sarchie{ 72853913Sarchie char *sval; 72953913Sarchie int len; 73068845Sbrian int slen; 73153913Sarchie 73268845Sbrian if ((sval = ng_get_string_token(s, off, &len, &slen)) == NULL) 73353913Sarchie return (EINVAL); 73453913Sarchie *off += len; 73568845Sbrian bcopy(sval, buf, slen + 1); 73670870Sjulian FREE(sval, M_NETGRAPH_PARSE); 73768845Sbrian *buflen = slen + 1; 73853913Sarchie return (0); 73953913Sarchie} 74053913Sarchie 74153913Sarchiestatic int 74253913Sarchieng_string_unparse(const struct ng_parse_type *type, 74353913Sarchie const u_char *data, int *off, char *cbuf, int cbuflen) 74453913Sarchie{ 74553913Sarchie const char *const raw = (const char *)data + *off; 74668845Sbrian char *const s = ng_encode_string(raw, strlen(raw)); 74753913Sarchie 74853913Sarchie if (s == NULL) 74953913Sarchie return (ENOMEM); 75053913Sarchie NG_PARSE_APPEND("%s", s); 75153913Sarchie *off += strlen(raw) + 1; 75270870Sjulian FREE(s, M_NETGRAPH_PARSE); 75353913Sarchie return (0); 75453913Sarchie} 75553913Sarchie 75653913Sarchiestatic int 75753913Sarchieng_string_getDefault(const struct ng_parse_type *type, 75853913Sarchie const u_char *const start, u_char *buf, int *buflen) 75953913Sarchie{ 76053913Sarchie 76153913Sarchie if (*buflen < 1) 76253913Sarchie return (ERANGE); 76353913Sarchie buf[0] = (u_char)'\0'; 76453913Sarchie *buflen = 1; 76553913Sarchie return (0); 76653913Sarchie} 76753913Sarchie 76853913Sarchieconst struct ng_parse_type ng_parse_string_type = { 76953913Sarchie NULL, 77053913Sarchie NULL, 77153913Sarchie NULL, 77253913Sarchie ng_string_parse, 77353913Sarchie ng_string_unparse, 77453913Sarchie ng_string_getDefault, 77553913Sarchie NULL 77653913Sarchie}; 77753913Sarchie 77853913Sarchie/************************************************************************ 77953913Sarchie FIXED BUFFER STRING TYPE 78053913Sarchie ************************************************************************/ 78153913Sarchie 78253913Sarchiestatic int 78353913Sarchieng_fixedstring_parse(const struct ng_parse_type *type, 78453913Sarchie const char *s, int *off, const u_char *const start, 78553913Sarchie u_char *const buf, int *buflen) 78653913Sarchie{ 78758011Sarchie const struct ng_parse_fixedstring_info *const fi = type->info; 78853913Sarchie char *sval; 78953913Sarchie int len; 79068845Sbrian int slen; 79153913Sarchie 79268845Sbrian if ((sval = ng_get_string_token(s, off, &len, &slen)) == NULL) 79353913Sarchie return (EINVAL); 79468845Sbrian if (slen + 1 > fi->bufSize) 79553913Sarchie return (E2BIG); 79653913Sarchie *off += len; 79768845Sbrian bcopy(sval, buf, slen); 79870870Sjulian FREE(sval, M_NETGRAPH_PARSE); 79968845Sbrian bzero(buf + slen, fi->bufSize - slen); 80053913Sarchie *buflen = fi->bufSize; 80153913Sarchie return (0); 80253913Sarchie} 80353913Sarchie 80453913Sarchiestatic int 80553913Sarchieng_fixedstring_unparse(const struct ng_parse_type *type, 80653913Sarchie const u_char *data, int *off, char *cbuf, int cbuflen) 80753913Sarchie{ 80858011Sarchie const struct ng_parse_fixedstring_info *const fi = type->info; 80953913Sarchie int error, temp = *off; 81053913Sarchie 81153913Sarchie if ((error = ng_string_unparse(type, data, &temp, cbuf, cbuflen)) != 0) 81253913Sarchie return (error); 81353913Sarchie *off += fi->bufSize; 81453913Sarchie return (0); 81553913Sarchie} 81653913Sarchie 81753913Sarchiestatic int 81853913Sarchieng_fixedstring_getDefault(const struct ng_parse_type *type, 81953913Sarchie const u_char *const start, u_char *buf, int *buflen) 82053913Sarchie{ 82158011Sarchie const struct ng_parse_fixedstring_info *const fi = type->info; 82253913Sarchie 82353913Sarchie if (*buflen < fi->bufSize) 82453913Sarchie return (ERANGE); 82553913Sarchie bzero(buf, fi->bufSize); 82653913Sarchie *buflen = fi->bufSize; 82753913Sarchie return (0); 82853913Sarchie} 82953913Sarchie 83053913Sarchieconst struct ng_parse_type ng_parse_fixedstring_type = { 83153913Sarchie NULL, 83253913Sarchie NULL, 83353913Sarchie NULL, 83453913Sarchie ng_fixedstring_parse, 83553913Sarchie ng_fixedstring_unparse, 83653913Sarchie ng_fixedstring_getDefault, 83753913Sarchie NULL 83853913Sarchie}; 83953913Sarchie 84058011Sarchieconst struct ng_parse_fixedstring_info ng_parse_nodebuf_info = { 84153913Sarchie NG_NODELEN + 1 84253913Sarchie}; 84353913Sarchieconst struct ng_parse_type ng_parse_nodebuf_type = { 84453913Sarchie &ng_parse_fixedstring_type, 84553913Sarchie &ng_parse_nodebuf_info 84653913Sarchie}; 84753913Sarchie 84858011Sarchieconst struct ng_parse_fixedstring_info ng_parse_hookbuf_info = { 84953913Sarchie NG_HOOKLEN + 1 85053913Sarchie}; 85153913Sarchieconst struct ng_parse_type ng_parse_hookbuf_type = { 85253913Sarchie &ng_parse_fixedstring_type, 85353913Sarchie &ng_parse_hookbuf_info 85453913Sarchie}; 85553913Sarchie 85658011Sarchieconst struct ng_parse_fixedstring_info ng_parse_pathbuf_info = { 85753913Sarchie NG_PATHLEN + 1 85853913Sarchie}; 85953913Sarchieconst struct ng_parse_type ng_parse_pathbuf_type = { 86053913Sarchie &ng_parse_fixedstring_type, 86153913Sarchie &ng_parse_pathbuf_info 86253913Sarchie}; 86353913Sarchie 86458011Sarchieconst struct ng_parse_fixedstring_info ng_parse_typebuf_info = { 86553913Sarchie NG_TYPELEN + 1 86653913Sarchie}; 86753913Sarchieconst struct ng_parse_type ng_parse_typebuf_type = { 86853913Sarchie &ng_parse_fixedstring_type, 86953913Sarchie &ng_parse_typebuf_info 87053913Sarchie}; 87153913Sarchie 87258011Sarchieconst struct ng_parse_fixedstring_info ng_parse_cmdbuf_info = { 87353913Sarchie NG_CMDSTRLEN + 1 87453913Sarchie}; 87553913Sarchieconst struct ng_parse_type ng_parse_cmdbuf_type = { 87653913Sarchie &ng_parse_fixedstring_type, 87753913Sarchie &ng_parse_cmdbuf_info 87853913Sarchie}; 87953913Sarchie 88053913Sarchie/************************************************************************ 88168845Sbrian EXPLICITLY SIZED STRING TYPE 88268845Sbrian ************************************************************************/ 88368845Sbrian 88468845Sbrianstatic int 88568845Sbrianng_sizedstring_parse(const struct ng_parse_type *type, 88668845Sbrian const char *s, int *off, const u_char *const start, 88768845Sbrian u_char *const buf, int *buflen) 88868845Sbrian{ 88968845Sbrian char *sval; 89068845Sbrian int len; 89168845Sbrian int slen; 89268845Sbrian 89368845Sbrian if ((sval = ng_get_string_token(s, off, &len, &slen)) == NULL) 89468845Sbrian return (EINVAL); 89568845Sbrian if (slen > 0xffff) 89668845Sbrian return (EINVAL); 89768845Sbrian *off += len; 89868845Sbrian *((u_int16_t *)buf) = (u_int16_t)slen; 89968845Sbrian bcopy(sval, buf + 2, slen); 90070870Sjulian FREE(sval, M_NETGRAPH_PARSE); 90168845Sbrian *buflen = 2 + slen; 90268845Sbrian return (0); 90368845Sbrian} 90468845Sbrian 90568845Sbrianstatic int 90668845Sbrianng_sizedstring_unparse(const struct ng_parse_type *type, 90768845Sbrian const u_char *data, int *off, char *cbuf, int cbuflen) 90868845Sbrian{ 90968845Sbrian const char *const raw = (const char *)data + *off + 2; 91068845Sbrian const int slen = *((const u_int16_t *)(data + *off)); 91168845Sbrian char *const s = ng_encode_string(raw, slen); 91268845Sbrian 91368845Sbrian if (s == NULL) 91468845Sbrian return (ENOMEM); 91568845Sbrian NG_PARSE_APPEND("%s", s); 91670870Sjulian FREE(s, M_NETGRAPH_PARSE); 91768845Sbrian *off += slen + 2; 91868845Sbrian return (0); 91968845Sbrian} 92068845Sbrian 92168845Sbrianstatic int 92268845Sbrianng_sizedstring_getDefault(const struct ng_parse_type *type, 92368845Sbrian const u_char *const start, u_char *buf, int *buflen) 92468845Sbrian{ 92568845Sbrian if (*buflen < 2) 92668845Sbrian return (ERANGE); 92768845Sbrian bzero(buf, 2); 92868845Sbrian *buflen = 2; 92968845Sbrian return (0); 93068845Sbrian} 93168845Sbrian 93268845Sbrianconst struct ng_parse_type ng_parse_sizedstring_type = { 93368845Sbrian NULL, 93468845Sbrian NULL, 93568845Sbrian NULL, 93668845Sbrian ng_sizedstring_parse, 93768845Sbrian ng_sizedstring_unparse, 93868845Sbrian ng_sizedstring_getDefault, 93968845Sbrian NULL 94068845Sbrian}; 94168845Sbrian 94268845Sbrian/************************************************************************ 94353913Sarchie IP ADDRESS TYPE 94453913Sarchie ************************************************************************/ 94553913Sarchie 94653913Sarchiestatic int 94753913Sarchieng_ipaddr_parse(const struct ng_parse_type *type, 94853913Sarchie const char *s, int *off, const u_char *const start, 94953913Sarchie u_char *const buf, int *buflen) 95053913Sarchie{ 95153913Sarchie int i, error; 95253913Sarchie 95353913Sarchie for (i = 0; i < 4; i++) { 95453913Sarchie if ((error = ng_int8_parse(&ng_parse_int8_type, 95553913Sarchie s, off, start, buf + i, buflen)) != 0) 95653913Sarchie return (error); 95753913Sarchie if (i < 3 && s[*off] != '.') 95853913Sarchie return (EINVAL); 95953913Sarchie (*off)++; 96053913Sarchie } 96153913Sarchie *buflen = 4; 96253913Sarchie return (0); 96353913Sarchie} 96453913Sarchie 96553913Sarchiestatic int 96653913Sarchieng_ipaddr_unparse(const struct ng_parse_type *type, 96753913Sarchie const u_char *data, int *off, char *cbuf, int cbuflen) 96853913Sarchie{ 96953913Sarchie struct in_addr ip; 97053913Sarchie 97153913Sarchie bcopy(data + *off, &ip, sizeof(ip)); 97253913Sarchie NG_PARSE_APPEND("%d.%d.%d.%d", ((u_char *)&ip)[0], 97353913Sarchie ((u_char *)&ip)[1], ((u_char *)&ip)[2], ((u_char *)&ip)[3]); 97453913Sarchie *off += sizeof(ip); 97553913Sarchie return (0); 97653913Sarchie} 97753913Sarchie 97853913Sarchiestatic int 97953913Sarchieng_ipaddr_getDefault(const struct ng_parse_type *type, 98053913Sarchie const u_char *const start, u_char *buf, int *buflen) 98153913Sarchie{ 98253913Sarchie struct in_addr ip = { 0 }; 98353913Sarchie 98453913Sarchie if (*buflen < sizeof(ip)) 98553913Sarchie return (ERANGE); 98653913Sarchie bcopy(&ip, buf, sizeof(ip)); 98753913Sarchie *buflen = sizeof(ip); 98853913Sarchie return (0); 98953913Sarchie} 99053913Sarchie 99153913Sarchieconst struct ng_parse_type ng_parse_ipaddr_type = { 99253913Sarchie NULL, 99353913Sarchie NULL, 99453913Sarchie NULL, 99553913Sarchie ng_ipaddr_parse, 99653913Sarchie ng_ipaddr_unparse, 99753913Sarchie ng_ipaddr_getDefault, 99853913Sarchie ng_int32_getAlign 99953913Sarchie}; 100053913Sarchie 100153913Sarchie/************************************************************************ 100253913Sarchie BYTE ARRAY TYPE 100353913Sarchie ************************************************************************/ 100453913Sarchie 100553913Sarchie/* Get the length of a byte array */ 100653913Sarchiestatic int 100753913Sarchieng_parse_bytearray_subtype_getLength(const struct ng_parse_type *type, 100853913Sarchie const u_char *start, const u_char *buf) 100953913Sarchie{ 101053913Sarchie ng_parse_array_getLength_t *const getLength = type->private; 101153913Sarchie 101253913Sarchie return (*getLength)(type, start, buf); 101353913Sarchie} 101453913Sarchie 101564505Sarchie/* Byte array element type is hex int8 */ 101653913Sarchiestatic const struct ng_parse_array_info ng_parse_bytearray_subtype_info = { 101764505Sarchie &ng_parse_hint8_type, 101853913Sarchie &ng_parse_bytearray_subtype_getLength, 101953913Sarchie NULL 102053913Sarchie}; 102153913Sarchiestatic const struct ng_parse_type ng_parse_bytearray_subtype = { 102253913Sarchie &ng_parse_array_type, 102353913Sarchie &ng_parse_bytearray_subtype_info 102453913Sarchie}; 102553913Sarchie 102653913Sarchiestatic int 102753913Sarchieng_bytearray_parse(const struct ng_parse_type *type, 102853913Sarchie const char *s, int *off, const u_char *const start, 102953913Sarchie u_char *const buf, int *buflen) 103053913Sarchie{ 103153913Sarchie char *str; 103253913Sarchie int toklen; 103368845Sbrian int slen; 103453913Sarchie 103553913Sarchie /* We accept either an array of bytes or a string constant */ 103668845Sbrian if ((str = ng_get_string_token(s, off, &toklen, &slen)) != NULL) { 103753913Sarchie ng_parse_array_getLength_t *const getLength = type->info; 103868845Sbrian int arraylen; 103953913Sarchie 104053913Sarchie arraylen = (*getLength)(type, start, buf); 104153913Sarchie if (arraylen > *buflen) { 104270870Sjulian FREE(str, M_NETGRAPH_PARSE); 104353913Sarchie return (ERANGE); 104453913Sarchie } 104553913Sarchie if (slen > arraylen) { 104670870Sjulian FREE(str, M_NETGRAPH_PARSE); 104753913Sarchie return (E2BIG); 104853913Sarchie } 104953913Sarchie bcopy(str, buf, slen); 105053913Sarchie bzero(buf + slen, arraylen - slen); 105170870Sjulian FREE(str, M_NETGRAPH_PARSE); 105253913Sarchie *off += toklen; 105353913Sarchie *buflen = arraylen; 105453913Sarchie return (0); 105553913Sarchie } else { 105653913Sarchie struct ng_parse_type subtype; 105753913Sarchie 105853913Sarchie subtype = ng_parse_bytearray_subtype; 105953913Sarchie (const void *)subtype.private = type->info; 106053913Sarchie return ng_array_parse(&subtype, s, off, start, buf, buflen); 106153913Sarchie } 106253913Sarchie} 106353913Sarchie 106453913Sarchiestatic int 106553913Sarchieng_bytearray_unparse(const struct ng_parse_type *type, 106653913Sarchie const u_char *data, int *off, char *cbuf, int cbuflen) 106753913Sarchie{ 106853913Sarchie struct ng_parse_type subtype; 106953913Sarchie 107053913Sarchie subtype = ng_parse_bytearray_subtype; 107153913Sarchie (const void *)subtype.private = type->info; 107253913Sarchie return ng_array_unparse(&subtype, data, off, cbuf, cbuflen); 107353913Sarchie} 107453913Sarchie 107553913Sarchiestatic int 107653913Sarchieng_bytearray_getDefault(const struct ng_parse_type *type, 107753913Sarchie const u_char *const start, u_char *buf, int *buflen) 107853913Sarchie{ 107953913Sarchie struct ng_parse_type subtype; 108053913Sarchie 108153913Sarchie subtype = ng_parse_bytearray_subtype; 108253913Sarchie (const void *)subtype.private = type->info; 108353913Sarchie return ng_array_getDefault(&subtype, start, buf, buflen); 108453913Sarchie} 108553913Sarchie 108653913Sarchieconst struct ng_parse_type ng_parse_bytearray_type = { 108753913Sarchie NULL, 108853913Sarchie NULL, 108953913Sarchie NULL, 109053913Sarchie ng_bytearray_parse, 109153913Sarchie ng_bytearray_unparse, 109253913Sarchie ng_bytearray_getDefault, 109353913Sarchie NULL 109453913Sarchie}; 109553913Sarchie 109653913Sarchie/************************************************************************ 109753913Sarchie STRUCT NG_MESG TYPE 109853913Sarchie ************************************************************************/ 109953913Sarchie 110053913Sarchie/* Get msg->header.arglen when "buf" is pointing to msg->data */ 110153913Sarchiestatic int 110253913Sarchieng_parse_ng_mesg_getLength(const struct ng_parse_type *type, 110353913Sarchie const u_char *start, const u_char *buf) 110453913Sarchie{ 110553913Sarchie const struct ng_mesg *msg; 110653913Sarchie 110753913Sarchie msg = (const struct ng_mesg *)(buf - sizeof(*msg)); 110853913Sarchie return msg->header.arglen; 110953913Sarchie} 111053913Sarchie 111153913Sarchie/* Type for the variable length data portion of a struct ng_mesg */ 111253913Sarchiestatic const struct ng_parse_type ng_msg_data_type = { 111353913Sarchie &ng_parse_bytearray_type, 111453913Sarchie &ng_parse_ng_mesg_getLength 111553913Sarchie}; 111653913Sarchie 111753913Sarchie/* Type for the entire struct ng_mesg header with data section */ 111897685Sarchiestatic const struct ng_parse_struct_field ng_parse_ng_mesg_type_fields[] 111997685Sarchie = NG_GENERIC_NG_MESG_INFO(&ng_msg_data_type); 112053913Sarchieconst struct ng_parse_type ng_parse_ng_mesg_type = { 112153913Sarchie &ng_parse_struct_type, 112297685Sarchie &ng_parse_ng_mesg_type_fields, 112353913Sarchie}; 112453913Sarchie 112553913Sarchie/************************************************************************ 112653913Sarchie COMPOSITE HELPER ROUTINES 112753913Sarchie ************************************************************************/ 112853913Sarchie 112953913Sarchie/* 113053913Sarchie * Convert a structure or array from ASCII to binary 113153913Sarchie */ 113253913Sarchiestatic int 113353913Sarchieng_parse_composite(const struct ng_parse_type *type, const char *s, 113453913Sarchie int *off, const u_char *const start, u_char *const buf, int *buflen, 113553913Sarchie const enum comptype ctype) 113653913Sarchie{ 113753913Sarchie const int num = ng_get_composite_len(type, start, buf, ctype); 113853913Sarchie int nextIndex = 0; /* next implicit array index */ 113953913Sarchie u_int index; /* field or element index */ 114053913Sarchie int *foff; /* field value offsets in string */ 114153913Sarchie int align, len, blen, error = 0; 114253913Sarchie 114353913Sarchie /* Initialize */ 114470870Sjulian MALLOC(foff, int *, num * sizeof(*foff), M_NETGRAPH_PARSE, M_NOWAIT | M_ZERO); 114553913Sarchie if (foff == NULL) { 114653913Sarchie error = ENOMEM; 114753913Sarchie goto done; 114853913Sarchie } 114953913Sarchie 115053913Sarchie /* Get opening brace/bracket */ 115153913Sarchie if (ng_parse_get_token(s, off, &len) 115253913Sarchie != (ctype == CT_STRUCT ? T_LBRACE : T_LBRACKET)) { 115353913Sarchie error = EINVAL; 115453913Sarchie goto done; 115553913Sarchie } 115653913Sarchie *off += len; 115753913Sarchie 115853913Sarchie /* Get individual element value positions in the string */ 115953913Sarchie for (;;) { 116053913Sarchie enum ng_parse_token tok; 116153913Sarchie 116253913Sarchie /* Check for closing brace/bracket */ 116353913Sarchie tok = ng_parse_get_token(s, off, &len); 116453913Sarchie if (tok == (ctype == CT_STRUCT ? T_RBRACE : T_RBRACKET)) { 116553913Sarchie *off += len; 116653913Sarchie break; 116753913Sarchie } 116853913Sarchie 116953913Sarchie /* For arrays, the 'name' (ie, index) is optional, so 117053913Sarchie distinguish name from values by seeing if the next 117153913Sarchie token is an equals sign */ 117253913Sarchie if (ctype != CT_STRUCT) { 117353913Sarchie int len2, off2; 117453913Sarchie char *eptr; 117553913Sarchie 117653913Sarchie /* If an opening brace/bracket, index is implied */ 117753913Sarchie if (tok == T_LBRACE || tok == T_LBRACKET) { 117853913Sarchie index = nextIndex++; 117953913Sarchie goto gotIndex; 118053913Sarchie } 118153913Sarchie 118253913Sarchie /* Might be an index, might be a value, either way... */ 118353913Sarchie if (tok != T_WORD) { 118453913Sarchie error = EINVAL; 118553913Sarchie goto done; 118653913Sarchie } 118753913Sarchie 118853913Sarchie /* If no equals sign follows, index is implied */ 118953913Sarchie off2 = *off + len; 119053913Sarchie if (ng_parse_get_token(s, &off2, &len2) != T_EQUALS) { 119153913Sarchie index = nextIndex++; 119253913Sarchie goto gotIndex; 119353913Sarchie } 119453913Sarchie 119553913Sarchie /* Index was specified explicitly; parse it */ 119653913Sarchie index = (u_int)strtoul(s + *off, &eptr, 0); 119753913Sarchie if (index < 0 || eptr - (s + *off) != len) { 119853913Sarchie error = EINVAL; 119953913Sarchie goto done; 120053913Sarchie } 120153913Sarchie nextIndex = index + 1; 120253913Sarchie *off += len + len2; 120353913Sarchie } else { /* a structure field */ 120497685Sarchie const struct ng_parse_struct_field *const 120597685Sarchie fields = type->info; 120653913Sarchie 120753913Sarchie /* Find the field by name (required) in field list */ 120853913Sarchie if (tok != T_WORD) { 120953913Sarchie error = EINVAL; 121053913Sarchie goto done; 121153913Sarchie } 121253913Sarchie for (index = 0; index < num; index++) { 121397685Sarchie const struct ng_parse_struct_field *const 121497685Sarchie field = &fields[index]; 121597685Sarchie 121653913Sarchie if (strncmp(&s[*off], field->name, len) == 0 121753913Sarchie && field->name[len] == '\0') 121853913Sarchie break; 121953913Sarchie } 122053913Sarchie if (index == num) { 122153913Sarchie error = ENOENT; 122253913Sarchie goto done; 122353913Sarchie } 122453913Sarchie *off += len; 122553913Sarchie 122653913Sarchie /* Get equals sign */ 122753913Sarchie if (ng_parse_get_token(s, off, &len) != T_EQUALS) { 122853913Sarchie error = EINVAL; 122953913Sarchie goto done; 123053913Sarchie } 123153913Sarchie *off += len; 123253913Sarchie } 123397229SpetergotIndex: 123453913Sarchie 123553913Sarchie /* Check array index */ 123653913Sarchie if (index >= num) { 123753913Sarchie error = E2BIG; 123853913Sarchie goto done; 123953913Sarchie } 124053913Sarchie 124153913Sarchie /* Save value's position and skip over it for now */ 124253913Sarchie if (foff[index] != 0) { 124353913Sarchie error = EALREADY; /* duplicate */ 124453913Sarchie goto done; 124553913Sarchie } 124653913Sarchie while (isspace(s[*off])) 124753913Sarchie (*off)++; 124853913Sarchie foff[index] = *off; 124953913Sarchie if ((error = ng_parse_skip_value(s, *off, &len)) != 0) 125053913Sarchie goto done; 125153913Sarchie *off += len; 125253913Sarchie } 125353913Sarchie 125453913Sarchie /* Now build binary structure from supplied values and defaults */ 125553913Sarchie for (blen = index = 0; index < num; index++) { 125653913Sarchie const struct ng_parse_type *const 125753913Sarchie etype = ng_get_composite_etype(type, index, ctype); 125853913Sarchie int k, pad, vlen; 125953913Sarchie 126053913Sarchie /* Zero-pad any alignment bytes */ 126153913Sarchie pad = ng_parse_get_elem_pad(type, index, ctype, blen); 126253913Sarchie for (k = 0; k < pad; k++) { 126353913Sarchie if (blen >= *buflen) { 126453913Sarchie error = ERANGE; 126553913Sarchie goto done; 126653913Sarchie } 126753913Sarchie buf[blen++] = 0; 126853913Sarchie } 126953913Sarchie 127053913Sarchie /* Get value */ 127153913Sarchie vlen = *buflen - blen; 127253913Sarchie if (foff[index] == 0) { /* use default value */ 127353913Sarchie error = ng_get_composite_elem_default(type, index, 127453913Sarchie start, buf + blen, &vlen, ctype); 127553913Sarchie } else { /* parse given value */ 127653913Sarchie *off = foff[index]; 127753913Sarchie error = INVOKE(etype, parse)(etype, 127853913Sarchie s, off, start, buf + blen, &vlen); 127953913Sarchie } 128053913Sarchie if (error != 0) 128153913Sarchie goto done; 128253913Sarchie blen += vlen; 128353913Sarchie } 128453913Sarchie 128553913Sarchie /* Make total composite structure size a multiple of its alignment */ 128653913Sarchie if ((align = ALIGNMENT(type)) != 0) { 128753913Sarchie while (blen % align != 0) { 128853913Sarchie if (blen >= *buflen) { 128953913Sarchie error = ERANGE; 129053913Sarchie goto done; 129153913Sarchie } 129253913Sarchie buf[blen++] = 0; 129353913Sarchie } 129453913Sarchie } 129553913Sarchie 129653913Sarchie /* Done */ 129753913Sarchie *buflen = blen; 129853913Sarchiedone: 129965303Sarchie if (foff != NULL) 130070870Sjulian FREE(foff, M_NETGRAPH_PARSE); 130153913Sarchie return (error); 130253913Sarchie} 130353913Sarchie 130453913Sarchie/* 130553913Sarchie * Convert an array or structure from binary to ASCII 130653913Sarchie */ 130753913Sarchiestatic int 130853913Sarchieng_unparse_composite(const struct ng_parse_type *type, const u_char *data, 130953913Sarchie int *off, char *cbuf, int cbuflen, const enum comptype ctype) 131053913Sarchie{ 131190047Sarchie const struct ng_mesg *const hdr 131290047Sarchie = (const struct ng_mesg *)(data - sizeof(*hdr)); 131353913Sarchie const int num = ng_get_composite_len(type, data, data + *off, ctype); 131464505Sarchie const int workSize = 20 * 1024; /* XXX hard coded constant */ 131553913Sarchie int nextIndex = 0, didOne = 0; 131653913Sarchie int error, index; 131764505Sarchie u_char *workBuf; 131853913Sarchie 131964505Sarchie /* Get workspace for checking default values */ 132070870Sjulian MALLOC(workBuf, u_char *, workSize, M_NETGRAPH_PARSE, M_NOWAIT); 132164505Sarchie if (workBuf == NULL) 132264505Sarchie return (ENOMEM); 132364505Sarchie 132453913Sarchie /* Opening brace/bracket */ 132553913Sarchie NG_PARSE_APPEND("%c", (ctype == CT_STRUCT) ? '{' : '['); 132653913Sarchie 132753913Sarchie /* Do each item */ 132853913Sarchie for (index = 0; index < num; index++) { 132953913Sarchie const struct ng_parse_type *const 133053913Sarchie etype = ng_get_composite_etype(type, index, ctype); 133153913Sarchie 133253913Sarchie /* Skip any alignment pad bytes */ 133353913Sarchie *off += ng_parse_get_elem_pad(type, index, ctype, *off); 133453913Sarchie 133590047Sarchie /* 133690047Sarchie * See if element is equal to its default value; skip if so. 133790047Sarchie * Copy struct ng_mesg header for types that peek into it. 133890047Sarchie */ 133990047Sarchie if (sizeof(*hdr) + *off < workSize) { 134090047Sarchie int tempsize = workSize - sizeof(*hdr) - *off; 134153913Sarchie 134290584Sarchie bcopy(hdr, workBuf, sizeof(*hdr) + *off); 134390047Sarchie if (ng_get_composite_elem_default(type, index, workBuf 134490047Sarchie + sizeof(*hdr), workBuf + sizeof(*hdr) + *off, 134590047Sarchie &tempsize, ctype) == 0 134690047Sarchie && bcmp(workBuf + sizeof(*hdr) + *off, 134764505Sarchie data + *off, tempsize) == 0) { 134853913Sarchie *off += tempsize; 134953913Sarchie continue; 135053913Sarchie } 135153913Sarchie } 135253913Sarchie 135353913Sarchie /* Print name= */ 135453913Sarchie NG_PARSE_APPEND(" "); 135553913Sarchie if (ctype != CT_STRUCT) { 135653913Sarchie if (index != nextIndex) { 135753913Sarchie nextIndex = index; 135853913Sarchie NG_PARSE_APPEND("%d=", index); 135953913Sarchie } 136053913Sarchie nextIndex++; 136153913Sarchie } else { 136297685Sarchie const struct ng_parse_struct_field *const 136397685Sarchie fields = type->info; 136453913Sarchie 136597685Sarchie NG_PARSE_APPEND("%s=", fields[index].name); 136653913Sarchie } 136753913Sarchie 136853913Sarchie /* Print value */ 136953913Sarchie if ((error = INVOKE(etype, unparse) 137064505Sarchie (etype, data, off, cbuf, cbuflen)) != 0) { 137170870Sjulian FREE(workBuf, M_NETGRAPH_PARSE); 137253913Sarchie return (error); 137364505Sarchie } 137453913Sarchie cbuflen -= strlen(cbuf); 137553913Sarchie cbuf += strlen(cbuf); 137653913Sarchie didOne = 1; 137753913Sarchie } 137870870Sjulian FREE(workBuf, M_NETGRAPH_PARSE); 137953913Sarchie 138053913Sarchie /* Closing brace/bracket */ 138153913Sarchie NG_PARSE_APPEND("%s%c", 138253913Sarchie didOne ? " " : "", (ctype == CT_STRUCT) ? '}' : ']'); 138353913Sarchie return (0); 138453913Sarchie} 138553913Sarchie 138653913Sarchie/* 138753913Sarchie * Generate the default value for an element of an array or structure 138853913Sarchie * Returns EOPNOTSUPP if default value is unspecified. 138953913Sarchie */ 139053913Sarchiestatic int 139153913Sarchieng_get_composite_elem_default(const struct ng_parse_type *type, 139253913Sarchie int index, const u_char *const start, u_char *buf, int *buflen, 139353913Sarchie const enum comptype ctype) 139453913Sarchie{ 139553913Sarchie const struct ng_parse_type *etype; 139653913Sarchie ng_getDefault_t *func; 139753913Sarchie 139853913Sarchie switch (ctype) { 139953913Sarchie case CT_STRUCT: 140053913Sarchie break; 140153913Sarchie case CT_ARRAY: 140253913Sarchie { 140353913Sarchie const struct ng_parse_array_info *const ai = type->info; 140453913Sarchie 140553913Sarchie if (ai->getDefault != NULL) { 140653913Sarchie return (*ai->getDefault)(type, 140753913Sarchie index, start, buf, buflen); 140853913Sarchie } 140953913Sarchie break; 141053913Sarchie } 141153913Sarchie case CT_FIXEDARRAY: 141253913Sarchie { 141353913Sarchie const struct ng_parse_fixedarray_info *const fi = type->info; 141453913Sarchie 141553913Sarchie if (*fi->getDefault != NULL) { 141653913Sarchie return (*fi->getDefault)(type, 141753913Sarchie index, start, buf, buflen); 141853913Sarchie } 141953913Sarchie break; 142053913Sarchie } 142153913Sarchie default: 142287599Sobrien panic("%s", __func__); 142353913Sarchie } 142453913Sarchie 142553913Sarchie /* Default to element type default */ 142653913Sarchie etype = ng_get_composite_etype(type, index, ctype); 142753913Sarchie func = METHOD(etype, getDefault); 142853913Sarchie if (func == NULL) 142953913Sarchie return (EOPNOTSUPP); 143053913Sarchie return (*func)(etype, start, buf, buflen); 143153913Sarchie} 143253913Sarchie 143353913Sarchie/* 143453913Sarchie * Get the number of elements in a struct, variable or fixed array. 143553913Sarchie */ 143653913Sarchiestatic int 143753913Sarchieng_get_composite_len(const struct ng_parse_type *type, 143853913Sarchie const u_char *const start, const u_char *buf, 143953913Sarchie const enum comptype ctype) 144053913Sarchie{ 144153913Sarchie switch (ctype) { 144253913Sarchie case CT_STRUCT: 144353913Sarchie { 144497685Sarchie const struct ng_parse_struct_field *const fields = type->info; 144553913Sarchie int numFields = 0; 144653913Sarchie 144753913Sarchie for (numFields = 0; ; numFields++) { 144853913Sarchie const struct ng_parse_struct_field *const 144997685Sarchie fi = &fields[numFields]; 145053913Sarchie 145153913Sarchie if (fi->name == NULL) 145253913Sarchie break; 145353913Sarchie } 145453913Sarchie return (numFields); 145553913Sarchie } 145653913Sarchie case CT_ARRAY: 145753913Sarchie { 145853913Sarchie const struct ng_parse_array_info *const ai = type->info; 145953913Sarchie 146053913Sarchie return (*ai->getLength)(type, start, buf); 146153913Sarchie } 146253913Sarchie case CT_FIXEDARRAY: 146353913Sarchie { 146453913Sarchie const struct ng_parse_fixedarray_info *const fi = type->info; 146553913Sarchie 146653913Sarchie return fi->length; 146753913Sarchie } 146853913Sarchie default: 146987599Sobrien panic("%s", __func__); 147053913Sarchie } 147153913Sarchie return (0); 147253913Sarchie} 147353913Sarchie 147453913Sarchie/* 147553913Sarchie * Return the type of the index'th element of a composite structure 147653913Sarchie */ 147753913Sarchiestatic const struct ng_parse_type * 147853913Sarchieng_get_composite_etype(const struct ng_parse_type *type, 147953913Sarchie int index, const enum comptype ctype) 148053913Sarchie{ 148153913Sarchie const struct ng_parse_type *etype = NULL; 148253913Sarchie 148353913Sarchie switch (ctype) { 148453913Sarchie case CT_STRUCT: 148553913Sarchie { 148697685Sarchie const struct ng_parse_struct_field *const fields = type->info; 148753913Sarchie 148897685Sarchie etype = fields[index].type; 148953913Sarchie break; 149053913Sarchie } 149153913Sarchie case CT_ARRAY: 149253913Sarchie { 149353913Sarchie const struct ng_parse_array_info *const ai = type->info; 149453913Sarchie 149553913Sarchie etype = ai->elementType; 149653913Sarchie break; 149753913Sarchie } 149853913Sarchie case CT_FIXEDARRAY: 149953913Sarchie { 150053913Sarchie const struct ng_parse_fixedarray_info *const fi = type->info; 150153913Sarchie 150253913Sarchie etype = fi->elementType; 150353913Sarchie break; 150453913Sarchie } 150553913Sarchie default: 150687599Sobrien panic("%s", __func__); 150753913Sarchie } 150853913Sarchie return (etype); 150953913Sarchie} 151053913Sarchie 151153913Sarchie/* 151253913Sarchie * Get the number of bytes to skip to align for the next 151353913Sarchie * element in a composite structure. 151453913Sarchie */ 151553913Sarchiestatic int 151653913Sarchieng_parse_get_elem_pad(const struct ng_parse_type *type, 151753913Sarchie int index, enum comptype ctype, int posn) 151853913Sarchie{ 151953913Sarchie const struct ng_parse_type *const 152053913Sarchie etype = ng_get_composite_etype(type, index, ctype); 152153913Sarchie int align; 152253913Sarchie 152353913Sarchie /* Get element's alignment, and possibly override */ 152453913Sarchie align = ALIGNMENT(etype); 152553913Sarchie if (ctype == CT_STRUCT) { 152697685Sarchie const struct ng_parse_struct_field *const fields = type->info; 152753913Sarchie 152897685Sarchie if (fields[index].alignment != 0) 152997685Sarchie align = fields[index].alignment; 153053913Sarchie } 153153913Sarchie 153253913Sarchie /* Return number of bytes to skip to align */ 153353913Sarchie return (align ? (align - (posn % align)) % align : 0); 153453913Sarchie} 153553913Sarchie 153653913Sarchie/************************************************************************ 153753913Sarchie PARSING HELPER ROUTINES 153853913Sarchie ************************************************************************/ 153953913Sarchie 154053913Sarchie/* 154153913Sarchie * Skip over a value 154253913Sarchie */ 154353913Sarchiestatic int 154453913Sarchieng_parse_skip_value(const char *s, int off0, int *lenp) 154553913Sarchie{ 154653913Sarchie int len, nbracket, nbrace; 154753913Sarchie int off = off0; 154853913Sarchie 154953913Sarchie len = nbracket = nbrace = 0; 155053913Sarchie do { 155153913Sarchie switch (ng_parse_get_token(s, &off, &len)) { 155253913Sarchie case T_LBRACKET: 155353913Sarchie nbracket++; 155453913Sarchie break; 155553913Sarchie case T_LBRACE: 155653913Sarchie nbrace++; 155753913Sarchie break; 155853913Sarchie case T_RBRACKET: 155953913Sarchie if (nbracket-- == 0) 156053913Sarchie return (EINVAL); 156153913Sarchie break; 156253913Sarchie case T_RBRACE: 156353913Sarchie if (nbrace-- == 0) 156453913Sarchie return (EINVAL); 156553913Sarchie break; 156653913Sarchie case T_EOF: 156753913Sarchie return (EINVAL); 156853913Sarchie default: 156953913Sarchie break; 157053913Sarchie } 157153913Sarchie off += len; 157253913Sarchie } while (nbracket > 0 || nbrace > 0); 157353913Sarchie *lenp = off - off0; 157453913Sarchie return (0); 157553913Sarchie} 157653913Sarchie 157753913Sarchie/* 157853913Sarchie * Find the next token in the string, starting at offset *startp. 157953913Sarchie * Returns the token type, with *startp pointing to the first char 158053913Sarchie * and *lenp the length. 158153913Sarchie */ 158253913Sarchieenum ng_parse_token 158353913Sarchieng_parse_get_token(const char *s, int *startp, int *lenp) 158453913Sarchie{ 158553913Sarchie char *t; 158653913Sarchie int i; 158753913Sarchie 158853913Sarchie while (isspace(s[*startp])) 158953913Sarchie (*startp)++; 159053913Sarchie switch (s[*startp]) { 159153913Sarchie case '\0': 159253913Sarchie *lenp = 0; 159353913Sarchie return T_EOF; 159453913Sarchie case '{': 159553913Sarchie *lenp = 1; 159653913Sarchie return T_LBRACE; 159753913Sarchie case '}': 159853913Sarchie *lenp = 1; 159953913Sarchie return T_RBRACE; 160053913Sarchie case '[': 160153913Sarchie *lenp = 1; 160253913Sarchie return T_LBRACKET; 160353913Sarchie case ']': 160453913Sarchie *lenp = 1; 160553913Sarchie return T_RBRACKET; 160653913Sarchie case '=': 160753913Sarchie *lenp = 1; 160853913Sarchie return T_EQUALS; 160953913Sarchie case '"': 161068845Sbrian if ((t = ng_get_string_token(s, startp, lenp, NULL)) == NULL) 161153913Sarchie return T_ERROR; 161270870Sjulian FREE(t, M_NETGRAPH_PARSE); 161353913Sarchie return T_STRING; 161453913Sarchie default: 161553913Sarchie for (i = *startp + 1; s[i] != '\0' && !isspace(s[i]) 161653913Sarchie && s[i] != '{' && s[i] != '}' && s[i] != '[' 161753913Sarchie && s[i] != ']' && s[i] != '=' && s[i] != '"'; i++) 161853913Sarchie ; 161953913Sarchie *lenp = i - *startp; 162053913Sarchie return T_WORD; 162153913Sarchie } 162253913Sarchie} 162353913Sarchie 162453913Sarchie/* 162553913Sarchie * Get a string token, which must be enclosed in double quotes. 162653913Sarchie * The normal C backslash escapes are recognized. 162753913Sarchie */ 162853913Sarchiechar * 162968845Sbrianng_get_string_token(const char *s, int *startp, int *lenp, int *slenp) 163053913Sarchie{ 163153913Sarchie char *cbuf, *p; 163253913Sarchie int start, off; 163368845Sbrian int slen; 163453913Sarchie 163553913Sarchie while (isspace(s[*startp])) 163653913Sarchie (*startp)++; 163753913Sarchie start = *startp; 163853913Sarchie if (s[*startp] != '"') 163953913Sarchie return (NULL); 164070870Sjulian MALLOC(cbuf, char *, strlen(s + start), M_NETGRAPH_PARSE, M_NOWAIT); 164153913Sarchie if (cbuf == NULL) 164253913Sarchie return (NULL); 164353913Sarchie strcpy(cbuf, s + start + 1); 164468845Sbrian for (slen = 0, off = 1, p = cbuf; *p != '\0'; slen++, off++, p++) { 164553913Sarchie if (*p == '"') { 164653913Sarchie *p = '\0'; 164753913Sarchie *lenp = off + 1; 164868845Sbrian if (slenp != NULL) 164968845Sbrian *slenp = slen; 165053913Sarchie return (cbuf); 165153913Sarchie } else if (p[0] == '\\' && p[1] != '\0') { 165253913Sarchie int x, k; 165353913Sarchie char *v; 165453913Sarchie 165553913Sarchie strcpy(p, p + 1); 165653913Sarchie v = p; 165753913Sarchie switch (*p) { 165853913Sarchie case 't': 165953913Sarchie *v = '\t'; 166053913Sarchie off++; 166153913Sarchie continue; 166253913Sarchie case 'n': 166353913Sarchie *v = '\n'; 166453913Sarchie off++; 166553913Sarchie continue; 166653913Sarchie case 'r': 166753913Sarchie *v = '\r'; 166853913Sarchie off++; 166953913Sarchie continue; 167053913Sarchie case 'v': 167153913Sarchie *v = '\v'; 167253913Sarchie off++; 167353913Sarchie continue; 167453913Sarchie case 'f': 167553913Sarchie *v = '\f'; 167653913Sarchie off++; 167753913Sarchie continue; 167853913Sarchie case '"': 167953913Sarchie *v = '"'; 168053913Sarchie off++; 168153913Sarchie continue; 168253913Sarchie case '0': case '1': case '2': case '3': 168353913Sarchie case '4': case '5': case '6': case '7': 168453913Sarchie for (x = k = 0; 168553913Sarchie k < 3 && *v >= '0' && *v <= '7'; v++) { 168653913Sarchie x = (x << 3) + (*v - '0'); 168753913Sarchie off++; 168853913Sarchie } 168953913Sarchie *--v = (char)x; 169053913Sarchie break; 169153913Sarchie case 'x': 169253913Sarchie for (v++, x = k = 0; 169353913Sarchie k < 2 && isxdigit(*v); v++) { 169453913Sarchie x = (x << 4) + (isdigit(*v) ? 169553913Sarchie (*v - '0') : 169653913Sarchie (tolower(*v) - 'a' + 10)); 169753913Sarchie off++; 169853913Sarchie } 169953913Sarchie *--v = (char)x; 170053913Sarchie break; 170153913Sarchie default: 170253913Sarchie continue; 170353913Sarchie } 170453913Sarchie strcpy(p, v); 170553913Sarchie } 170653913Sarchie } 170753913Sarchie return (NULL); /* no closing quote */ 170853913Sarchie} 170953913Sarchie 171053913Sarchie/* 171153913Sarchie * Encode a string so it can be safely put in double quotes. 171268845Sbrian * Caller must free the result. Exactly "slen" characters 171368845Sbrian * are encoded. 171453913Sarchie */ 171553913Sarchiechar * 171668845Sbrianng_encode_string(const char *raw, int slen) 171753913Sarchie{ 171853913Sarchie char *cbuf; 171953913Sarchie int off = 0; 172068845Sbrian int i; 172153913Sarchie 172270870Sjulian MALLOC(cbuf, char *, strlen(raw) * 4 + 3, M_NETGRAPH_PARSE, M_NOWAIT); 172353913Sarchie if (cbuf == NULL) 172453913Sarchie return (NULL); 172553913Sarchie cbuf[off++] = '"'; 172668845Sbrian for (i = 0; i < slen; i++, raw++) { 172753913Sarchie switch (*raw) { 172853913Sarchie case '\t': 172953913Sarchie cbuf[off++] = '\\'; 173053913Sarchie cbuf[off++] = 't'; 173153913Sarchie break; 173253913Sarchie case '\f': 173353913Sarchie cbuf[off++] = '\\'; 173453913Sarchie cbuf[off++] = 'f'; 173553913Sarchie break; 173653913Sarchie case '\n': 173753913Sarchie cbuf[off++] = '\\'; 173853913Sarchie cbuf[off++] = 'n'; 173953913Sarchie break; 174053913Sarchie case '\r': 174153913Sarchie cbuf[off++] = '\\'; 174253913Sarchie cbuf[off++] = 'r'; 174353913Sarchie break; 174453913Sarchie case '\v': 174553913Sarchie cbuf[off++] = '\\'; 174653913Sarchie cbuf[off++] = 'v'; 174753913Sarchie break; 174853913Sarchie case '"': 174953913Sarchie case '\\': 175053913Sarchie cbuf[off++] = '\\'; 175153913Sarchie cbuf[off++] = *raw; 175253913Sarchie break; 175353913Sarchie default: 175453913Sarchie if (*raw < 0x20 || *raw > 0x7e) { 175553913Sarchie off += sprintf(cbuf + off, 175653913Sarchie "\\x%02x", (u_char)*raw); 175753913Sarchie break; 175853913Sarchie } 175953913Sarchie cbuf[off++] = *raw; 176053913Sarchie break; 176153913Sarchie } 176253913Sarchie } 176353913Sarchie cbuf[off++] = '"'; 176453913Sarchie cbuf[off] = '\0'; 176553913Sarchie return (cbuf); 176653913Sarchie} 176753913Sarchie 176853913Sarchie/************************************************************************ 176953913Sarchie VIRTUAL METHOD LOOKUP 177053913Sarchie ************************************************************************/ 177153913Sarchie 177253913Sarchiestatic ng_parse_t * 177353913Sarchieng_get_parse_method(const struct ng_parse_type *t) 177453913Sarchie{ 177553913Sarchie while (t != NULL && t->parse == NULL) 177653913Sarchie t = t->supertype; 177753913Sarchie return (t ? t->parse : NULL); 177853913Sarchie} 177953913Sarchie 178053913Sarchiestatic ng_unparse_t * 178153913Sarchieng_get_unparse_method(const struct ng_parse_type *t) 178253913Sarchie{ 178353913Sarchie while (t != NULL && t->unparse == NULL) 178453913Sarchie t = t->supertype; 178553913Sarchie return (t ? t->unparse : NULL); 178653913Sarchie} 178753913Sarchie 178853913Sarchiestatic ng_getDefault_t * 178953913Sarchieng_get_getDefault_method(const struct ng_parse_type *t) 179053913Sarchie{ 179153913Sarchie while (t != NULL && t->getDefault == NULL) 179253913Sarchie t = t->supertype; 179353913Sarchie return (t ? t->getDefault : NULL); 179453913Sarchie} 179553913Sarchie 179653913Sarchiestatic ng_getAlign_t * 179753913Sarchieng_get_getAlign_method(const struct ng_parse_type *t) 179853913Sarchie{ 179953913Sarchie while (t != NULL && t->getAlign == NULL) 180053913Sarchie t = t->supertype; 180153913Sarchie return (t ? t->getAlign : NULL); 180253913Sarchie} 180353913Sarchie 1804