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