1*83ee113eSDavid van Moolenbroek /* $NetBSD: tree.h,v 1.1.1.3 2014/07/12 11:57:56 spz Exp $ */ 2*83ee113eSDavid van Moolenbroek /* tree.h 3*83ee113eSDavid van Moolenbroek 4*83ee113eSDavid van Moolenbroek Definitions for address trees... */ 5*83ee113eSDavid van Moolenbroek 6*83ee113eSDavid van Moolenbroek /* 7*83ee113eSDavid van Moolenbroek * Copyright (c) 2011,2013,2014 by Internet Systems Consortium, Inc. ("ISC") 8*83ee113eSDavid van Moolenbroek * Copyright (c) 2004,2007-2009 by Internet Systems Consortium, Inc. ("ISC") 9*83ee113eSDavid van Moolenbroek * Copyright (c) 1996-2003 by Internet Software Consortium 10*83ee113eSDavid van Moolenbroek * 11*83ee113eSDavid van Moolenbroek * Permission to use, copy, modify, and distribute this software for any 12*83ee113eSDavid van Moolenbroek * purpose with or without fee is hereby granted, provided that the above 13*83ee113eSDavid van Moolenbroek * copyright notice and this permission notice appear in all copies. 14*83ee113eSDavid van Moolenbroek * 15*83ee113eSDavid van Moolenbroek * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 16*83ee113eSDavid van Moolenbroek * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 17*83ee113eSDavid van Moolenbroek * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 18*83ee113eSDavid van Moolenbroek * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19*83ee113eSDavid van Moolenbroek * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 20*83ee113eSDavid van Moolenbroek * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 21*83ee113eSDavid van Moolenbroek * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22*83ee113eSDavid van Moolenbroek * 23*83ee113eSDavid van Moolenbroek * Internet Systems Consortium, Inc. 24*83ee113eSDavid van Moolenbroek * 950 Charter Street 25*83ee113eSDavid van Moolenbroek * Redwood City, CA 94063 26*83ee113eSDavid van Moolenbroek * <info@isc.org> 27*83ee113eSDavid van Moolenbroek * https://www.isc.org/ 28*83ee113eSDavid van Moolenbroek * 29*83ee113eSDavid van Moolenbroek */ 30*83ee113eSDavid van Moolenbroek 31*83ee113eSDavid van Moolenbroek /* A pair of pointers, suitable for making a linked list. */ 32*83ee113eSDavid van Moolenbroek typedef struct _pair { 33*83ee113eSDavid van Moolenbroek caddr_t car; 34*83ee113eSDavid van Moolenbroek struct _pair *cdr; 35*83ee113eSDavid van Moolenbroek } *pair; 36*83ee113eSDavid van Moolenbroek 37*83ee113eSDavid van Moolenbroek struct option_chain_head { 38*83ee113eSDavid van Moolenbroek int refcnt; 39*83ee113eSDavid van Moolenbroek pair first; 40*83ee113eSDavid van Moolenbroek }; 41*83ee113eSDavid van Moolenbroek 42*83ee113eSDavid van Moolenbroek struct enumeration_value { 43*83ee113eSDavid van Moolenbroek const char *name; 44*83ee113eSDavid van Moolenbroek u_int8_t value; 45*83ee113eSDavid van Moolenbroek }; 46*83ee113eSDavid van Moolenbroek 47*83ee113eSDavid van Moolenbroek struct enumeration { 48*83ee113eSDavid van Moolenbroek struct enumeration *next; 49*83ee113eSDavid van Moolenbroek const char *name; 50*83ee113eSDavid van Moolenbroek unsigned width; 51*83ee113eSDavid van Moolenbroek struct enumeration_value *values; 52*83ee113eSDavid van Moolenbroek }; 53*83ee113eSDavid van Moolenbroek 54*83ee113eSDavid van Moolenbroek /* Tree node types... */ 55*83ee113eSDavid van Moolenbroek #define TREE_CONCAT 1 56*83ee113eSDavid van Moolenbroek #define TREE_HOST_LOOKUP 2 57*83ee113eSDavid van Moolenbroek #define TREE_CONST 3 58*83ee113eSDavid van Moolenbroek #define TREE_LIMIT 4 59*83ee113eSDavid van Moolenbroek #define TREE_DATA_EXPR 5 60*83ee113eSDavid van Moolenbroek 61*83ee113eSDavid van Moolenbroek /* A data buffer with a reference count. */ 62*83ee113eSDavid van Moolenbroek struct buffer { 63*83ee113eSDavid van Moolenbroek int refcnt; 64*83ee113eSDavid van Moolenbroek unsigned char data [1]; 65*83ee113eSDavid van Moolenbroek }; 66*83ee113eSDavid van Moolenbroek 67*83ee113eSDavid van Moolenbroek /* XXX The mechanism by which data strings are returned is currently 68*83ee113eSDavid van Moolenbroek XXX broken: rather than returning an ephemeral pointer, we create 69*83ee113eSDavid van Moolenbroek XXX a reference to the data in the caller's space, which the caller 70*83ee113eSDavid van Moolenbroek XXX then has to dereference - instead, the reference should be 71*83ee113eSDavid van Moolenbroek XXX ephemeral by default and be made a persistent reference explicitly. */ 72*83ee113eSDavid van Moolenbroek /* XXX on the other hand, it seems to work pretty nicely, so maybe the 73*83ee113eSDavid van Moolenbroek XXX above comment is meshuggenah. */ 74*83ee113eSDavid van Moolenbroek /* XXX I think the above comment tries to say this: 75*83ee113eSDavid van Moolenbroek XXX http://tinyurl.com/2tjqre */ 76*83ee113eSDavid van Moolenbroek 77*83ee113eSDavid van Moolenbroek /* A string of data bytes, possibly accompanied by a larger buffer. */ 78*83ee113eSDavid van Moolenbroek struct data_string { 79*83ee113eSDavid van Moolenbroek struct buffer *buffer; 80*83ee113eSDavid van Moolenbroek const unsigned char *data; 81*83ee113eSDavid van Moolenbroek unsigned len; /* Does not include NUL terminator, if any. */ 82*83ee113eSDavid van Moolenbroek int terminated; 83*83ee113eSDavid van Moolenbroek }; 84*83ee113eSDavid van Moolenbroek 85*83ee113eSDavid van Moolenbroek enum expression_context { 86*83ee113eSDavid van Moolenbroek context_any, /* indefinite */ 87*83ee113eSDavid van Moolenbroek context_boolean, 88*83ee113eSDavid van Moolenbroek context_data, 89*83ee113eSDavid van Moolenbroek context_numeric, 90*83ee113eSDavid van Moolenbroek context_dns, 91*83ee113eSDavid van Moolenbroek context_data_or_numeric, /* indefinite */ 92*83ee113eSDavid van Moolenbroek context_function 93*83ee113eSDavid van Moolenbroek }; 94*83ee113eSDavid van Moolenbroek 95*83ee113eSDavid van Moolenbroek struct fundef { 96*83ee113eSDavid van Moolenbroek int refcnt; 97*83ee113eSDavid van Moolenbroek struct string_list *args; 98*83ee113eSDavid van Moolenbroek struct executable_statement *statements; 99*83ee113eSDavid van Moolenbroek }; 100*83ee113eSDavid van Moolenbroek 101*83ee113eSDavid van Moolenbroek struct binding_value { 102*83ee113eSDavid van Moolenbroek int refcnt; 103*83ee113eSDavid van Moolenbroek enum { 104*83ee113eSDavid van Moolenbroek binding_boolean, 105*83ee113eSDavid van Moolenbroek binding_data, 106*83ee113eSDavid van Moolenbroek binding_numeric, 107*83ee113eSDavid van Moolenbroek binding_dns, 108*83ee113eSDavid van Moolenbroek binding_function 109*83ee113eSDavid van Moolenbroek } type; 110*83ee113eSDavid van Moolenbroek union value { 111*83ee113eSDavid van Moolenbroek struct data_string data; 112*83ee113eSDavid van Moolenbroek unsigned long intval; 113*83ee113eSDavid van Moolenbroek int boolean; 114*83ee113eSDavid van Moolenbroek struct fundef *fundef; 115*83ee113eSDavid van Moolenbroek struct binding_value *bv; 116*83ee113eSDavid van Moolenbroek } value; 117*83ee113eSDavid van Moolenbroek }; 118*83ee113eSDavid van Moolenbroek 119*83ee113eSDavid van Moolenbroek struct binding { 120*83ee113eSDavid van Moolenbroek struct binding *next; 121*83ee113eSDavid van Moolenbroek char *name; 122*83ee113eSDavid van Moolenbroek struct binding_value *value; 123*83ee113eSDavid van Moolenbroek }; 124*83ee113eSDavid van Moolenbroek 125*83ee113eSDavid van Moolenbroek struct binding_scope { 126*83ee113eSDavid van Moolenbroek int refcnt; 127*83ee113eSDavid van Moolenbroek struct binding_scope *outer; 128*83ee113eSDavid van Moolenbroek struct binding *bindings; 129*83ee113eSDavid van Moolenbroek }; 130*83ee113eSDavid van Moolenbroek 131*83ee113eSDavid van Moolenbroek /* Expression tree structure. */ 132*83ee113eSDavid van Moolenbroek 133*83ee113eSDavid van Moolenbroek enum expr_op { 134*83ee113eSDavid van Moolenbroek expr_none, 135*83ee113eSDavid van Moolenbroek expr_match, 136*83ee113eSDavid van Moolenbroek expr_check, 137*83ee113eSDavid van Moolenbroek expr_equal, 138*83ee113eSDavid van Moolenbroek expr_substring, 139*83ee113eSDavid van Moolenbroek expr_suffix, 140*83ee113eSDavid van Moolenbroek expr_concat, 141*83ee113eSDavid van Moolenbroek expr_host_lookup, 142*83ee113eSDavid van Moolenbroek expr_and, 143*83ee113eSDavid van Moolenbroek expr_or, 144*83ee113eSDavid van Moolenbroek expr_not, 145*83ee113eSDavid van Moolenbroek expr_option, 146*83ee113eSDavid van Moolenbroek expr_hardware, 147*83ee113eSDavid van Moolenbroek expr_packet, 148*83ee113eSDavid van Moolenbroek expr_const_data, 149*83ee113eSDavid van Moolenbroek expr_extract_int8, 150*83ee113eSDavid van Moolenbroek expr_extract_int16, 151*83ee113eSDavid van Moolenbroek expr_extract_int32, 152*83ee113eSDavid van Moolenbroek expr_encode_int8, 153*83ee113eSDavid van Moolenbroek expr_encode_int16, 154*83ee113eSDavid van Moolenbroek expr_encode_int32, 155*83ee113eSDavid van Moolenbroek expr_const_int, 156*83ee113eSDavid van Moolenbroek expr_exists, 157*83ee113eSDavid van Moolenbroek expr_encapsulate, 158*83ee113eSDavid van Moolenbroek expr_known, 159*83ee113eSDavid van Moolenbroek expr_reverse, 160*83ee113eSDavid van Moolenbroek expr_leased_address, 161*83ee113eSDavid van Moolenbroek expr_binary_to_ascii, 162*83ee113eSDavid van Moolenbroek expr_config_option, 163*83ee113eSDavid van Moolenbroek expr_host_decl_name, 164*83ee113eSDavid van Moolenbroek expr_pick_first_value, 165*83ee113eSDavid van Moolenbroek expr_lease_time, 166*83ee113eSDavid van Moolenbroek expr_dns_transaction, 167*83ee113eSDavid van Moolenbroek expr_static, 168*83ee113eSDavid van Moolenbroek expr_ns_add, 169*83ee113eSDavid van Moolenbroek expr_ns_delete, 170*83ee113eSDavid van Moolenbroek expr_ns_exists, 171*83ee113eSDavid van Moolenbroek expr_ns_not_exists, 172*83ee113eSDavid van Moolenbroek expr_not_equal, 173*83ee113eSDavid van Moolenbroek expr_null, 174*83ee113eSDavid van Moolenbroek expr_variable_exists, 175*83ee113eSDavid van Moolenbroek expr_variable_reference, 176*83ee113eSDavid van Moolenbroek expr_filename, 177*83ee113eSDavid van Moolenbroek expr_sname, 178*83ee113eSDavid van Moolenbroek expr_arg, 179*83ee113eSDavid van Moolenbroek expr_funcall, 180*83ee113eSDavid van Moolenbroek expr_function, 181*83ee113eSDavid van Moolenbroek expr_add, 182*83ee113eSDavid van Moolenbroek expr_subtract, 183*83ee113eSDavid van Moolenbroek expr_multiply, 184*83ee113eSDavid van Moolenbroek expr_divide, 185*83ee113eSDavid van Moolenbroek expr_remainder, 186*83ee113eSDavid van Moolenbroek expr_binary_and, 187*83ee113eSDavid van Moolenbroek expr_binary_or, 188*83ee113eSDavid van Moolenbroek expr_binary_xor, 189*83ee113eSDavid van Moolenbroek expr_client_state, 190*83ee113eSDavid van Moolenbroek expr_ucase, 191*83ee113eSDavid van Moolenbroek expr_lcase, 192*83ee113eSDavid van Moolenbroek expr_regex_match, 193*83ee113eSDavid van Moolenbroek expr_iregex_match, 194*83ee113eSDavid van Moolenbroek expr_gethostname, 195*83ee113eSDavid van Moolenbroek expr_v6relay 196*83ee113eSDavid van Moolenbroek }; 197*83ee113eSDavid van Moolenbroek 198*83ee113eSDavid van Moolenbroek struct expression { 199*83ee113eSDavid van Moolenbroek int refcnt; 200*83ee113eSDavid van Moolenbroek enum expr_op op; 201*83ee113eSDavid van Moolenbroek union expr_union { 202*83ee113eSDavid van Moolenbroek struct { 203*83ee113eSDavid van Moolenbroek struct expression *expr; 204*83ee113eSDavid van Moolenbroek struct expression *offset; 205*83ee113eSDavid van Moolenbroek struct expression *len; 206*83ee113eSDavid van Moolenbroek } substring; 207*83ee113eSDavid van Moolenbroek struct expression *equal [2]; 208*83ee113eSDavid van Moolenbroek struct expression *and [2]; 209*83ee113eSDavid van Moolenbroek struct expression *or [2]; 210*83ee113eSDavid van Moolenbroek struct expression *not; 211*83ee113eSDavid van Moolenbroek struct expression *add; 212*83ee113eSDavid van Moolenbroek struct expression *subtract; 213*83ee113eSDavid van Moolenbroek struct expression *multiply; 214*83ee113eSDavid van Moolenbroek struct expression *divide; 215*83ee113eSDavid van Moolenbroek struct expression *remainder; 216*83ee113eSDavid van Moolenbroek struct collection *check; 217*83ee113eSDavid van Moolenbroek struct { 218*83ee113eSDavid van Moolenbroek struct expression *expr; 219*83ee113eSDavid van Moolenbroek struct expression *len; 220*83ee113eSDavid van Moolenbroek } suffix; 221*83ee113eSDavid van Moolenbroek struct expression *lcase; 222*83ee113eSDavid van Moolenbroek struct expression *ucase; 223*83ee113eSDavid van Moolenbroek struct option *option; 224*83ee113eSDavid van Moolenbroek struct option *config_option; 225*83ee113eSDavid van Moolenbroek struct { 226*83ee113eSDavid van Moolenbroek struct expression *offset; 227*83ee113eSDavid van Moolenbroek struct expression *len; 228*83ee113eSDavid van Moolenbroek } packet; 229*83ee113eSDavid van Moolenbroek struct data_string const_data; 230*83ee113eSDavid van Moolenbroek struct expression *extract_int; 231*83ee113eSDavid van Moolenbroek struct expression *encode_int; 232*83ee113eSDavid van Moolenbroek unsigned long const_int; 233*83ee113eSDavid van Moolenbroek struct expression *concat [2]; 234*83ee113eSDavid van Moolenbroek struct dns_host_entry *host_lookup; 235*83ee113eSDavid van Moolenbroek struct option *exists; 236*83ee113eSDavid van Moolenbroek struct data_string encapsulate; 237*83ee113eSDavid van Moolenbroek struct { 238*83ee113eSDavid van Moolenbroek struct expression *base; 239*83ee113eSDavid van Moolenbroek struct expression *width; 240*83ee113eSDavid van Moolenbroek struct expression *separator; 241*83ee113eSDavid van Moolenbroek struct expression *buffer; 242*83ee113eSDavid van Moolenbroek } b2a; 243*83ee113eSDavid van Moolenbroek struct { 244*83ee113eSDavid van Moolenbroek struct expression *width; 245*83ee113eSDavid van Moolenbroek struct expression *buffer; 246*83ee113eSDavid van Moolenbroek } reverse; 247*83ee113eSDavid van Moolenbroek struct { 248*83ee113eSDavid van Moolenbroek struct expression *car; 249*83ee113eSDavid van Moolenbroek struct expression *cdr; 250*83ee113eSDavid van Moolenbroek } pick_first_value; 251*83ee113eSDavid van Moolenbroek struct { 252*83ee113eSDavid van Moolenbroek struct expression *car; 253*83ee113eSDavid van Moolenbroek struct expression *cdr; 254*83ee113eSDavid van Moolenbroek } dns_transaction; 255*83ee113eSDavid van Moolenbroek struct { 256*83ee113eSDavid van Moolenbroek unsigned rrclass; 257*83ee113eSDavid van Moolenbroek unsigned rrtype; 258*83ee113eSDavid van Moolenbroek struct expression *rrname; 259*83ee113eSDavid van Moolenbroek struct expression *rrdata; 260*83ee113eSDavid van Moolenbroek struct expression *ttl; 261*83ee113eSDavid van Moolenbroek } ns_add; 262*83ee113eSDavid van Moolenbroek struct { 263*83ee113eSDavid van Moolenbroek unsigned rrclass; 264*83ee113eSDavid van Moolenbroek unsigned rrtype; 265*83ee113eSDavid van Moolenbroek struct expression *rrname; 266*83ee113eSDavid van Moolenbroek struct expression *rrdata; 267*83ee113eSDavid van Moolenbroek } ns_delete, ns_exists, ns_not_exists; 268*83ee113eSDavid van Moolenbroek char *variable; 269*83ee113eSDavid van Moolenbroek struct { 270*83ee113eSDavid van Moolenbroek struct expression *val; 271*83ee113eSDavid van Moolenbroek struct expression *next; 272*83ee113eSDavid van Moolenbroek } arg; 273*83ee113eSDavid van Moolenbroek struct { 274*83ee113eSDavid van Moolenbroek char *name; 275*83ee113eSDavid van Moolenbroek struct expression *arglist; 276*83ee113eSDavid van Moolenbroek } funcall; 277*83ee113eSDavid van Moolenbroek struct fundef *func; 278*83ee113eSDavid van Moolenbroek struct { 279*83ee113eSDavid van Moolenbroek struct expression *relay; 280*83ee113eSDavid van Moolenbroek struct expression *roption; 281*83ee113eSDavid van Moolenbroek } v6relay; 282*83ee113eSDavid van Moolenbroek } data; 283*83ee113eSDavid van Moolenbroek int flags; 284*83ee113eSDavid van Moolenbroek # define EXPR_EPHEMERAL 1 285*83ee113eSDavid van Moolenbroek }; 286*83ee113eSDavid van Moolenbroek 287*83ee113eSDavid van Moolenbroek /* DNS host entry structure... */ 288*83ee113eSDavid van Moolenbroek struct dns_host_entry { 289*83ee113eSDavid van Moolenbroek int refcnt; 290*83ee113eSDavid van Moolenbroek TIME timeout; 291*83ee113eSDavid van Moolenbroek struct data_string data; 292*83ee113eSDavid van Moolenbroek char hostname [1]; 293*83ee113eSDavid van Moolenbroek }; 294*83ee113eSDavid van Moolenbroek 295*83ee113eSDavid van Moolenbroek struct option_cache; /* forward */ 296*83ee113eSDavid van Moolenbroek struct packet; /* forward */ 297*83ee113eSDavid van Moolenbroek struct option_state; /* forward */ 298*83ee113eSDavid van Moolenbroek struct decoded_option_state; /* forward */ 299*83ee113eSDavid van Moolenbroek struct lease; /* forward */ 300*83ee113eSDavid van Moolenbroek struct client_state; /* forward */ 301*83ee113eSDavid van Moolenbroek 302*83ee113eSDavid van Moolenbroek struct universe { 303*83ee113eSDavid van Moolenbroek const char *name; 304*83ee113eSDavid van Moolenbroek struct option_cache *(*lookup_func) (struct universe *, 305*83ee113eSDavid van Moolenbroek struct option_state *, 306*83ee113eSDavid van Moolenbroek unsigned); 307*83ee113eSDavid van Moolenbroek void (*save_func) (struct universe *, struct option_state *, 308*83ee113eSDavid van Moolenbroek struct option_cache *, isc_boolean_t); 309*83ee113eSDavid van Moolenbroek void (*foreach) (struct packet *, 310*83ee113eSDavid van Moolenbroek struct lease *, struct client_state *, 311*83ee113eSDavid van Moolenbroek struct option_state *, struct option_state *, 312*83ee113eSDavid van Moolenbroek struct binding_scope **, struct universe *, void *, 313*83ee113eSDavid van Moolenbroek void (*) (struct option_cache *, struct packet *, 314*83ee113eSDavid van Moolenbroek struct lease *, struct client_state *, 315*83ee113eSDavid van Moolenbroek struct option_state *, 316*83ee113eSDavid van Moolenbroek struct option_state *, 317*83ee113eSDavid van Moolenbroek struct binding_scope **, 318*83ee113eSDavid van Moolenbroek struct universe *, void *)); 319*83ee113eSDavid van Moolenbroek void (*delete_func) (struct universe *universe, 320*83ee113eSDavid van Moolenbroek struct option_state *, int); 321*83ee113eSDavid van Moolenbroek int (*option_state_dereference) (struct universe *, 322*83ee113eSDavid van Moolenbroek struct option_state *, 323*83ee113eSDavid van Moolenbroek const char *, int); 324*83ee113eSDavid van Moolenbroek int (*decode) (struct option_state *, 325*83ee113eSDavid van Moolenbroek const unsigned char *, unsigned, struct universe *); 326*83ee113eSDavid van Moolenbroek int (*encapsulate) (struct data_string *, struct packet *, 327*83ee113eSDavid van Moolenbroek struct lease *, struct client_state *, 328*83ee113eSDavid van Moolenbroek struct option_state *, struct option_state *, 329*83ee113eSDavid van Moolenbroek struct binding_scope **, 330*83ee113eSDavid van Moolenbroek struct universe *); 331*83ee113eSDavid van Moolenbroek u_int32_t (*get_tag) (const unsigned char *); 332*83ee113eSDavid van Moolenbroek void (*store_tag) (unsigned char *, u_int32_t); 333*83ee113eSDavid van Moolenbroek u_int32_t (*get_length) (const unsigned char *); 334*83ee113eSDavid van Moolenbroek void (*store_length) (unsigned char *, u_int32_t); 335*83ee113eSDavid van Moolenbroek int tag_size, length_size; 336*83ee113eSDavid van Moolenbroek unsigned site_code_min, end; 337*83ee113eSDavid van Moolenbroek option_name_hash_t *name_hash; 338*83ee113eSDavid van Moolenbroek option_code_hash_t *code_hash; 339*83ee113eSDavid van Moolenbroek struct option *enc_opt; 340*83ee113eSDavid van Moolenbroek int index; 341*83ee113eSDavid van Moolenbroek 342*83ee113eSDavid van Moolenbroek /* Flags should probably become condensed. */ 343*83ee113eSDavid van Moolenbroek int concat_duplicates; 344*83ee113eSDavid van Moolenbroek }; 345*83ee113eSDavid van Moolenbroek 346*83ee113eSDavid van Moolenbroek struct option { 347*83ee113eSDavid van Moolenbroek const char *name; 348*83ee113eSDavid van Moolenbroek const char *format; 349*83ee113eSDavid van Moolenbroek struct universe *universe; 350*83ee113eSDavid van Moolenbroek unsigned code; 351*83ee113eSDavid van Moolenbroek int refcnt; 352*83ee113eSDavid van Moolenbroek }; 353