1161304Snetchild/* tree.c 2161304Snetchild 3161304Snetchild Routines for manipulating parse trees... */ 4161304Snetchild 5161304Snetchild/* 6161304Snetchild * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 7161304Snetchild * Copyright (c) 1995-2003 by Internet Software Consortium 8161304Snetchild * 9161304Snetchild * Permission to use, copy, modify, and distribute this software for any 10161304Snetchild * purpose with or without fee is hereby granted, provided that the above 11161304Snetchild * copyright notice and this permission notice appear in all copies. 12161304Snetchild * 13161304Snetchild * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 14161304Snetchild * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15161304Snetchild * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 16161304Snetchild * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17161304Snetchild * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18161304Snetchild * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 19161304Snetchild * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20161304Snetchild * 21161304Snetchild * Internet Systems Consortium, Inc. 22161304Snetchild * 950 Charter Street 23161304Snetchild * Redwood City, CA 94063 24161304Snetchild * <info@isc.org> 25161304Snetchild * http://www.isc.org/ 26161304Snetchild * 27161304Snetchild * This software has been written for Internet Systems Consortium 28161304Snetchild * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. 29161304Snetchild * To learn more about Internet Systems Consortium, see 30161304Snetchild * ``http://www.isc.org/''. To learn more about Vixie Enterprises, 31161304Snetchild * see ``http://www.vix.com''. To learn more about Nominum, Inc., see 32161304Snetchild * ``http://www.nominum.com''. 33161304Snetchild */ 34161304Snetchild 35161304Snetchild#ifndef lint 36161304Snetchildstatic char copyright[] = 37161304Snetchild"$Id: tree.c,v 1.6 2005/08/11 17:13:21 drochner Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; 38161304Snetchild#endif /* not lint */ 39235063Snetchild 40161304Snetchild#include "dhcpd.h" 41161304Snetchild#include <omapip/omapip_p.h> 42235063Snetchild 43293561Sdchaginstruct binding_scope *global_scope; 44161304Snetchild 45161304Snetchildstatic int do_host_lookup PROTO ((struct data_string *, 46293561Sdchagin struct dns_host_entry *)); 47293561Sdchagin 48235063Snetchild#ifdef NSUPDATE 49161304Snetchildstruct __res_state resolver_state; 50161304Snetchildint resolver_inited = 0; 51161304Snetchild#endif 52161304Snetchild 53161304Snetchildpair cons (car, cdr) 54161304Snetchild caddr_t car; 55161304Snetchild pair cdr; 56161304Snetchild{ 57161304Snetchild pair foo = (pair)dmalloc (sizeof *foo, MDL); 58161304Snetchild if (!foo) 59161304Snetchild log_fatal ("no memory for cons."); 60161304Snetchild foo -> car = car; 61161304Snetchild foo -> cdr = cdr; 62161304Snetchild return foo; 63161304Snetchild} 64161304Snetchild 65235063Snetchildint make_const_option_cache (oc, buffer, data, len, option, file, line) 66293561Sdchagin struct option_cache **oc; 67235063Snetchild struct buffer **buffer; 68235063Snetchild u_int8_t *data; 69235063Snetchild unsigned len; 70235063Snetchild struct option *option; 71235063Snetchild const char *file; 72235063Snetchild int line; 73235063Snetchild{ 74235063Snetchild struct buffer *bp; 75235063Snetchild 76235063Snetchild if (buffer) { 77235063Snetchild bp = *buffer; 78235063Snetchild *buffer = 0; 79235063Snetchild } else { 80235063Snetchild bp = (struct buffer *)0; 81235063Snetchild if (!buffer_allocate (&bp, len, file, line)) { 82235063Snetchild log_error ("%s(%d): can't allocate buffer.", 83235063Snetchild file, line); 84235063Snetchild return 0; 85235063Snetchild } 86235063Snetchild } 87235063Snetchild 88235063Snetchild if (!option_cache_allocate (oc, file, line)) { 89235063Snetchild log_error ("%s(%d): can't allocate option cache.", file, line); 90235063Snetchild buffer_dereference (&bp, file, line); 91235063Snetchild return 0; 92235063Snetchild } 93235063Snetchild 94235063Snetchild (*oc) -> data.len = len; 95235063Snetchild (*oc) -> data.buffer = bp; 96235063Snetchild (*oc) -> data.data = &bp -> data [0]; 97235063Snetchild (*oc) -> data.terminated = 0; 98235063Snetchild if (data) 99235063Snetchild memcpy (&bp -> data [0], data, len); 100235063Snetchild (*oc) -> option = option; 101235063Snetchild return 1; 102235063Snetchild} 103235063Snetchild 104235063Snetchildint make_host_lookup (expr, name) 105235063Snetchild struct expression **expr; 106235063Snetchild const char *name; 107235063Snetchild{ 108235063Snetchild if (!expression_allocate (expr, MDL)) { 109235063Snetchild log_error ("No memory for host lookup tree node."); 110235063Snetchild return 0; 111235063Snetchild } 112235063Snetchild (*expr) -> op = expr_host_lookup; 113235063Snetchild if (!enter_dns_host (&((*expr) -> data.host_lookup), name)) { 114235063Snetchild expression_dereference (expr, MDL); 115235063Snetchild return 0; 116235063Snetchild } 117235063Snetchild return 1; 118235063Snetchild} 119235063Snetchild 120235063Snetchildint enter_dns_host (dh, name) 121161304Snetchild struct dns_host_entry **dh; 122293565Sdchagin const char *name; 123161304Snetchild{ 124161304Snetchild /* XXX This should really keep a hash table of hostnames 125235063Snetchild XXX and just add a new reference to a hostname that 126235063Snetchild XXX already exists, if possible, rather than creating 127235063Snetchild XXX a new structure. */ 128161304Snetchild if (!dns_host_entry_allocate (dh, name, MDL)) { 129161304Snetchild log_error ("Can't allocate space for new host."); 130235063Snetchild return 0; 131235063Snetchild } 132161304Snetchild return 1; 133161304Snetchild} 134293565Sdchagin 135161304Snetchildint make_const_data (struct expression **expr, const unsigned char *data, 136161304Snetchild unsigned len, int terminated, int allocate, 137235063Snetchild const char *file, int line) 138235063Snetchild{ 139235063Snetchild struct expression *nt; 140235063Snetchild 141235063Snetchild if (!expression_allocate (expr, file, line)) { 142165408Sjkim log_error ("No memory for make_const_data tree node."); 143235063Snetchild return 0; 144161304Snetchild } 145161304Snetchild nt = *expr; 146165408Sjkim 147235063Snetchild if (len) { 148165408Sjkim if (allocate) { 149161304Snetchild if (!buffer_allocate (&nt -> data.const_data.buffer, 150161304Snetchild len + terminated, file, line)) { 151293566Sdchagin log_error ("Can't allocate const_data buffer"); 152161304Snetchild expression_dereference (expr, file, line); 153161304Snetchild return 0; 154235063Snetchild } 155235063Snetchild nt -> data.const_data.data = 156235063Snetchild &nt -> data.const_data.buffer -> data [0]; 157293561Sdchagin memcpy (nt -> data.const_data.buffer -> data, 158293561Sdchagin data, len + terminated); 159293561Sdchagin } else 160293561Sdchagin nt -> data.const_data.data = data; 161293561Sdchagin nt -> data.const_data.terminated = terminated; 162293561Sdchagin } else 163293561Sdchagin nt -> data.const_data.data = 0; 164293561Sdchagin 165293561Sdchagin nt -> op = expr_const_data; 166293561Sdchagin nt -> data.const_data.len = len; 167293561Sdchagin return 1; 168293561Sdchagin} 169293561Sdchagin 170293561Sdchaginint make_const_int (expr, val) 171161304Snetchild struct expression **expr; 172161304Snetchild unsigned long val; 173161304Snetchild{ 174161304Snetchild if (!expression_allocate (expr, MDL)) { 175161304Snetchild log_error ("No memory for make_const_int tree node."); 176161304Snetchild return 0; 177161304Snetchild } 178293561Sdchagin 179293561Sdchagin (*expr) -> op = expr_const_int; 180293561Sdchagin (*expr) -> data.const_int = val; 181293561Sdchagin return 1; 182293561Sdchagin} 183293561Sdchagin 184293561Sdchaginint make_concat (expr, left, right) 185293561Sdchagin struct expression **expr; 186293561Sdchagin struct expression *left, *right; 187293561Sdchagin{ 188293561Sdchagin /* If we're concatenating a null tree to a non-null tree, just 189293561Sdchagin return the non-null tree; if both trees are null, return 190235063Snetchild a null tree. */ 191235063Snetchild if (!left) { 192235063Snetchild if (!right) 193235063Snetchild return 0; 194165408Sjkim expression_reference (expr, right, MDL); 195235063Snetchild return 1; 196235063Snetchild } 197235063Snetchild if (!right) { 198165408Sjkim expression_reference (expr, left, MDL); 199161304Snetchild return 1; 200161304Snetchild } 201235063Snetchild 202165408Sjkim /* Otherwise, allocate a new node to concatenate the two. */ 203161304Snetchild if (!expression_allocate (expr, MDL)) { 204161304Snetchild log_error ("No memory for concatenation expression node."); 205161304Snetchild return 0; 206161304Snetchild } 207161304Snetchild 208161304Snetchild (*expr) -> op = expr_concat; 209293561Sdchagin expression_reference (&(*expr) -> data.concat [0], left, MDL); 210293561Sdchagin expression_reference (&(*expr) -> data.concat [1], right, MDL); 211293561Sdchagin return 1; 212293561Sdchagin} 213293561Sdchagin 214161304Snetchildint make_encapsulation (expr, name) 215293561Sdchagin struct expression **expr; 216293561Sdchagin struct data_string *name; 217161304Snetchild{ 218235063Snetchild /* Allocate a new node to store the encapsulation. */ 219235063Snetchild if (!expression_allocate (expr, MDL)) { 220161304Snetchild log_error ("No memory for encapsulation expression node."); 221235063Snetchild return 0; 222235063Snetchild } 223235063Snetchild 224235063Snetchild (*expr) -> op = expr_encapsulate; 225165408Sjkim data_string_copy (&(*expr) -> data.encapsulate, name, MDL); 226235063Snetchild return 1; 227293561Sdchagin} 228293561Sdchagin 229293561Sdchaginint make_substring (new, expr, offset, length) 230293561Sdchagin struct expression **new; 231293561Sdchagin struct expression *expr; 232293561Sdchagin struct expression *offset; 233293561Sdchagin struct expression *length; 234293561Sdchagin{ 235293561Sdchagin /* Allocate an expression node to compute the substring. */ 236293561Sdchagin if (!expression_allocate (new, MDL)) { 237293561Sdchagin log_error ("no memory for substring expression."); 238293561Sdchagin return 0; 239293561Sdchagin } 240293561Sdchagin (*new) -> op = expr_substring; 241293561Sdchagin expression_reference (&(*new) -> data.substring.expr, expr, MDL); 242293561Sdchagin expression_reference (&(*new) -> data.substring.offset, offset, MDL); 243293561Sdchagin expression_reference (&(*new) -> data.substring.len, length, MDL); 244293561Sdchagin return 1; 245293561Sdchagin} 246293561Sdchagin 247293561Sdchaginint make_limit (new, expr, limit) 248293561Sdchagin struct expression **new; 249293561Sdchagin struct expression *expr; 250293561Sdchagin int limit; 251293561Sdchagin{ 252293561Sdchagin 253293561Sdchagin /* Allocate a node to enforce a limit on evaluation. */ 254293561Sdchagin if (!expression_allocate (new, MDL)) 255293561Sdchagin log_error ("no memory for limit expression"); 256293561Sdchagin (*new) -> op = expr_substring; 257293561Sdchagin expression_reference (&(*new) -> data.substring.expr, expr, MDL); 258293561Sdchagin 259293561Sdchagin /* Offset is a constant 0. */ 260293561Sdchagin if (!expression_allocate (&(*new) -> data.substring.offset, MDL)) { 261293561Sdchagin log_error ("no memory for limit offset expression"); 262293561Sdchagin expression_dereference (new, MDL); 263293561Sdchagin return 0; 264293561Sdchagin } 265293561Sdchagin (*new) -> data.substring.offset -> op = expr_const_int; 266293561Sdchagin (*new) -> data.substring.offset -> data.const_int = 0; 267293561Sdchagin 268293561Sdchagin /* Length is a constant: the specified limit. */ 269293561Sdchagin if (!expression_allocate (&(*new) -> data.substring.len, MDL)) { 270293561Sdchagin log_error ("no memory for limit length expression"); 271293561Sdchagin expression_dereference (new, MDL); 272293561Sdchagin return 0; 273293561Sdchagin } 274293561Sdchagin (*new) -> data.substring.len -> op = expr_const_int; 275293561Sdchagin (*new) -> data.substring.len -> data.const_int = limit; 276293561Sdchagin 277293561Sdchagin return 1; 278293561Sdchagin} 279293561Sdchagin 280293561Sdchaginint option_cache (struct option_cache **oc, struct data_string *dp, 281293561Sdchagin struct expression *expr, struct option *option, 282293561Sdchagin const char *file, int line) 283293561Sdchagin{ 284293561Sdchagin if (!option_cache_allocate (oc, file, line)) 285293561Sdchagin return 0; 286293561Sdchagin if (dp) 287293561Sdchagin data_string_copy (&(*oc) -> data, dp, file, line); 288293561Sdchagin if (expr) 289293561Sdchagin expression_reference (&(*oc) -> expression, expr, file, line); 290293561Sdchagin (*oc) -> option = option; 291293561Sdchagin return 1; 292293561Sdchagin} 293293561Sdchagin 294293561Sdchaginint make_let (result, name) 295293561Sdchagin struct executable_statement **result; 296293561Sdchagin const char *name; 297293561Sdchagin{ 298293561Sdchagin if (!(executable_statement_allocate (result, MDL))) 299293561Sdchagin return 0; 300293561Sdchagin 301293561Sdchagin (*result) -> op = let_statement; 302293561Sdchagin (*result) -> data.let.name = dmalloc (strlen (name) + 1, MDL); 303293561Sdchagin if (!(*result) -> data.let.name) { 304293561Sdchagin executable_statement_dereference (result, MDL); 305293561Sdchagin return 0; 306293561Sdchagin } 307293561Sdchagin strcpy ((*result) -> data.let.name, name); 308293561Sdchagin return 1; 309293561Sdchagin} 310293561Sdchagin 311293561Sdchaginstatic int do_host_lookup (result, dns) 312293561Sdchagin struct data_string *result; 313293561Sdchagin struct dns_host_entry *dns; 314293561Sdchagin{ 315293561Sdchagin struct hostent *h; 316293561Sdchagin unsigned i, count; 317293561Sdchagin unsigned new_len; 318293561Sdchagin 319293561Sdchagin#ifdef DEBUG_EVAL 320293561Sdchagin log_debug ("time: now = %d dns = %d diff = %d", 321235063Snetchild cur_time, dns -> timeout, cur_time - dns -> timeout); 322235063Snetchild#endif 323235063Snetchild 324165408Sjkim /* If the record hasn't timed out, just copy the data and return. */ 325235063Snetchild if (cur_time <= dns -> timeout) { 326161304Snetchild#ifdef DEBUG_EVAL 327161304Snetchild log_debug ("easy copy: %d %s", 328235063Snetchild dns -> data.len, 329235063Snetchild (dns -> data.len > 4 330235063Snetchild ? inet_ntoa (*(struct in_addr *)(dns -> data.data)) 331235063Snetchild : 0)); 332235063Snetchild#endif 333235063Snetchild data_string_copy (result, &dns -> data, MDL); 334161304Snetchild return 1; 335161304Snetchild } 336161304Snetchild#ifdef DEBUG_EVAL 337161304Snetchild log_debug ("Looking up %s", dns -> hostname); 338161304Snetchild#endif 339161304Snetchild 340161304Snetchild /* Otherwise, look it up... */ 341161304Snetchild h = gethostbyname (dns -> hostname); 342161304Snetchild if (!h) { 343161304Snetchild#ifndef NO_H_ERRNO 344235063Snetchild switch (h_errno) { 345235063Snetchild case HOST_NOT_FOUND: 346161304Snetchild#endif 347235063Snetchild log_error ("%s: host unknown.", dns -> hostname); 348235063Snetchild#ifndef NO_H_ERRNO 349235063Snetchild break; 350235063Snetchild case TRY_AGAIN: 351165408Sjkim log_error ("%s: temporary name server failure", 352235063Snetchild dns -> hostname); 353161304Snetchild break; 354235063Snetchild case NO_RECOVERY: 355235063Snetchild log_error ("%s: name server failed", dns -> hostname); 356235063Snetchild break; 357165408Sjkim case NO_DATA: 358235063Snetchild log_error ("%s: no A record associated with address", 359165408Sjkim dns -> hostname); 360235063Snetchild } 361235063Snetchild#endif /* !NO_H_ERRNO */ 362235063Snetchild 363235063Snetchild /* Okay to try again after a minute. */ 364165408Sjkim dns -> timeout = cur_time + 60; 365235063Snetchild data_string_forget (&dns -> data, MDL); 366161304Snetchild return 0; 367235063Snetchild } 368235063Snetchild 369235063Snetchild#ifdef DEBUG_EVAL 370235063Snetchild log_debug ("Lookup succeeded; first address is %s", 371235063Snetchild inet_ntoa (h -> h_addr_list [0])); 372235063Snetchild#endif 373161304Snetchild 374161304Snetchild /* Count the number of addresses we got... */ 375161304Snetchild for (count = 0; h -> h_addr_list [count]; count++) 376161304Snetchild ; 377161304Snetchild 378293561Sdchagin /* Dereference the old data, if any. */ 379161304Snetchild data_string_forget (&dns -> data, MDL); 380161304Snetchild 381293561Sdchagin /* Do we need to allocate more memory? */ 382161304Snetchild new_len = count * h -> h_length; 383293561Sdchagin if (!buffer_allocate (&dns -> data.buffer, new_len, MDL)) 384293561Sdchagin { 385161304Snetchild log_error ("No memory for %s.", dns -> hostname); 386235063Snetchild return 0; 387235063Snetchild } 388161304Snetchild 389235063Snetchild dns -> data.data = &dns -> data.buffer -> data [0]; 390235063Snetchild dns -> data.len = new_len; 391235063Snetchild dns -> data.terminated = 0; 392235063Snetchild 393165408Sjkim /* Addresses are conveniently stored one to the buffer, so we 394235063Snetchild have to copy them out one at a time... :'( */ 395293561Sdchagin for (i = 0; i < count; i++) { 396293561Sdchagin memcpy (&dns -> data.buffer -> data [h -> h_length * i], 397293561Sdchagin h -> h_addr_list [i], (unsigned)(h -> h_length)); 398293561Sdchagin } 399293561Sdchagin#ifdef DEBUG_EVAL 400293561Sdchagin log_debug ("dns -> data: %x h -> h_addr_list [0]: %x", 401293561Sdchagin *(int *)(dns -> buffer), h -> h_addr_list [0]); 402293561Sdchagin#endif 403293561Sdchagin 404293561Sdchagin /* XXX Set the timeout for an hour from now. 405293561Sdchagin XXX This should really use the time on the DNS reply. */ 406293561Sdchagin dns -> timeout = cur_time + 3600; 407293561Sdchagin 408293561Sdchagin#ifdef DEBUG_EVAL 409293561Sdchagin log_debug ("hard copy: %d %s", dns -> data.len, 410293561Sdchagin (dns -> data.len > 4 411293561Sdchagin ? inet_ntoa (*(struct in_addr *)(dns -> data.data)) : 0)); 412293561Sdchagin#endif 413293561Sdchagin data_string_copy (result, &dns -> data, MDL); 414293561Sdchagin return 1; 415293561Sdchagin} 416293561Sdchagin 417293561Sdchaginint evaluate_expression (result, packet, lease, client_state, 418293561Sdchagin in_options, cfg_options, scope, expr, file, line) 419293561Sdchagin struct binding_value **result; 420293561Sdchagin struct packet *packet; 421293561Sdchagin struct lease *lease; 422293561Sdchagin struct client_state *client_state; 423293561Sdchagin struct option_state *in_options; 424293561Sdchagin struct option_state *cfg_options; 425293561Sdchagin struct binding_scope **scope; 426293561Sdchagin struct expression *expr; 427293561Sdchagin const char *file; 428293561Sdchagin int line; 429293561Sdchagin{ 430293561Sdchagin struct binding_value *bv; 431293561Sdchagin int status; 432293561Sdchagin struct binding *binding; 433293561Sdchagin 434293561Sdchagin bv = (struct binding_value *)0; 435293561Sdchagin 436293561Sdchagin if (expr -> op == expr_variable_reference) { 437293561Sdchagin if (!scope || !*scope) 438293561Sdchagin return 0; 439293561Sdchagin 440293561Sdchagin binding = find_binding (*scope, expr -> data.variable); 441293561Sdchagin 442293561Sdchagin if (binding && binding -> value) { 443293561Sdchagin if (result) 444293561Sdchagin binding_value_reference (result, 445293561Sdchagin binding -> value, 446293561Sdchagin file, line); 447293561Sdchagin return 1; 448161304Snetchild } else 449235063Snetchild return 0; 450235063Snetchild } else if (expr -> op == expr_funcall) { 451235063Snetchild struct string_list *s; 452165408Sjkim struct expression *arg; 453235063Snetchild struct binding_scope *ns; 454165408Sjkim struct binding *nb; 455161304Snetchild 456235063Snetchild if (!scope || !*scope) { 457235063Snetchild log_error ("%s: no such function.", 458235063Snetchild expr -> data.funcall.name); 459235063Snetchild return 0; 460235063Snetchild } 461235063Snetchild 462161304Snetchild binding = find_binding (*scope, expr -> data.funcall.name); 463161304Snetchild 464161304Snetchild if (!binding || !binding -> value) { 465165408Sjkim log_error ("%s: no such function.", 466165408Sjkim expr -> data.funcall.name); 467165408Sjkim return 0; 468165408Sjkim } 469165408Sjkim if (binding -> value -> type != binding_function) { 470293598Sdchagin log_error ("%s: not a function.", 471165408Sjkim expr -> data.funcall.name); 472235063Snetchild return 0; 473235063Snetchild } 474165408Sjkim 475235063Snetchild /* Create a new binding scope in which to define 476235063Snetchild the arguments to the function. */ 477235063Snetchild ns = (struct binding_scope *)0; 478165408Sjkim if (!binding_scope_allocate (&ns, MDL)) { 479235063Snetchild log_error ("%s: can't allocate argument scope.", 480165408Sjkim expr -> data.funcall.name); 481165408Sjkim return 0; 482293598Sdchagin } 483165408Sjkim 484293598Sdchagin arg = expr -> data.funcall.arglist; 485165408Sjkim s = binding -> value -> value.fundef -> args; 486165408Sjkim while (arg && s) { 487235063Snetchild nb = dmalloc (sizeof *nb, MDL); 488235063Snetchild if (!nb) { 489235063Snetchild blb: 490165408Sjkim binding_scope_dereference (&ns, MDL); 491235063Snetchild return 0; 492165408Sjkim } else { 493165408Sjkim memset (nb, 0, sizeof *nb); 494293598Sdchagin nb -> name = dmalloc (strlen (s -> string) + 1, 495293598Sdchagin MDL); 496293598Sdchagin if (nb -> name) 497235063Snetchild strcpy (nb -> name, s -> string); 498293598Sdchagin else { 499293598Sdchagin dfree (nb, MDL); 500293598Sdchagin nb = (struct binding *)0; 501235063Snetchild goto blb; 502165408Sjkim } 503165408Sjkim } 504293598Sdchagin evaluate_expression (&nb -> value, packet, lease, 505293598Sdchagin client_state, 506165408Sjkim in_options, cfg_options, scope, 507165408Sjkim arg -> data.arg.val, file, line); 508165408Sjkim nb -> next = ns -> bindings; 509161304Snetchild ns -> bindings = nb; 510161304Snetchild arg = arg -> data.arg.next; 511161304Snetchild s = s -> next; 512161304Snetchild } 513161304Snetchild if (arg) { 514293598Sdchagin log_error ("%s: too many arguments.", 515161304Snetchild expr -> data.funcall.name); 516235063Snetchild binding_scope_dereference (&ns, MDL); 517235063Snetchild return 0; 518235063Snetchild } 519235063Snetchild if (s) { 520235063Snetchild log_error ("%s: too few arguments.", 521235063Snetchild expr -> data.funcall.name); 522235063Snetchild binding_scope_dereference (&ns, MDL); 523235063Snetchild return 0; 524165408Sjkim } 525235063Snetchild 526161304Snetchild if (scope && *scope) 527235063Snetchild binding_scope_reference (&ns -> outer, *scope, MDL); 528235063Snetchild 529235063Snetchild status = (execute_statements 530235063Snetchild (&bv, packet, 531165408Sjkim lease, client_state, in_options, cfg_options, &ns, 532235063Snetchild binding -> value -> value.fundef -> statements)); 533161304Snetchild binding_scope_dereference (&ns, MDL); 534293598Sdchagin 535235063Snetchild if (!bv) 536235063Snetchild return 1; 537235063Snetchild } else if (is_boolean_expression (expr)) { 538235063Snetchild if (!binding_value_allocate (&bv, MDL)) 539165408Sjkim return 0; 540235063Snetchild bv -> type = binding_boolean; 541161304Snetchild status = (evaluate_boolean_expression 542161304Snetchild (&bv -> value.boolean, packet, lease, client_state, 543293598Sdchagin in_options, cfg_options, scope, expr)); 544161304Snetchild } else if (is_numeric_expression (expr)) { 545293598Sdchagin if (!binding_value_allocate (&bv, MDL)) 546161304Snetchild return 0; 547165408Sjkim bv -> type = binding_numeric; 548235063Snetchild status = (evaluate_numeric_expression 549235063Snetchild (&bv -> value.intval, packet, lease, client_state, 550235063Snetchild in_options, cfg_options, scope, expr)); 551235063Snetchild } else if (is_data_expression (expr)) { 552165408Sjkim if (!binding_value_allocate (&bv, MDL)) 553235063Snetchild return 0; 554161304Snetchild bv -> type = binding_data; 555161304Snetchild status = (evaluate_data_expression 556293598Sdchagin (&bv -> value.data, packet, lease, client_state, 557161304Snetchild in_options, cfg_options, scope, expr, MDL)); 558293598Sdchagin } else if (is_dns_expression (expr)) { 559293598Sdchagin#if defined (NSUPDATE) 560235063Snetchild if (!binding_value_allocate (&bv, MDL)) 561293598Sdchagin return 0; 562293598Sdchagin bv -> type = binding_dns; 563293598Sdchagin status = (evaluate_dns_expression 564293598Sdchagin (&bv -> value.dns, packet, lease, client_state, 565235063Snetchild in_options, cfg_options, scope, expr)); 566161304Snetchild#endif 567161304Snetchild } else { 568293598Sdchagin log_error ("%s: invalid expression type: %d", 569293598Sdchagin "evaluate_expression", expr -> op); 570161304Snetchild return 0; 571 } 572 if (result && status) 573 binding_value_reference (result, bv, file, line); 574 binding_value_dereference (&bv, MDL); 575 576 return status; 577} 578 579int binding_value_dereference (struct binding_value **v, 580 const char *file, int line) 581{ 582 struct binding_value *bv = *v; 583 584 *v = (struct binding_value *)0; 585 586 /* Decrement the reference count. If it's nonzero, we're 587 done. */ 588 --(bv -> refcnt); 589 rc_register (file, line, v, bv, bv -> refcnt, 1, RC_MISC); 590 if (bv -> refcnt > 0) 591 return 1; 592 if (bv -> refcnt < 0) { 593 log_error ("%s(%d): negative refcnt!", file, line); 594#if defined (DEBUG_RC_HISTORY) 595 dump_rc_history (bv); 596#endif 597#if defined (POINTER_DEBUG) 598 abort (); 599#else 600 return 0; 601#endif 602 } 603 604 switch (bv -> type) { 605 case binding_boolean: 606 case binding_numeric: 607 break; 608 case binding_data: 609 if (bv -> value.data.buffer) 610 data_string_forget (&bv -> value.data, file, line); 611 break; 612 case binding_dns: 613#if defined (NSUPDATE) 614 if (bv -> value.dns) { 615 if (bv -> value.dns -> r_data) { 616 dfree (bv -> value.dns -> r_data_ephem, MDL); 617 bv -> value.dns -> r_data = (unsigned char *)0; 618 bv -> value.dns -> r_data_ephem = 619 (unsigned char *)0; 620 } 621 minires_freeupdrec (bv -> value.dns); 622 } 623 break; 624#endif 625 default: 626 log_error ("%s(%d): invalid binding type: %d", 627 file, line, bv -> type); 628 return 0; 629 } 630 dfree (bv, file, line); 631 return 1; 632} 633 634#if defined (NSUPDATE) 635int evaluate_dns_expression (result, packet, lease, client_state, in_options, 636 cfg_options, scope, expr) 637 ns_updrec **result; 638 struct packet *packet; 639 struct lease *lease; 640 struct client_state *client_state; 641 struct option_state *in_options; 642 struct option_state *cfg_options; 643 struct binding_scope **scope; 644 struct expression *expr; 645{ 646 unsigned long ttl = 0; 647 char *tname; 648 struct data_string name, data; 649 int r0, r1, r2; 650 651 tname = NULL; /* XXXGCC -Wuninitialized */ 652 653 if (!result || *result) { 654 log_error ("evaluate_dns_expression called with non-null %s", 655 "result pointer"); 656#if defined (POINTER_DEBUG) 657 abort (); 658#else 659 return 0; 660#endif 661 } 662 663 switch (expr -> op) { 664#if defined (NSUPDATE) 665 case expr_ns_add: 666 r0 = evaluate_numeric_expression (&ttl, packet, lease, 667 client_state, 668 in_options, cfg_options, 669 scope, 670 expr -> data.ns_add.ttl); 671 goto nsfinish; 672 673 case expr_ns_exists: 674 ttl = 1; 675 676 case expr_ns_delete: 677 case expr_ns_not_exists: 678 r0 = 1; 679 nsfinish: 680 memset (&name, 0, sizeof name); 681 r1 = evaluate_data_expression (&name, packet, lease, 682 client_state, 683 in_options, cfg_options, scope, 684 expr -> data.ns_add.rrname, 685 MDL); 686 if (r1) { 687 /* The result of the evaluation may or may not 688 be NUL-terminated, but we need it 689 terminated for sure, so we have to allocate 690 a buffer and terminate it. */ 691 tname = dmalloc (name.len + 1, MDL); 692 if (!tname) { 693 r2 = 0; 694 r1 = 0; 695 data_string_forget (&name, MDL); 696 } else { 697 memcpy (tname, name.data, name.len); 698 tname [name.len] = 0; 699 memset (&data, 0, sizeof data); 700 r2 = evaluate_data_expression 701 (&data, packet, lease, client_state, 702 in_options, cfg_options, scope, 703 expr -> data.ns_add.rrdata, MDL); 704 } 705 } else { 706 r2 = 0; 707 tname = NULL; 708 } 709 if (r0 && r1 && (r2 || expr -> op != expr_ns_add)) { 710 *result = minires_mkupdrec (((expr -> op == expr_ns_add || 711 expr -> op == expr_ns_delete) 712 ? S_UPDATE : S_PREREQ), 713 tname, 714 expr -> data.ns_add.rrclass, 715 expr -> data.ns_add.rrtype, 716 ttl); 717 if (!*result) { 718 ngood: 719 if (r2) { 720 data_string_forget (&data, MDL); 721 r2 = 0; 722 } 723 } else { 724 if (data.len) { 725 /* As a special case, if we get exactly 726 four bytes of data, it's an IP address 727 represented as a 32-bit quantity, which 728 is actually what we *should* be getting 729 here. Because res_mkupdrec is currently 730 broken and expects a dotted quad, convert 731 it. This should be fixed when the new 732 resolver is merged. */ 733 if (data.len == 4) { 734 (*result) -> r_data_ephem = 735 dmalloc (16, MDL); 736 if (!(*result) -> r_data_ephem) 737 goto dpngood; 738 (*result) -> r_data = 739 (*result) -> r_data_ephem; 740 /*%Audit% 16 bytes max. %2004.06.17,Safe%*/ 741 sprintf ((char *)(*result) -> r_data_ephem, 742 "%u.%u.%u.%u", 743 data.data [0] & 0xff, 744 data.data [1] & 0xff, 745 data.data [2] & 0xff, 746 data.data [3] & 0xff); 747 (*result) -> r_size = 748 strlen ((const char *) 749 (*result) -> r_data); 750 } else { 751 (*result) -> r_size = data.len; 752 (*result) -> r_data_ephem = 753 dmalloc (data.len, MDL); 754 if (!(*result) -> r_data_ephem) { 755 dpngood: /* double plus ungood. */ 756 minires_freeupdrec (*result); 757 *result = 0; 758 goto ngood; 759 } 760 (*result) -> r_data = 761 (*result) -> r_data_ephem; 762 memcpy ((*result) -> r_data_ephem, 763 data.data, data.len); 764 } 765 } else { 766 (*result) -> r_data = 0; 767 (*result) -> r_size = 0; 768 } 769 switch (expr -> op) { 770 case expr_ns_add: 771 (*result) -> r_opcode = ADD; 772 break; 773 case expr_ns_delete: 774 (*result) -> r_opcode = DELETE; 775 break; 776 case expr_ns_exists: 777 (*result) -> r_opcode = YXRRSET; 778 break; 779 case expr_ns_not_exists: 780 (*result) -> r_opcode = NXRRSET; 781 break; 782 783 /* Can't happen, but satisfy gcc. */ 784 default: 785 break; 786 } 787 } 788 } 789 if (r1) { 790 data_string_forget (&name, MDL); 791 dfree (tname, MDL); 792 } 793 if (r2) 794 data_string_forget (&data, MDL); 795 /* One flaw in the thinking here: an IP address and an 796 ASCII string both look like data expressions, but 797 for A records, we want an ASCII string, not a 798 binary IP address. Do I need to turn binary IP 799 addresses into a seperate type? */ 800 return (r0 && r1 && 801 (r2 || expr -> op != expr_ns_add) && *result); 802 803#else 804 case expr_ns_add: 805 case expr_ns_delete: 806 case expr_ns_exists: 807 case expr_ns_not_exists: 808 return 0; 809#endif 810 case expr_funcall: 811 log_error ("%s: dns values for functions not supported.", 812 expr -> data.funcall.name); 813 break; 814 815 case expr_variable_reference: 816 log_error ("%s: dns values for variables not supported.", 817 expr -> data.variable); 818 break; 819 820 case expr_check: 821 case expr_equal: 822 case expr_not_equal: 823 case expr_and: 824 case expr_or: 825 case expr_not: 826 case expr_match: 827 case expr_static: 828 case expr_known: 829 case expr_exists: 830 case expr_variable_exists: 831 log_error ("Boolean opcode in evaluate_dns_expression: %d", 832 expr -> op); 833 return 0; 834 835 case expr_none: 836 case expr_substring: 837 case expr_suffix: 838 case expr_option: 839 case expr_hardware: 840 case expr_const_data: 841 case expr_packet: 842 case expr_concat: 843 case expr_encapsulate: 844 case expr_host_lookup: 845 case expr_encode_int8: 846 case expr_encode_int16: 847 case expr_encode_int32: 848 case expr_binary_to_ascii: 849 case expr_reverse: 850 case expr_filename: 851 case expr_sname: 852 case expr_pick_first_value: 853 case expr_host_decl_name: 854 case expr_config_option: 855 case expr_leased_address: 856 case expr_null: 857 log_error ("Data opcode in evaluate_dns_expression: %d", 858 expr -> op); 859 return 0; 860 861 case expr_extract_int8: 862 case expr_extract_int16: 863 case expr_extract_int32: 864 case expr_const_int: 865 case expr_lease_time: 866 case expr_dns_transaction: 867 case expr_add: 868 case expr_subtract: 869 case expr_multiply: 870 case expr_divide: 871 case expr_remainder: 872 case expr_binary_and: 873 case expr_binary_or: 874 case expr_binary_xor: 875 case expr_client_state: 876 log_error ("Numeric opcode in evaluate_dns_expression: %d", 877 expr -> op); 878 return 0; 879 880 case expr_function: 881 log_error ("Function opcode in evaluate_dns_expression: %d", 882 expr -> op); 883 return 0; 884 885 case expr_arg: 886 break; 887 } 888 889 log_error ("Bogus opcode in evaluate_dns_expression: %d", 890 expr -> op); 891 return 0; 892} 893#endif /* defined (NSUPDATE) */ 894 895int evaluate_boolean_expression (result, packet, lease, client_state, 896 in_options, cfg_options, scope, expr) 897 int *result; 898 struct packet *packet; 899 struct lease *lease; 900 struct client_state *client_state; 901 struct option_state *in_options; 902 struct option_state *cfg_options; 903 struct binding_scope **scope; 904 struct expression *expr; 905{ 906 struct data_string left; 907 int bleft, bright; 908 int sleft, sright; 909 struct binding *binding; 910 struct binding_value *bv, *obv; 911 912 switch (expr -> op) { 913 case expr_check: 914 *result = check_collection (packet, lease, 915 expr -> data.check); 916#if defined (DEBUG_EXPRESSIONS) 917 log_debug ("bool: check (%s) returns %s", 918 expr -> data.check -> name, 919 *result ? "true" : "false"); 920#endif 921 return 1; 922 923 case expr_equal: 924 case expr_not_equal: 925 bv = obv = (struct binding_value *)0; 926 sleft = evaluate_expression (&bv, packet, lease, client_state, 927 in_options, cfg_options, scope, 928 expr -> data.equal [0], MDL); 929 sright = evaluate_expression (&obv, packet, lease, 930 client_state, in_options, 931 cfg_options, scope, 932 expr -> data.equal [1], MDL); 933 if (sleft && sright) { 934 if (bv -> type != obv -> type) 935 *result = expr -> op == expr_not_equal; 936 else { 937 switch (obv -> type) { 938 case binding_boolean: 939 if (bv -> value.boolean == obv -> value.boolean) 940 *result = expr -> op == expr_equal; 941 else 942 *result = expr -> op == expr_not_equal; 943 break; 944 945 case binding_data: 946 if ((bv -> value.data.len == 947 obv -> value.data.len) && 948 !memcmp (bv -> value.data.data, 949 obv -> value.data.data, 950 obv -> value.data.len)) 951 *result = expr -> op == expr_equal; 952 else 953 *result = expr -> op == expr_not_equal; 954 break; 955 956 case binding_numeric: 957 if (bv -> value.intval == obv -> value.intval) 958 *result = expr -> op == expr_equal; 959 else 960 *result = expr -> op == expr_not_equal; 961 break; 962 963 case binding_dns: 964#if defined (NSUPDATE) 965 /* XXX This should be a comparison for equal 966 XXX values, not for identity. */ 967 if (bv -> value.dns == obv -> value.dns) 968 *result = expr -> op == expr_equal; 969 else 970 *result = expr -> op == expr_not_equal; 971#else 972 *result = expr -> op == expr_not_equal; 973#endif 974 break; 975 976 case binding_function: 977 if (bv -> value.fundef == obv -> value.fundef) 978 *result = expr -> op == expr_equal; 979 else 980 *result = expr -> op == expr_not_equal; 981 break; 982 default: 983 *result = expr -> op == expr_not_equal; 984 break; 985 } 986 } 987 } else if (!sleft && !sright) 988 *result = expr -> op == expr_equal; 989 else 990 *result = expr -> op == expr_not_equal; 991 992#if defined (DEBUG_EXPRESSIONS) 993 log_debug ("bool: %sequal = %s", 994 expr -> op == expr_not_equal ? "not" : "", 995 (*result ? "true" : "false")); 996#endif 997 if (sleft) 998 binding_value_dereference (&bv, MDL); 999 if (sright) 1000 binding_value_dereference (&obv, MDL); 1001 return 1; 1002 1003 case expr_and: 1004 sleft = evaluate_boolean_expression (&bleft, packet, lease, 1005 client_state, 1006 in_options, cfg_options, 1007 scope, 1008 expr -> data.and [0]); 1009 if (sleft && bleft) 1010 sright = evaluate_boolean_expression 1011 (&bright, packet, lease, client_state, 1012 in_options, cfg_options, 1013 scope, expr -> data.and [1]); 1014 else 1015 sright = bright = 0; 1016 1017#if defined (DEBUG_EXPRESSIONS) 1018 log_debug ("bool: and (%s, %s) = %s", 1019 sleft ? (bleft ? "true" : "false") : "NULL", 1020 sright ? (bright ? "true" : "false") : "NULL", 1021 ((sleft && sright) 1022 ? (bleft && bright ? "true" : "false") : "NULL")); 1023#endif 1024 if (sleft && sright) { 1025 *result = bleft && bright; 1026 return 1; 1027 } 1028 return 0; 1029 1030 case expr_or: 1031 bleft = bright = 0; 1032 sleft = evaluate_boolean_expression (&bleft, packet, lease, 1033 client_state, 1034 in_options, cfg_options, 1035 scope, 1036 expr -> data.or [0]); 1037 if (!sleft || !bleft) 1038 sright = evaluate_boolean_expression 1039 (&bright, packet, lease, client_state, 1040 in_options, cfg_options, 1041 scope, expr -> data.or [1]); 1042 else 1043 sright = 0; 1044#if defined (DEBUG_EXPRESSIONS) 1045 log_debug ("bool: or (%s, %s) = %s", 1046 sleft ? (bleft ? "true" : "false") : "NULL", 1047 sright ? (bright ? "true" : "false") : "NULL", 1048 ((sleft || sright) 1049 ? (bleft || bright ? "true" : "false") : "NULL")); 1050#endif 1051 if (sleft || sright) { 1052 *result = bleft || bright; 1053 return 1; 1054 } 1055 return 0; 1056 1057 case expr_not: 1058 sleft = evaluate_boolean_expression (&bleft, packet, lease, 1059 client_state, 1060 in_options, cfg_options, 1061 scope, 1062 expr -> data.not); 1063#if defined (DEBUG_EXPRESSIONS) 1064 log_debug ("bool: not (%s) = %s", 1065 sleft ? (bleft ? "true" : "false") : "NULL", 1066 ((sleft && sright) 1067 ? (!bleft ? "true" : "false") : "NULL")); 1068 1069#endif 1070 if (sleft) { 1071 *result = !bleft; 1072 return 1; 1073 } 1074 return 0; 1075 1076 case expr_exists: 1077 memset (&left, 0, sizeof left); 1078 if (!in_options || 1079 !get_option (&left, expr -> data.exists -> universe, 1080 packet, lease, client_state, 1081 in_options, cfg_options, in_options, 1082 scope, expr -> data.exists -> code, MDL)) 1083 *result = 0; 1084 else { 1085 *result = 1; 1086 data_string_forget (&left, MDL); 1087 } 1088#if defined (DEBUG_EXPRESSIONS) 1089 log_debug ("bool: exists %s.%s = %s", 1090 expr -> data.option -> universe -> name, 1091 expr -> data.option -> name, 1092 *result ? "true" : "false"); 1093#endif 1094 return 1; 1095 1096 case expr_known: 1097 if (!packet) { 1098#if defined (DEBUG_EXPRESSIONS) 1099 log_debug ("bool: known = NULL"); 1100#endif 1101 return 0; 1102 } 1103#if defined (DEBUG_EXPRESSIONS) 1104 log_debug ("bool: known = %s", 1105 packet -> known ? "true" : "false"); 1106#endif 1107 *result = packet -> known; 1108 return 1; 1109 1110 case expr_static: 1111 if (!lease || !(lease -> flags & STATIC_LEASE)) { 1112#if defined (DEBUG_EXPRESSIONS) 1113 log_debug ("bool: static = false (%s %s %s %d)", 1114 lease ? "y" : "n", 1115 (lease && (lease -> flags & STATIC_LEASE) 1116 ? "y" : "n"), 1117 piaddr (lease -> ip_addr), 1118 lease ? lease -> flags : 0); 1119#endif 1120 *result = 0; 1121 return 1; 1122 } 1123#if defined (DEBUG_EXPRESSIONS) 1124 log_debug ("bool: static = true"); 1125#endif 1126 *result = 1; 1127 return 1; 1128 1129 case expr_variable_exists: 1130 if (scope && *scope) { 1131 binding = find_binding (*scope, expr -> data.variable); 1132 1133 if (binding) { 1134 if (binding -> value) 1135 *result = 1; 1136 else 1137 *result = 0; 1138 } else 1139 *result = 0; 1140 } else 1141 *result = 0; 1142#if defined (DEBUG_EXPRESSIONS) 1143 log_debug ("boolean: %s? = %s", expr -> data.variable, 1144 *result ? "true" : "false"); 1145#endif 1146 return 1; 1147 1148 case expr_variable_reference: 1149 if (scope && *scope) { 1150 binding = find_binding (*scope, expr -> data.variable); 1151 1152 if (binding && binding -> value) { 1153 if (binding -> value -> type == 1154 binding_boolean) { 1155 *result = binding -> value -> value.boolean; 1156 sleft = 1; 1157 } else { 1158 log_error ("binding type %d in %s.", 1159 binding -> value -> type, 1160 "evaluate_boolean_expression"); 1161 sleft = 0; 1162 } 1163 } else 1164 sleft = 0; 1165 } else 1166 sleft = 0; 1167#if defined (DEBUG_EXPRESSIONS) 1168 log_debug ("boolean: %s = %s", expr -> data.variable, 1169 sleft ? (*result ? "true" : "false") : "NULL"); 1170#endif 1171 return sleft; 1172 1173 case expr_funcall: 1174 bv = (struct binding_value *)0; 1175 sleft = evaluate_expression (&bv, packet, lease, client_state, 1176 in_options, cfg_options, 1177 scope, expr, MDL); 1178 if (sleft) { 1179 if (bv -> type != binding_boolean) 1180 log_error ("%s() returned type %d in %s.", 1181 expr -> data.funcall.name, 1182 bv -> type, 1183 "evaluate_boolean_expression"); 1184 else 1185 *result = bv -> value.boolean; 1186 binding_value_dereference (&bv, MDL); 1187 } 1188#if defined (DEBUG_EXPRESSIONS) 1189 log_debug ("boolean: %s() = %s", expr -> data.funcall.name, 1190 sleft ? (*result ? "true" : "false") : "NULL"); 1191#endif 1192 break; 1193 1194 case expr_none: 1195 case expr_match: 1196 case expr_substring: 1197 case expr_suffix: 1198 case expr_option: 1199 case expr_hardware: 1200 case expr_const_data: 1201 case expr_packet: 1202 case expr_concat: 1203 case expr_encapsulate: 1204 case expr_host_lookup: 1205 case expr_encode_int8: 1206 case expr_encode_int16: 1207 case expr_encode_int32: 1208 case expr_binary_to_ascii: 1209 case expr_reverse: 1210 case expr_pick_first_value: 1211 case expr_host_decl_name: 1212 case expr_config_option: 1213 case expr_leased_address: 1214 case expr_null: 1215 case expr_filename: 1216 case expr_sname: 1217 log_error ("Data opcode in evaluate_boolean_expression: %d", 1218 expr -> op); 1219 return 0; 1220 1221 case expr_extract_int8: 1222 case expr_extract_int16: 1223 case expr_extract_int32: 1224 case expr_const_int: 1225 case expr_lease_time: 1226 case expr_dns_transaction: 1227 case expr_add: 1228 case expr_subtract: 1229 case expr_multiply: 1230 case expr_divide: 1231 case expr_remainder: 1232 case expr_binary_and: 1233 case expr_binary_or: 1234 case expr_binary_xor: 1235 case expr_client_state: 1236 log_error ("Numeric opcode in evaluate_boolean_expression: %d", 1237 expr -> op); 1238 return 0; 1239 1240 case expr_ns_add: 1241 case expr_ns_delete: 1242 case expr_ns_exists: 1243 case expr_ns_not_exists: 1244 log_error ("dns opcode in evaluate_boolean_expression: %d", 1245 expr -> op); 1246 return 0; 1247 1248 case expr_function: 1249 log_error ("function definition in evaluate_boolean_expr"); 1250 return 0; 1251 1252 case expr_arg: 1253 break; 1254 } 1255 1256 log_error ("Bogus opcode in evaluate_boolean_expression: %d", 1257 expr -> op); 1258 return 0; 1259} 1260 1261int evaluate_data_expression (result, packet, lease, client_state, 1262 in_options, cfg_options, scope, expr, file, line) 1263 struct data_string *result; 1264 struct packet *packet; 1265 struct lease *lease; 1266 struct client_state *client_state; 1267 struct option_state *in_options; 1268 struct option_state *cfg_options; 1269 struct binding_scope **scope; 1270 struct expression *expr; 1271 const char *file; 1272 int line; 1273{ 1274 struct data_string data, other; 1275 unsigned long offset, len; 1276 int s0, s1, s2, s3; 1277 int status; 1278 struct binding *binding; 1279 struct binding_value *bv; 1280 1281 status = 0; /* XXXGCC -Wuninitialized */ 1282 1283 switch (expr -> op) { 1284 /* Extract N bytes starting at byte M of a data string. */ 1285 case expr_substring: 1286 memset (&data, 0, sizeof data); 1287 s0 = evaluate_data_expression (&data, packet, lease, 1288 client_state, 1289 in_options, cfg_options, scope, 1290 expr -> data.substring.expr, 1291 MDL); 1292 1293 /* Evaluate the offset and length. */ 1294 s1 = evaluate_numeric_expression 1295 (&offset, packet, lease, client_state, in_options, 1296 cfg_options, scope, expr -> data.substring.offset); 1297 s2 = evaluate_numeric_expression (&len, packet, lease, 1298 client_state, 1299 in_options, cfg_options, 1300 scope, 1301 expr -> data.substring.len); 1302 1303 if (s0 && s1 && s2) { 1304 /* If the offset is after end of the string, 1305 return an empty string. Otherwise, do the 1306 adjustments and return what's left. */ 1307 if (data.len > offset) { 1308 data_string_copy (result, &data, file, line); 1309 result -> len -= offset; 1310 if (result -> len > len) { 1311 result -> len = len; 1312 result -> terminated = 0; 1313 } 1314 result -> data += offset; 1315 } 1316 s3 = 1; 1317 } else 1318 s3 = 0; 1319 1320#if defined (DEBUG_EXPRESSIONS) 1321 log_debug ("data: substring (%s, %s, %s) = %s", 1322 s0 ? print_hex_1 (data.len, data.data, 30) : "NULL", 1323 s1 ? print_dec_1 (offset) : "NULL", 1324 s2 ? print_dec_2 (len) : "NULL", 1325 (s3 ? print_hex_2 (result -> len, result -> data, 30) 1326 : "NULL")); 1327#endif 1328 if (s0) 1329 data_string_forget (&data, MDL); 1330 if (s3) 1331 return 1; 1332 return 0; 1333 1334 1335 /* Extract the last N bytes of a data string. */ 1336 case expr_suffix: 1337 memset (&data, 0, sizeof data); 1338 s0 = evaluate_data_expression (&data, packet, lease, 1339 client_state, 1340 in_options, cfg_options, scope, 1341 expr -> data.suffix.expr, MDL); 1342 /* Evaluate the length. */ 1343 s1 = evaluate_numeric_expression (&len, packet, lease, 1344 client_state, 1345 in_options, cfg_options, 1346 scope, 1347 expr -> data.suffix.len); 1348 if (s0 && s1) { 1349 data_string_copy (result, &data, file, line); 1350 1351 /* If we are returning the last N bytes of a 1352 string whose length is <= N, just return 1353 the string - otherwise, compute a new 1354 starting address and decrease the 1355 length. */ 1356 if (data.len > len) { 1357 result -> data += data.len - len; 1358 result -> len = len; 1359 } 1360 data_string_forget (&data, MDL); 1361 } 1362 1363#if defined (DEBUG_EXPRESSIONS) 1364 log_debug ("data: suffix (%s, %s) = %s", 1365 s0 ? print_hex_1 (data.len, data.data, 30) : "NULL", 1366 s1 ? print_dec_1 (len) : "NULL", 1367 ((s0 && s1) 1368 ? print_hex_2 (result -> len, result -> data, 30) 1369 : "NULL")); 1370#endif 1371 return s0 && s1; 1372 1373 /* Extract an option. */ 1374 case expr_option: 1375 if (in_options) 1376 s0 = get_option (result, 1377 expr -> data.option -> universe, 1378 packet, lease, client_state, 1379 in_options, cfg_options, in_options, 1380 scope, expr -> data.option -> code, 1381 file, line); 1382 else 1383 s0 = 0; 1384 1385#if defined (DEBUG_EXPRESSIONS) 1386 log_debug ("data: option %s.%s = %s", 1387 expr -> data.option -> universe -> name, 1388 expr -> data.option -> name, 1389 s0 ? print_hex_1 (result -> len, result -> data, 60) 1390 : "NULL"); 1391#endif 1392 return s0; 1393 1394 case expr_config_option: 1395 if (cfg_options) 1396 s0 = get_option (result, 1397 expr -> data.option -> universe, 1398 packet, lease, client_state, 1399 in_options, cfg_options, cfg_options, 1400 scope, expr -> data.option -> code, 1401 file, line); 1402 else 1403 s0 = 0; 1404 1405#if defined (DEBUG_EXPRESSIONS) 1406 log_debug ("data: config-option %s.%s = %s", 1407 expr -> data.option -> universe -> name, 1408 expr -> data.option -> name, 1409 s0 ? print_hex_1 (result -> len, result -> data, 60) 1410 : "NULL"); 1411#endif 1412 return s0; 1413 1414 /* Combine the hardware type and address. */ 1415 case expr_hardware: 1416 /* On the client, hardware is our hardware. */ 1417 if (client_state) { 1418 memset (result, 0, sizeof *result); 1419 result -> data = 1420 client_state -> interface -> hw_address.hbuf; 1421 result -> len = 1422 client_state -> interface -> hw_address.hlen; 1423#if defined (DEBUG_EXPRESSIONS) 1424 log_debug ("data: hardware = %s", 1425 print_hex_1 (result -> len, 1426 result -> data, 60)); 1427#endif 1428 return 1; 1429 } 1430 1431 /* The server cares about the client's hardware address, 1432 so only in the case where we are examining a packet can 1433 we return anything. */ 1434 if (!packet || !packet -> raw) { 1435 log_error ("data: hardware: raw packet not available"); 1436 return 0; 1437 } 1438 if (packet -> raw -> hlen > sizeof packet -> raw -> chaddr) { 1439 log_error ("data: hardware: invalid hlen (%d)\n", 1440 packet -> raw -> hlen); 1441 return 0; 1442 } 1443 result -> len = packet -> raw -> hlen + 1; 1444 if (buffer_allocate (&result -> buffer, result -> len, 1445 file, line)) { 1446 result -> data = &result -> buffer -> data [0]; 1447 result -> buffer -> data [0] = packet -> raw -> htype; 1448 memcpy (&result -> buffer -> data [1], 1449 packet -> raw -> chaddr, 1450 packet -> raw -> hlen); 1451 result -> terminated = 0; 1452 } else { 1453 log_error ("data: hardware: no memory for buffer."); 1454 return 0; 1455 } 1456#if defined (DEBUG_EXPRESSIONS) 1457 log_debug ("data: hardware = %s", 1458 print_hex_1 (result -> len, result -> data, 60)); 1459#endif 1460 return 1; 1461 1462 /* Extract part of the raw packet. */ 1463 case expr_packet: 1464 if (!packet || !packet -> raw) { 1465 log_error ("data: packet: raw packet not available"); 1466 return 0; 1467 } 1468 1469 s0 = evaluate_numeric_expression (&offset, packet, lease, 1470 client_state, 1471 in_options, cfg_options, 1472 scope, 1473 expr -> data.packet.offset); 1474 s1 = evaluate_numeric_expression (&len, 1475 packet, lease, client_state, 1476 in_options, cfg_options, 1477 scope, 1478 expr -> data.packet.len); 1479 if (s0 && s1 && offset < packet -> packet_length) { 1480 if (offset + len > packet -> packet_length) 1481 result -> len = 1482 packet -> packet_length - offset; 1483 else 1484 result -> len = len; 1485 if (buffer_allocate (&result -> buffer, 1486 result -> len, file, line)) { 1487 result -> data = &result -> buffer -> data [0]; 1488 memcpy (result -> buffer -> data, 1489 (((unsigned char *)(packet -> raw)) 1490 + offset), result -> len); 1491 result -> terminated = 0; 1492 } else { 1493 log_error ("data: packet: no buffer memory."); 1494 return 0; 1495 } 1496 s2 = 1; 1497 } else 1498 s2 = 0; 1499#if defined (DEBUG_EXPRESSIONS) 1500 log_debug ("data: packet (%ld, %ld) = %s", 1501 offset, len, 1502 s2 ? print_hex_1 (result -> len, 1503 result -> data, 60) : NULL); 1504#endif 1505 return s2; 1506 1507 /* The encapsulation of all defined options in an 1508 option space... */ 1509 case expr_encapsulate: 1510 if (cfg_options) 1511 s0 = option_space_encapsulate 1512 (result, packet, lease, client_state, 1513 in_options, cfg_options, scope, 1514 &expr -> data.encapsulate); 1515 else 1516 s0 = 0; 1517 1518#if defined (DEBUG_EXPRESSIONS) 1519 log_debug ("data: encapsulate (%s) = %s", 1520 expr -> data.encapsulate.data, 1521 s0 ? print_hex_1 (result -> len, 1522 result -> data, 60) : "NULL"); 1523#endif 1524 return s0; 1525 1526 /* Some constant data... */ 1527 case expr_const_data: 1528#if defined (DEBUG_EXPRESSIONS) 1529 log_debug ("data: const = %s", 1530 print_hex_1 (expr -> data.const_data.len, 1531 expr -> data.const_data.data, 60)); 1532#endif 1533 data_string_copy (result, 1534 &expr -> data.const_data, file, line); 1535 return 1; 1536 1537 /* Hostname lookup... */ 1538 case expr_host_lookup: 1539 s0 = do_host_lookup (result, expr -> data.host_lookup); 1540#if defined (DEBUG_EXPRESSIONS) 1541 log_debug ("data: DNS lookup (%s) = %s", 1542 expr -> data.host_lookup -> hostname, 1543 (s0 1544 ? print_dotted_quads (result -> len, result -> data) 1545 : "NULL")); 1546#endif 1547 return s0; 1548 1549 /* Concatenation... */ 1550 case expr_concat: 1551 memset (&data, 0, sizeof data); 1552 s0 = evaluate_data_expression (&data, packet, lease, 1553 client_state, 1554 in_options, cfg_options, scope, 1555 expr -> data.concat [0], MDL); 1556 memset (&other, 0, sizeof other); 1557 s1 = evaluate_data_expression (&other, packet, lease, 1558 client_state, 1559 in_options, cfg_options, scope, 1560 expr -> data.concat [1], MDL); 1561 1562 if (s0 && s1) { 1563 result -> len = data.len + other.len; 1564 if (!buffer_allocate (&result -> buffer, 1565 (result -> len + other.terminated), 1566 file, line)) { 1567 log_error ("data: concat: no memory"); 1568 result -> len = 0; 1569 data_string_forget (&data, MDL); 1570 data_string_forget (&other, MDL); 1571 return 0; 1572 } 1573 result -> data = &result -> buffer -> data [0]; 1574 memcpy (result -> buffer -> data, data.data, data.len); 1575 memcpy (&result -> buffer -> data [data.len], 1576 other.data, other.len + other.terminated); 1577 } 1578 1579 if (s0) 1580 data_string_forget (&data, MDL); 1581 if (s1) 1582 data_string_forget (&other, MDL); 1583#if defined (DEBUG_EXPRESSIONS) 1584 log_debug ("data: concat (%s, %s) = %s", 1585 s0 ? print_hex_1 (data.len, data.data, 20) : "NULL", 1586 s1 ? print_hex_2 (other.len, other.data, 20) : "NULL", 1587 ((s0 && s1) 1588 ? print_hex_3 (result -> len, result -> data, 30) 1589 : "NULL")); 1590#endif 1591 return s0 && s1; 1592 1593 case expr_encode_int8: 1594 s0 = evaluate_numeric_expression (&len, packet, lease, 1595 client_state, 1596 in_options, cfg_options, 1597 scope, 1598 expr -> data.encode_int); 1599 if (s0) { 1600 result -> len = 1; 1601 if (!buffer_allocate (&result -> buffer, 1602 1, file, line)) { 1603 log_error ("data: encode_int8: no memory"); 1604 result -> len = 0; 1605 s0 = 0; 1606 } else { 1607 result -> data = &result -> buffer -> data [0]; 1608 result -> buffer -> data [0] = len; 1609 } 1610 } else 1611 result -> len = 0; 1612 1613#if defined (DEBUG_EXPRESSIONS) 1614 if (!s0) 1615 log_debug ("data: encode_int8 (NULL) = NULL"); 1616 else 1617 log_debug ("data: encode_int8 (%ld) = %s", len, 1618 print_hex_2 (result -> len, 1619 result -> data, 20)); 1620#endif 1621 return s0; 1622 1623 1624 case expr_encode_int16: 1625 s0 = evaluate_numeric_expression (&len, packet, lease, 1626 client_state, 1627 in_options, cfg_options, 1628 scope, 1629 expr -> data.encode_int); 1630 if (s0) { 1631 result -> len = 2; 1632 if (!buffer_allocate (&result -> buffer, 2, 1633 file, line)) { 1634 log_error ("data: encode_int16: no memory"); 1635 result -> len = 0; 1636 s0 = 0; 1637 } else { 1638 result -> data = &result -> buffer -> data [0]; 1639 putUShort (result -> buffer -> data, len); 1640 } 1641 } else 1642 result -> len = 0; 1643 1644#if defined (DEBUG_EXPRESSIONS) 1645 if (!s0) 1646 log_debug ("data: encode_int16 (NULL) = NULL"); 1647 else 1648 log_debug ("data: encode_int16 (%ld) = %s", len, 1649 print_hex_2 (result -> len, 1650 result -> data, 20)); 1651#endif 1652 return s0; 1653 1654 case expr_encode_int32: 1655 s0 = evaluate_numeric_expression (&len, packet, lease, 1656 client_state, 1657 in_options, cfg_options, 1658 scope, 1659 expr -> data.encode_int); 1660 if (s0) { 1661 result -> len = 4; 1662 if (!buffer_allocate (&result -> buffer, 4, 1663 file, line)) { 1664 log_error ("data: encode_int32: no memory"); 1665 result -> len = 0; 1666 s0 = 0; 1667 } else { 1668 result -> data = &result -> buffer -> data [0]; 1669 putULong (result -> buffer -> data, len); 1670 } 1671 } else 1672 result -> len = 0; 1673 1674#if defined (DEBUG_EXPRESSIONS) 1675 if (!s0) 1676 log_debug ("data: encode_int32 (NULL) = NULL"); 1677 else 1678 log_debug ("data: encode_int32 (%ld) = %s", len, 1679 print_hex_2 (result -> len, 1680 result -> data, 20)); 1681#endif 1682 return s0; 1683 1684 case expr_binary_to_ascii: 1685 /* Evaluate the base (offset) and width (len): */ 1686 s0 = evaluate_numeric_expression 1687 (&offset, packet, lease, client_state, in_options, 1688 cfg_options, scope, expr -> data.b2a.base); 1689 s1 = evaluate_numeric_expression (&len, packet, lease, 1690 client_state, 1691 in_options, cfg_options, 1692 scope, 1693 expr -> data.b2a.width); 1694 1695 /* Evaluate the seperator string. */ 1696 memset (&data, 0, sizeof data); 1697 s2 = evaluate_data_expression (&data, packet, lease, 1698 client_state, 1699 in_options, cfg_options, scope, 1700 expr -> data.b2a.seperator, 1701 MDL); 1702 1703 /* Evaluate the data to be converted. */ 1704 memset (&other, 0, sizeof other); 1705 s3 = evaluate_data_expression (&other, packet, lease, 1706 client_state, 1707 in_options, cfg_options, scope, 1708 expr -> data.b2a.buffer, MDL); 1709 1710 if (s0 && s1 && s2 && s3) { 1711 unsigned buflen, i; 1712 1713 if (len != 8 && len != 16 && len != 32) { 1714 log_info ("binary_to_ascii: %s %ld!", 1715 "invalid width", len); 1716 status = 0; 1717 goto b2a_out; 1718 } 1719 len /= 8; 1720 1721 /* The buffer must be a multiple of the number's 1722 width. */ 1723 if (other.len % len) { 1724 log_info ("binary-to-ascii: %s %d %s %ld!", 1725 "length of buffer", other.len, 1726 "not a multiple of width", len); 1727 status = 0; 1728 goto b2a_out; 1729 } 1730 1731 /* Count the width of the output. */ 1732 buflen = 0; 1733 for (i = 0; i < other.len; i += len) { 1734 if (len == 1) { 1735 if (offset == 8) { 1736 if (other.data [i] < 8) 1737 buflen++; 1738 else if (other.data [i] < 64) 1739 buflen += 2; 1740 else 1741 buflen += 3; 1742 } else if (offset == 10) { 1743 if (other.data [i] < 10) 1744 buflen++; 1745 else if (other.data [i] < 100) 1746 buflen += 2; 1747 else 1748 buflen += 3; 1749 } else if (offset == 16) { 1750 if (other.data [i] < 16) 1751 buflen++; 1752 else 1753 buflen += 2; 1754 } else 1755 buflen += (converted_length 1756 (&other.data [i], 1757 offset, 1)); 1758 } else 1759 buflen += (converted_length 1760 (&other.data [i], 1761 offset, len)); 1762 if (i + len != other.len) 1763 buflen += data.len; 1764 } 1765 1766 if (!buffer_allocate (&result -> buffer, 1767 buflen + 1, file, line)) { 1768 log_error ("data: binary-to-ascii: no memory"); 1769 status = 0; 1770 goto b2a_out; 1771 } 1772 result -> data = &result -> buffer -> data [0]; 1773 result -> len = buflen; 1774 result -> terminated = 1; 1775 1776 buflen = 0; 1777 for (i = 0; i < other.len; i += len) { 1778 buflen += (binary_to_ascii 1779 (&result -> buffer -> data [buflen], 1780 &other.data [i], offset, len)); 1781 if (i + len != other.len) { 1782 memcpy (&result -> 1783 buffer -> data [buflen], 1784 data.data, data.len); 1785 buflen += data.len; 1786 } 1787 } 1788 /* NUL terminate. */ 1789 result -> buffer -> data [buflen] = 0; 1790 status = 1; 1791 } else 1792 status = 0; 1793 1794 b2a_out: 1795#if defined (DEBUG_EXPRESSIONS) 1796 log_debug ("data: binary-to-ascii (%s, %s, %s, %s) = %s", 1797 s0 ? print_dec_1 (offset) : "NULL", 1798 s1 ? print_dec_2 (len) : "NULL", 1799 s2 ? print_hex_1 (data.len, data.data, 30) : "NULL", 1800 s3 ? print_hex_2 (other.len, other.data, 30) : "NULL", 1801 (status ? print_hex_3 (result -> len, result -> data, 30) 1802 : "NULL")); 1803#endif 1804 if (s2) 1805 data_string_forget (&data, MDL); 1806 if (s3) 1807 data_string_forget (&other, MDL); 1808 if (status) 1809 return 1; 1810 return 0; 1811 1812 case expr_reverse: 1813 /* Evaluate the width (len): */ 1814 s0 = evaluate_numeric_expression 1815 (&len, packet, lease, client_state, in_options, 1816 cfg_options, scope, expr -> data.reverse.width); 1817 1818 /* Evaluate the data. */ 1819 memset (&data, 0, sizeof data); 1820 s1 = evaluate_data_expression (&data, packet, lease, 1821 client_state, 1822 in_options, cfg_options, scope, 1823 expr -> data.reverse.buffer, 1824 MDL); 1825 1826 if (s0 && s1) { 1827 int i; 1828 1829 /* The buffer must be a multiple of the number's 1830 width. */ 1831 if (data.len % len) { 1832 log_info ("reverse: %s %d %s %ld!", 1833 "length of buffer", data.len, 1834 "not a multiple of width", len); 1835 status = 0; 1836 goto reverse_out; 1837 } 1838 1839 /* XXX reverse in place? I don't think we can. */ 1840 if (!buffer_allocate (&result -> buffer, 1841 data.len, file, line)) { 1842 log_error ("data: reverse: no memory"); 1843 status = 0; 1844 goto reverse_out; 1845 } 1846 result -> data = &result -> buffer -> data [0]; 1847 result -> len = data.len; 1848 result -> terminated = 0; 1849 1850 for (i = 0; i < data.len; i += len) { 1851 memcpy (&result -> buffer -> data [i], 1852 &data.data [data.len - i - len], len); 1853 } 1854 status = 1; 1855 } else 1856 status = 0; 1857 1858 reverse_out: 1859#if defined (DEBUG_EXPRESSIONS) 1860 log_debug ("data: reverse (%s, %s) = %s", 1861 s0 ? print_dec_1 (len) : "NULL", 1862 s1 ? print_hex_1 (data.len, data.data, 30) : "NULL", 1863 (status ? print_hex_3 (result -> len, result -> data, 30) 1864 : "NULL")); 1865#endif 1866 if (s0) 1867 data_string_forget (&data, MDL); 1868 if (status) 1869 return 1; 1870 return 0; 1871 1872 case expr_leased_address: 1873 if (!lease) { 1874 log_error ("data: leased_address: not available"); 1875 return 0; 1876 } 1877 result -> len = lease -> ip_addr.len; 1878 if (buffer_allocate (&result -> buffer, result -> len, 1879 file, line)) { 1880 result -> data = &result -> buffer -> data [0]; 1881 memcpy (&result -> buffer -> data [0], 1882 lease -> ip_addr.iabuf, lease -> ip_addr.len); 1883 result -> terminated = 0; 1884 } else { 1885 log_error ("data: leased-address: no memory."); 1886 return 0; 1887 } 1888#if defined (DEBUG_EXPRESSIONS) 1889 log_debug ("data: leased-address = %s", 1890 print_hex_1 (result -> len, result -> data, 60)); 1891#endif 1892 return 1; 1893 1894 case expr_pick_first_value: 1895 memset (&data, 0, sizeof data); 1896 if ((evaluate_data_expression 1897 (result, packet, 1898 lease, client_state, in_options, cfg_options, 1899 scope, expr -> data.pick_first_value.car, MDL))) { 1900#if defined (DEBUG_EXPRESSIONS) 1901 log_debug ("data: pick_first_value (%s, xxx)", 1902 print_hex_1 (result -> len, 1903 result -> data, 40)); 1904#endif 1905 return 1; 1906 } 1907 1908 if (expr -> data.pick_first_value.cdr && 1909 (evaluate_data_expression 1910 (result, packet, 1911 lease, client_state, in_options, cfg_options, 1912 scope, expr -> data.pick_first_value.cdr, MDL))) { 1913#if defined (DEBUG_EXPRESSIONS) 1914 log_debug ("data: pick_first_value (NULL, %s)", 1915 print_hex_1 (result -> len, 1916 result -> data, 40)); 1917#endif 1918 return 1; 1919 } 1920 1921#if defined (DEBUG_EXPRESSIONS) 1922 log_debug ("data: pick_first_value (NULL, NULL) = NULL"); 1923#endif 1924 return 0; 1925 1926 case expr_host_decl_name: 1927 if (!lease || !lease -> host) { 1928 log_error ("data: host_decl_name: not available"); 1929 return 0; 1930 } 1931 result -> len = strlen (lease -> host -> name); 1932 if (buffer_allocate (&result -> buffer, 1933 result -> len + 1, file, line)) { 1934 result -> data = &result -> buffer -> data [0]; 1935 strcpy ((char *)&result -> buffer -> data [0], 1936 lease -> host -> name); 1937 result -> terminated = 1; 1938 } else { 1939 log_error ("data: host-decl-name: no memory."); 1940 return 0; 1941 } 1942#if defined (DEBUG_EXPRESSIONS) 1943 log_debug ("data: host-decl-name = %s", lease -> host -> name); 1944#endif 1945 return 1; 1946 1947 case expr_null: 1948#if defined (DEBUG_EXPRESSIONS) 1949 log_debug ("data: null = NULL"); 1950#endif 1951 return 0; 1952 1953 case expr_variable_reference: 1954 if (scope && *scope) { 1955 binding = find_binding (*scope, expr -> data.variable); 1956 1957 if (binding && binding -> value) { 1958 if (binding -> value -> type == binding_data) { 1959 data_string_copy (result, 1960 &binding -> value -> value.data, 1961 file, line); 1962 s0 = 1; 1963 } else if (binding -> value -> type != binding_data) { 1964 log_error ("binding type %d in %s.", 1965 binding -> value -> type, 1966 "evaluate_data_expression"); 1967 s0 = 0; 1968 } else 1969 s0 = 0; 1970 } else 1971 s0 = 0; 1972 } else 1973 s0 = 0; 1974#if defined (DEBUG_EXPRESSIONS) 1975 log_debug ("data: %s = %s", expr -> data.variable, 1976 s0 ? print_hex_1 (result -> len, 1977 result -> data, 50) : "NULL"); 1978#endif 1979 return s0; 1980 1981 case expr_funcall: 1982 bv = (struct binding_value *)0; 1983 s0 = evaluate_expression (&bv, packet, lease, client_state, 1984 in_options, cfg_options, 1985 scope, expr, MDL); 1986 if (s0) { 1987 if (bv -> type != binding_data) 1988 log_error ("%s() returned type %d in %s.", 1989 expr -> data.funcall.name, 1990 bv -> type, 1991 "evaluate_data_expression"); 1992 else 1993 data_string_copy (result, &bv -> value.data, 1994 file, line); 1995 binding_value_dereference (&bv, MDL); 1996 } 1997#if defined (DEBUG_EXPRESSIONS) 1998 log_debug ("data: %s = %s", expr -> data.funcall.name, 1999 s0 ? print_hex_1 (result -> len, 2000 result -> data, 50) : "NULL"); 2001#endif 2002 break; 2003 2004 /* Extract the filename. */ 2005 case expr_filename: 2006 if (packet && packet -> raw -> file [0]) { 2007 char *fn = 2008 memchr (packet -> raw -> file, 0, 2009 sizeof packet -> raw -> file); 2010 if (!fn) 2011 fn = ((char *)packet -> raw -> file + 2012 sizeof packet -> raw -> file); 2013 result -> len = fn - &(packet -> raw -> file [0]); 2014 if (buffer_allocate (&result -> buffer, 2015 result -> len + 1, file, line)) { 2016 result -> data = &result -> buffer -> data [0]; 2017 memcpy (&result -> buffer -> data [0], 2018 packet -> raw -> file, 2019 result -> len); 2020 result -> buffer -> data [result -> len] = 0; 2021 result -> terminated = 1; 2022 s0 = 1; 2023 } else { 2024 log_error ("data: filename: no memory."); 2025 s0 = 0; 2026 } 2027 } else 2028 s0 = 0; 2029 2030#if defined (DEBUG_EXPRESSIONS) 2031 log_info ("data: filename = \"%s\"", 2032 s0 ? (const char *)(result -> data) : "NULL"); 2033#endif 2034 return s0; 2035 2036 /* Extract the server name. */ 2037 case expr_sname: 2038 if (packet && packet -> raw -> sname [0]) { 2039 char *fn = 2040 memchr (packet -> raw -> sname, 0, 2041 sizeof packet -> raw -> sname); 2042 if (!fn) 2043 fn = ((char *)packet -> raw -> sname + 2044 sizeof packet -> raw -> sname); 2045 result -> len = fn - &packet -> raw -> sname [0]; 2046 if (buffer_allocate (&result -> buffer, 2047 result -> len + 1, file, line)) { 2048 result -> data = &result -> buffer -> data [0]; 2049 memcpy (&result -> buffer -> data [0], 2050 packet -> raw -> sname, 2051 result -> len); 2052 result -> buffer -> data [result -> len] = 0; 2053 result -> terminated = 1; 2054 s0 = 1; 2055 } else { 2056 log_error ("data: sname: no memory."); 2057 s0 = 0; 2058 } 2059 } else 2060 s0 = 0; 2061 2062#if defined (DEBUG_EXPRESSIONS) 2063 log_info ("data: sname = \"%s\"", 2064 s0 ? (const char *)(result -> data) : "NULL"); 2065#endif 2066 return s0; 2067 2068 case expr_check: 2069 case expr_equal: 2070 case expr_not_equal: 2071 case expr_and: 2072 case expr_or: 2073 case expr_not: 2074 case expr_match: 2075 case expr_static: 2076 case expr_known: 2077 case expr_none: 2078 case expr_exists: 2079 case expr_variable_exists: 2080 log_error ("Boolean opcode in evaluate_data_expression: %d", 2081 expr -> op); 2082 return 0; 2083 2084 case expr_extract_int8: 2085 case expr_extract_int16: 2086 case expr_extract_int32: 2087 case expr_const_int: 2088 case expr_lease_time: 2089 case expr_dns_transaction: 2090 case expr_add: 2091 case expr_subtract: 2092 case expr_multiply: 2093 case expr_divide: 2094 case expr_remainder: 2095 case expr_binary_and: 2096 case expr_binary_or: 2097 case expr_binary_xor: 2098 case expr_client_state: 2099 log_error ("Numeric opcode in evaluate_data_expression: %d", 2100 expr -> op); 2101 return 0; 2102 2103 case expr_ns_add: 2104 case expr_ns_delete: 2105 case expr_ns_exists: 2106 case expr_ns_not_exists: 2107 log_error ("dns update opcode in evaluate_data_expression: %d", 2108 expr -> op); 2109 return 0; 2110 2111 case expr_function: 2112 log_error ("function definition in evaluate_data_expression"); 2113 return 0; 2114 2115 case expr_arg: 2116 break; 2117 } 2118 2119 log_error ("Bogus opcode in evaluate_data_expression: %d", expr -> op); 2120 return 0; 2121} 2122 2123int evaluate_numeric_expression (result, packet, lease, client_state, 2124 in_options, cfg_options, scope, expr) 2125 unsigned long *result; 2126 struct packet *packet; 2127 struct lease *lease; 2128 struct client_state *client_state; 2129 struct option_state *in_options; 2130 struct option_state *cfg_options; 2131 struct binding_scope **scope; 2132 struct expression *expr; 2133{ 2134 struct data_string data; 2135 int status, sleft, sright; 2136#if defined (NSUPDATE) 2137 ns_updrec *nut; 2138 ns_updque uq; 2139#endif 2140 struct expression *cur, *next; 2141 struct binding *binding; 2142 struct binding_value *bv; 2143 unsigned long ileft, iright; 2144 2145 switch (expr -> op) { 2146 case expr_check: 2147 case expr_equal: 2148 case expr_not_equal: 2149 case expr_and: 2150 case expr_or: 2151 case expr_not: 2152 case expr_match: 2153 case expr_static: 2154 case expr_known: 2155 case expr_none: 2156 case expr_exists: 2157 case expr_variable_exists: 2158 log_error ("Boolean opcode in evaluate_numeric_expression: %d", 2159 expr -> op); 2160 return 0; 2161 2162 case expr_substring: 2163 case expr_suffix: 2164 case expr_option: 2165 case expr_hardware: 2166 case expr_const_data: 2167 case expr_packet: 2168 case expr_concat: 2169 case expr_encapsulate: 2170 case expr_host_lookup: 2171 case expr_encode_int8: 2172 case expr_encode_int16: 2173 case expr_encode_int32: 2174 case expr_binary_to_ascii: 2175 case expr_reverse: 2176 case expr_filename: 2177 case expr_sname: 2178 case expr_pick_first_value: 2179 case expr_host_decl_name: 2180 case expr_config_option: 2181 case expr_leased_address: 2182 case expr_null: 2183 log_error ("Data opcode in evaluate_numeric_expression: %d", 2184 expr -> op); 2185 return 0; 2186 2187 case expr_extract_int8: 2188 memset (&data, 0, sizeof data); 2189 status = evaluate_data_expression 2190 (&data, packet, lease, client_state, in_options, 2191 cfg_options, scope, expr -> data.extract_int, MDL); 2192 if (status) 2193 *result = data.data [0]; 2194#if defined (DEBUG_EXPRESSIONS) 2195 log_debug ("num: extract_int8 (%s) = %s", 2196 status ? print_hex_1 (data.len, data.data, 60) : "NULL", 2197 status ? print_dec_1 (*result) : "NULL" ); 2198#endif 2199 if (status) data_string_forget (&data, MDL); 2200 return status; 2201 2202 case expr_extract_int16: 2203 memset (&data, 0, sizeof data); 2204 status = (evaluate_data_expression 2205 (&data, packet, lease, client_state, in_options, 2206 cfg_options, scope, expr -> data.extract_int, MDL)); 2207 if (status && data.len >= 2) 2208 *result = getUShort (data.data); 2209#if defined (DEBUG_EXPRESSIONS) 2210 log_debug ("num: extract_int16 (%s) = %ld", 2211 ((status && data.len >= 2) ? 2212 print_hex_1 (data.len, data.data, 60) : "NULL"), 2213 *result); 2214#endif 2215 if (status) data_string_forget (&data, MDL); 2216 return (status && data.len >= 2); 2217 2218 case expr_extract_int32: 2219 memset (&data, 0, sizeof data); 2220 status = (evaluate_data_expression 2221 (&data, packet, lease, client_state, in_options, 2222 cfg_options, scope, expr -> data.extract_int, MDL)); 2223 if (status && data.len >= 4) 2224 *result = getULong (data.data); 2225#if defined (DEBUG_EXPRESSIONS) 2226 log_debug ("num: extract_int32 (%s) = %ld", 2227 ((status && data.len >= 4) ? 2228 print_hex_1 (data.len, data.data, 60) : "NULL"), 2229 *result); 2230#endif 2231 if (status) data_string_forget (&data, MDL); 2232 return (status && data.len >= 4); 2233 2234 case expr_const_int: 2235 *result = expr -> data.const_int; 2236#if defined (DEBUG_EXPRESSIONS) 2237 log_debug ("number: CONSTANT = %ld", *result); 2238#endif 2239 return 1; 2240 2241 case expr_lease_time: 2242 if (!lease) { 2243 log_error ("data: leased_lease: not available"); 2244 return 0; 2245 } 2246 if (lease -> ends < cur_time) { 2247 log_error ("%s %lu when it is now %lu", 2248 "data: lease_time: lease ends at", 2249 (long)(lease -> ends), (long)cur_time); 2250 return 0; 2251 } 2252 *result = lease -> ends - cur_time; 2253#if defined (DEBUG_EXPRESSIONS) 2254 log_debug ("number: lease-time = (%lu - %lu) = %ld", 2255 lease -> ends, 2256 cur_time, *result); 2257#endif 2258 return 1; 2259 2260 case expr_dns_transaction: 2261#if !defined (NSUPDATE) 2262 return 0; 2263#else 2264 if (!resolver_inited) { 2265 minires_ninit (&resolver_state); 2266 resolver_inited = 1; 2267 resolver_state.retrans = 1; 2268 resolver_state.retry = 1; 2269 } 2270 ISC_LIST_INIT (uq); 2271 cur = expr; 2272 do { 2273 next = cur -> data.dns_transaction.cdr; 2274 nut = 0; 2275 status = (evaluate_dns_expression 2276 (&nut, packet, 2277 lease, client_state, in_options, cfg_options, 2278 scope, cur -> data.dns_transaction.car)); 2279 if (!status) 2280 goto dns_bad; 2281 ISC_LIST_APPEND (uq, nut, r_link); 2282 cur = next; 2283 } while (next); 2284 2285 /* Do the update and record the error code, if there was 2286 an error; otherwise set it to NOERROR. */ 2287 *result = minires_nupdate (&resolver_state, 2288 ISC_LIST_HEAD (uq)); 2289 status = 1; 2290 2291 print_dns_status ((int)*result, &uq); 2292 2293 dns_bad: 2294 while (!ISC_LIST_EMPTY (uq)) { 2295 ns_updrec *tmp = ISC_LIST_HEAD (uq); 2296 ISC_LIST_UNLINK (uq, tmp, r_link); 2297 if (tmp -> r_data_ephem) { 2298 dfree (tmp -> r_data_ephem, MDL); 2299 tmp -> r_data = (unsigned char *)0; 2300 tmp -> r_data_ephem = (unsigned char *)0; 2301 } 2302 minires_freeupdrec (tmp); 2303 } 2304 return status; 2305#endif /* NSUPDATE */ 2306 2307 case expr_variable_reference: 2308 if (scope && *scope) { 2309 binding = find_binding (*scope, expr -> data.variable); 2310 2311 if (binding && binding -> value) { 2312 if (binding -> value -> type == binding_numeric) { 2313 *result = binding -> value -> value.intval; 2314 status = 1; 2315 } else { 2316 log_error ("binding type %d in %s.", 2317 binding -> value -> type, 2318 "evaluate_numeric_expression"); 2319 status = 0; 2320 } 2321 } else 2322 status = 0; 2323 } else 2324 status = 0; 2325#if defined (DEBUG_EXPRESSIONS) 2326 if (status) 2327 log_debug ("numeric: %s = %ld", 2328 expr -> data.variable, *result); 2329 else 2330 log_debug ("numeric: %s = NULL", 2331 expr -> data.variable); 2332#endif 2333 return status; 2334 2335 case expr_funcall: 2336 bv = (struct binding_value *)0; 2337 status = evaluate_expression (&bv, packet, lease, 2338 client_state, 2339 in_options, cfg_options, 2340 scope, expr, MDL); 2341 if (status) { 2342 if (bv -> type != binding_numeric) 2343 log_error ("%s() returned type %d in %s.", 2344 expr -> data.funcall.name, 2345 bv -> type, 2346 "evaluate_numeric_expression"); 2347 else 2348 *result = bv -> value.intval; 2349 binding_value_dereference (&bv, MDL); 2350 } 2351#if defined (DEBUG_EXPRESSIONS) 2352 log_debug ("data: %s = %ld", expr -> data.funcall.name, 2353 status ? *result : 0); 2354#endif 2355 break; 2356 2357 case expr_add: 2358 sleft = evaluate_numeric_expression (&ileft, packet, lease, 2359 client_state, 2360 in_options, cfg_options, 2361 scope, 2362 expr -> data.and [0]); 2363 sright = evaluate_numeric_expression (&iright, packet, lease, 2364 client_state, 2365 in_options, cfg_options, 2366 scope, 2367 expr -> data.and [1]); 2368 2369#if defined (DEBUG_EXPRESSIONS) 2370 if (sleft && sright) 2371 log_debug ("num: %ld + %ld = %ld", 2372 ileft, iright, ileft + iright); 2373 else if (sleft) 2374 log_debug ("num: %ld + NULL = NULL", ileft); 2375 else 2376 log_debug ("num: NULL + %ld = NULL", iright); 2377#endif 2378 if (sleft && sright) { 2379 *result = ileft + iright; 2380 return 1; 2381 } 2382 return 0; 2383 2384 case expr_subtract: 2385 sleft = evaluate_numeric_expression (&ileft, packet, lease, 2386 client_state, 2387 in_options, cfg_options, 2388 scope, 2389 expr -> data.and [0]); 2390 sright = evaluate_numeric_expression (&iright, packet, lease, 2391 client_state, 2392 in_options, cfg_options, 2393 scope, 2394 expr -> data.and [1]); 2395 2396#if defined (DEBUG_EXPRESSIONS) 2397 if (sleft && sright) 2398 log_debug ("num: %ld - %ld = %ld", 2399 ileft, iright, ileft - iright); 2400 else if (sleft) 2401 log_debug ("num: %ld - NULL = NULL", ileft); 2402 else 2403 log_debug ("num: NULL - %ld = NULL", iright); 2404#endif 2405 if (sleft && sright) { 2406 *result = ileft - iright; 2407 return 1; 2408 } 2409 return 0; 2410 2411 case expr_multiply: 2412 sleft = evaluate_numeric_expression (&ileft, packet, lease, 2413 client_state, 2414 in_options, cfg_options, 2415 scope, 2416 expr -> data.and [0]); 2417 sright = evaluate_numeric_expression (&iright, packet, lease, 2418 client_state, 2419 in_options, cfg_options, 2420 scope, 2421 expr -> data.and [1]); 2422 2423#if defined (DEBUG_EXPRESSIONS) 2424 if (sleft && sright) 2425 log_debug ("num: %ld * %ld = %ld", 2426 ileft, iright, ileft * iright); 2427 else if (sleft) 2428 log_debug ("num: %ld * NULL = NULL", ileft); 2429 else 2430 log_debug ("num: NULL * %ld = NULL", iright); 2431#endif 2432 if (sleft && sright) { 2433 *result = ileft * iright; 2434 return 1; 2435 } 2436 return 0; 2437 2438 case expr_divide: 2439 sleft = evaluate_numeric_expression (&ileft, packet, lease, 2440 client_state, 2441 in_options, cfg_options, 2442 scope, 2443 expr -> data.and [0]); 2444 sright = evaluate_numeric_expression (&iright, packet, lease, 2445 client_state, 2446 in_options, cfg_options, 2447 scope, 2448 expr -> data.and [1]); 2449 2450#if defined (DEBUG_EXPRESSIONS) 2451 if (sleft && sright) { 2452 if (iright != 0) 2453 log_debug ("num: %ld / %ld = %ld", 2454 ileft, iright, ileft / iright); 2455 else 2456 log_debug ("num: %ld / %ld = NULL", 2457 ileft, iright); 2458 } else if (sleft) 2459 log_debug ("num: %ld / NULL = NULL", ileft); 2460 else 2461 log_debug ("num: NULL / %ld = NULL", iright); 2462#endif 2463 if (sleft && sright && iright) { 2464 *result = ileft / iright; 2465 return 1; 2466 } 2467 return 0; 2468 2469 case expr_remainder: 2470 sleft = evaluate_numeric_expression (&ileft, packet, lease, 2471 client_state, 2472 in_options, cfg_options, 2473 scope, 2474 expr -> data.and [0]); 2475 sright = evaluate_numeric_expression (&iright, packet, lease, 2476 client_state, 2477 in_options, cfg_options, 2478 scope, 2479 expr -> data.and [1]); 2480 2481#if defined (DEBUG_EXPRESSIONS) 2482 if (sleft && sright) { 2483 if (iright != 0) 2484 log_debug ("num: %ld %% %ld = %ld", 2485 ileft, iright, ileft % iright); 2486 else 2487 log_debug ("num: %ld %% %ld = NULL", 2488 ileft, iright); 2489 } else if (sleft) 2490 log_debug ("num: %ld %% NULL = NULL", ileft); 2491 else 2492 log_debug ("num: NULL %% %ld = NULL", iright); 2493#endif 2494 if (sleft && sright && iright) { 2495 *result = ileft % iright; 2496 return 1; 2497 } 2498 return 0; 2499 2500 case expr_binary_and: 2501 sleft = evaluate_numeric_expression (&ileft, packet, lease, 2502 client_state, 2503 in_options, cfg_options, 2504 scope, 2505 expr -> data.and [0]); 2506 sright = evaluate_numeric_expression (&iright, packet, lease, 2507 client_state, 2508 in_options, cfg_options, 2509 scope, 2510 expr -> data.and [1]); 2511 2512#if defined (DEBUG_EXPRESSIONS) 2513 if (sleft && sright) 2514 log_debug ("num: %ld | %ld = %ld", 2515 ileft, iright, ileft & iright); 2516 else if (sleft) 2517 log_debug ("num: %ld & NULL = NULL", ileft); 2518 else 2519 log_debug ("num: NULL & %ld = NULL", iright); 2520#endif 2521 if (sleft && sright) { 2522 *result = ileft & iright; 2523 return 1; 2524 } 2525 return 0; 2526 2527 case expr_binary_or: 2528 sleft = evaluate_numeric_expression (&ileft, packet, lease, 2529 client_state, 2530 in_options, cfg_options, 2531 scope, 2532 expr -> data.and [0]); 2533 sright = evaluate_numeric_expression (&iright, packet, lease, 2534 client_state, 2535 in_options, cfg_options, 2536 scope, 2537 expr -> data.and [1]); 2538 2539#if defined (DEBUG_EXPRESSIONS) 2540 if (sleft && sright) 2541 log_debug ("num: %ld | %ld = %ld", 2542 ileft, iright, ileft | iright); 2543 else if (sleft) 2544 log_debug ("num: %ld | NULL = NULL", ileft); 2545 else 2546 log_debug ("num: NULL | %ld = NULL", iright); 2547#endif 2548 if (sleft && sright) { 2549 *result = ileft | iright; 2550 return 1; 2551 } 2552 return 0; 2553 2554 case expr_binary_xor: 2555 sleft = evaluate_numeric_expression (&ileft, packet, lease, 2556 client_state, 2557 in_options, cfg_options, 2558 scope, 2559 expr -> data.and [0]); 2560 sright = evaluate_numeric_expression (&iright, packet, lease, 2561 client_state, 2562 in_options, cfg_options, 2563 scope, 2564 expr -> data.and [1]); 2565 2566#if defined (DEBUG_EXPRESSIONS) 2567 if (sleft && sright) 2568 log_debug ("num: %ld ^ %ld = %ld", 2569 ileft, iright, ileft ^ iright); 2570 else if (sleft) 2571 log_debug ("num: %ld ^ NULL = NULL", ileft); 2572 else 2573 log_debug ("num: NULL ^ %ld = NULL", iright); 2574#endif 2575 if (sleft && sright) { 2576 *result = ileft ^ iright; 2577 return 1; 2578 } 2579 return 0; 2580 2581 case expr_client_state: 2582 if (client_state) { 2583#if defined (DEBUG_EXPRESSIONS) 2584 log_debug ("num: client-state = %d", 2585 client_state -> state); 2586#endif 2587 *result = client_state -> state; 2588 return 1; 2589 } else { 2590#if defined (DEBUG_EXPRESSIONS) 2591 log_debug ("num: client-state = NULL"); 2592#endif 2593 return 0; 2594 } 2595 2596 case expr_ns_add: 2597 case expr_ns_delete: 2598 case expr_ns_exists: 2599 case expr_ns_not_exists: 2600 log_error ("dns opcode in evaluate_numeric_expression: %d", 2601 expr -> op); 2602 return 0; 2603 2604 case expr_function: 2605 log_error ("function definition in evaluate_numeric_expr"); 2606 return 0; 2607 2608 case expr_arg: 2609 break; 2610 } 2611 2612 log_error ("evaluate_numeric_expression: bogus opcode %d", expr -> op); 2613 return 0; 2614} 2615 2616/* Return data hanging off of an option cache structure, or if there 2617 isn't any, evaluate the expression hanging off of it and return the 2618 result of that evaluation. There should never be both an expression 2619 and a valid data_string. */ 2620 2621int evaluate_option_cache (result, packet, lease, client_state, 2622 in_options, cfg_options, scope, oc, file, line) 2623 struct data_string *result; 2624 struct packet *packet; 2625 struct lease *lease; 2626 struct client_state *client_state; 2627 struct option_state *in_options; 2628 struct option_state *cfg_options; 2629 struct binding_scope **scope; 2630 struct option_cache *oc; 2631 const char *file; 2632 int line; 2633{ 2634 if (oc -> data.len) { 2635 data_string_copy (result, &oc -> data, file, line); 2636 return 1; 2637 } 2638 if (!oc -> expression) 2639 return 0; 2640 return evaluate_data_expression (result, packet, lease, client_state, 2641 in_options, cfg_options, scope, 2642 oc -> expression, file, line); 2643} 2644 2645/* Evaluate an option cache and extract a boolean from the result, 2646 returning the boolean. Return false if there is no data. */ 2647 2648int evaluate_boolean_option_cache (ignorep, packet, 2649 lease, client_state, in_options, 2650 cfg_options, scope, oc, file, line) 2651 int *ignorep; 2652 struct packet *packet; 2653 struct lease *lease; 2654 struct client_state *client_state; 2655 struct option_state *in_options; 2656 struct option_state *cfg_options; 2657 struct binding_scope **scope; 2658 struct option_cache *oc; 2659 const char *file; 2660 int line; 2661{ 2662 struct data_string ds; 2663 int result; 2664 2665 /* So that we can be called with option_lookup as an argument. */ 2666 if (!oc || !in_options) 2667 return 0; 2668 2669 memset (&ds, 0, sizeof ds); 2670 if (!evaluate_option_cache (&ds, packet, 2671 lease, client_state, in_options, 2672 cfg_options, scope, oc, file, line)) 2673 return 0; 2674 2675 if (ds.len) { 2676 result = ds.data [0]; 2677 if (result == 2) { 2678 result = 0; 2679 *ignorep = 1; 2680 } else 2681 *ignorep = 0; 2682 } else 2683 result = 0; 2684 data_string_forget (&ds, MDL); 2685 return result; 2686} 2687 2688 2689/* Evaluate a boolean expression and return the result of the evaluation, 2690 or FALSE if it failed. */ 2691 2692int evaluate_boolean_expression_result (ignorep, packet, lease, client_state, 2693 in_options, cfg_options, scope, expr) 2694 int *ignorep; 2695 struct packet *packet; 2696 struct lease *lease; 2697 struct client_state *client_state; 2698 struct option_state *in_options; 2699 struct option_state *cfg_options; 2700 struct binding_scope **scope; 2701 struct expression *expr; 2702{ 2703 int result; 2704 2705 /* So that we can be called with option_lookup as an argument. */ 2706 if (!expr) 2707 return 0; 2708 2709 if (!evaluate_boolean_expression (&result, packet, lease, client_state, 2710 in_options, cfg_options, 2711 scope, expr)) 2712 return 0; 2713 2714 if (result == 2) { 2715 *ignorep = 1; 2716 result = 0; 2717 } else 2718 *ignorep = 0; 2719 return result; 2720} 2721 2722 2723/* Dereference an expression node, and if the reference count goes to zero, 2724 dereference any data it refers to, and then free it. */ 2725void expression_dereference (eptr, file, line) 2726 struct expression **eptr; 2727 const char *file; 2728 int line; 2729{ 2730 struct expression *expr = *eptr; 2731 2732 /* Zero the pointer. */ 2733 *eptr = (struct expression *)0; 2734 2735 /* Decrement the reference count. If it's nonzero, we're 2736 done. */ 2737 --(expr -> refcnt); 2738 rc_register (file, line, eptr, expr, expr -> refcnt, 1, RC_MISC); 2739 if (expr -> refcnt > 0) 2740 return; 2741 if (expr -> refcnt < 0) { 2742 log_error ("%s(%d): negative refcnt!", file, line); 2743#if defined (DEBUG_RC_HISTORY) 2744 dump_rc_history (expr); 2745#endif 2746#if defined (POINTER_DEBUG) 2747 abort (); 2748#else 2749 return; 2750#endif 2751 } 2752 2753 /* Dereference subexpressions. */ 2754 switch (expr -> op) { 2755 /* All the binary operators can be handled the same way. */ 2756 case expr_equal: 2757 case expr_not_equal: 2758 case expr_concat: 2759 case expr_and: 2760 case expr_or: 2761 case expr_add: 2762 case expr_subtract: 2763 case expr_multiply: 2764 case expr_divide: 2765 case expr_remainder: 2766 case expr_binary_and: 2767 case expr_binary_or: 2768 case expr_binary_xor: 2769 case expr_client_state: 2770 if (expr -> data.equal [0]) 2771 expression_dereference (&expr -> data.equal [0], 2772 file, line); 2773 if (expr -> data.equal [1]) 2774 expression_dereference (&expr -> data.equal [1], 2775 file, line); 2776 break; 2777 2778 case expr_substring: 2779 if (expr -> data.substring.expr) 2780 expression_dereference (&expr -> data.substring.expr, 2781 file, line); 2782 if (expr -> data.substring.offset) 2783 expression_dereference (&expr -> data.substring.offset, 2784 file, line); 2785 if (expr -> data.substring.len) 2786 expression_dereference (&expr -> data.substring.len, 2787 file, line); 2788 break; 2789 2790 case expr_suffix: 2791 if (expr -> data.suffix.expr) 2792 expression_dereference (&expr -> data.suffix.expr, 2793 file, line); 2794 if (expr -> data.suffix.len) 2795 expression_dereference (&expr -> data.suffix.len, 2796 file, line); 2797 break; 2798 2799 case expr_not: 2800 if (expr -> data.not) 2801 expression_dereference (&expr -> data.not, file, line); 2802 break; 2803 2804 case expr_packet: 2805 if (expr -> data.packet.offset) 2806 expression_dereference (&expr -> data.packet.offset, 2807 file, line); 2808 if (expr -> data.packet.len) 2809 expression_dereference (&expr -> data.packet.len, 2810 file, line); 2811 break; 2812 2813 case expr_extract_int8: 2814 case expr_extract_int16: 2815 case expr_extract_int32: 2816 if (expr -> data.extract_int) 2817 expression_dereference (&expr -> data.extract_int, 2818 file, line); 2819 break; 2820 2821 case expr_encode_int8: 2822 case expr_encode_int16: 2823 case expr_encode_int32: 2824 if (expr -> data.encode_int) 2825 expression_dereference (&expr -> data.encode_int, 2826 file, line); 2827 break; 2828 2829 case expr_encapsulate: 2830 case expr_const_data: 2831 data_string_forget (&expr -> data.const_data, file, line); 2832 break; 2833 2834 case expr_host_lookup: 2835 if (expr -> data.host_lookup) 2836 dns_host_entry_dereference (&expr -> data.host_lookup, 2837 file, line); 2838 break; 2839 2840 case expr_binary_to_ascii: 2841 if (expr -> data.b2a.base) 2842 expression_dereference (&expr -> data.b2a.base, 2843 file, line); 2844 if (expr -> data.b2a.width) 2845 expression_dereference (&expr -> data.b2a.width, 2846 file, line); 2847 if (expr -> data.b2a.seperator) 2848 expression_dereference (&expr -> data.b2a.seperator, 2849 file, line); 2850 if (expr -> data.b2a.buffer) 2851 expression_dereference (&expr -> data.b2a.buffer, 2852 file, line); 2853 break; 2854 2855 case expr_pick_first_value: 2856 if (expr -> data.pick_first_value.car) 2857 expression_dereference (&expr -> data.pick_first_value.car, 2858 file, line); 2859 if (expr -> data.pick_first_value.cdr) 2860 expression_dereference (&expr -> data.pick_first_value.cdr, 2861 file, line); 2862 break; 2863 2864 case expr_reverse: 2865 if (expr -> data.reverse.width) 2866 expression_dereference (&expr -> data.reverse.width, 2867 file, line); 2868 if (expr -> data.reverse.buffer) 2869 expression_dereference 2870 (&expr -> data.reverse.buffer, file, line); 2871 break; 2872 2873 case expr_dns_transaction: 2874 if (expr -> data.dns_transaction.car) 2875 expression_dereference (&expr -> data.dns_transaction.car, 2876 file, line); 2877 if (expr -> data.dns_transaction.cdr) 2878 expression_dereference (&expr -> data.dns_transaction.cdr, 2879 file, line); 2880 break; 2881 2882 case expr_ns_add: 2883 if (expr -> data.ns_add.rrname) 2884 expression_dereference (&expr -> data.ns_add.rrname, 2885 file, line); 2886 if (expr -> data.ns_add.rrdata) 2887 expression_dereference (&expr -> data.ns_add.rrdata, 2888 file, line); 2889 if (expr -> data.ns_add.ttl) 2890 expression_dereference (&expr -> data.ns_add.ttl, 2891 file, line); 2892 break; 2893 2894 case expr_ns_delete: 2895 case expr_ns_exists: 2896 case expr_ns_not_exists: 2897 if (expr -> data.ns_delete.rrname) 2898 expression_dereference (&expr -> data.ns_delete.rrname, 2899 file, line); 2900 if (expr -> data.ns_delete.rrdata) 2901 expression_dereference (&expr -> data.ns_delete.rrdata, 2902 file, line); 2903 break; 2904 2905 case expr_variable_reference: 2906 case expr_variable_exists: 2907 if (expr -> data.variable) 2908 dfree (expr -> data.variable, file, line); 2909 break; 2910 2911 case expr_funcall: 2912 if (expr -> data.funcall.name) 2913 dfree (expr -> data.funcall.name, file, line); 2914 if (expr -> data.funcall.arglist) 2915 expression_dereference (&expr -> data.funcall.arglist, 2916 file, line); 2917 break; 2918 2919 case expr_arg: 2920 if (expr -> data.arg.val) 2921 expression_dereference (&expr -> data.arg.val, 2922 file, line); 2923 if (expr -> data.arg.next) 2924 expression_dereference (&expr -> data.arg.next, 2925 file, line); 2926 break; 2927 2928 case expr_function: 2929 fundef_dereference (&expr -> data.func, file, line); 2930 break; 2931 2932 /* No subexpressions. */ 2933 case expr_leased_address: 2934 case expr_lease_time: 2935 case expr_filename: 2936 case expr_sname: 2937 case expr_const_int: 2938 case expr_check: 2939 case expr_option: 2940 case expr_hardware: 2941 case expr_exists: 2942 case expr_known: 2943 case expr_null: 2944 break; 2945 2946 default: 2947 break; 2948 } 2949 free_expression (expr, MDL); 2950} 2951 2952int is_dns_expression (expr) 2953 struct expression *expr; 2954{ 2955 return (expr -> op == expr_ns_add || 2956 expr -> op == expr_ns_delete || 2957 expr -> op == expr_ns_exists || 2958 expr -> op == expr_ns_not_exists); 2959} 2960 2961int is_boolean_expression (expr) 2962 struct expression *expr; 2963{ 2964 return (expr -> op == expr_check || 2965 expr -> op == expr_exists || 2966 expr -> op == expr_variable_exists || 2967 expr -> op == expr_equal || 2968 expr -> op == expr_not_equal || 2969 expr -> op == expr_and || 2970 expr -> op == expr_or || 2971 expr -> op == expr_not || 2972 expr -> op == expr_known || 2973 expr -> op == expr_static); 2974} 2975 2976int is_data_expression (expr) 2977 struct expression *expr; 2978{ 2979 return (expr -> op == expr_substring || 2980 expr -> op == expr_suffix || 2981 expr -> op == expr_option || 2982 expr -> op == expr_hardware || 2983 expr -> op == expr_const_data || 2984 expr -> op == expr_packet || 2985 expr -> op == expr_concat || 2986 expr -> op == expr_encapsulate || 2987 expr -> op == expr_encode_int8 || 2988 expr -> op == expr_encode_int16 || 2989 expr -> op == expr_encode_int32 || 2990 expr -> op == expr_host_lookup || 2991 expr -> op == expr_binary_to_ascii || 2992 expr -> op == expr_filename || 2993 expr -> op == expr_sname || 2994 expr -> op == expr_reverse || 2995 expr -> op == expr_pick_first_value || 2996 expr -> op == expr_host_decl_name || 2997 expr -> op == expr_leased_address || 2998 expr -> op == expr_config_option || 2999 expr -> op == expr_null); 3000} 3001 3002int is_numeric_expression (expr) 3003 struct expression *expr; 3004{ 3005 return (expr -> op == expr_extract_int8 || 3006 expr -> op == expr_extract_int16 || 3007 expr -> op == expr_extract_int32 || 3008 expr -> op == expr_const_int || 3009 expr -> op == expr_lease_time || 3010 expr -> op == expr_dns_transaction || 3011 expr -> op == expr_add || 3012 expr -> op == expr_subtract || 3013 expr -> op == expr_multiply || 3014 expr -> op == expr_divide || 3015 expr -> op == expr_remainder || 3016 expr -> op == expr_binary_and || 3017 expr -> op == expr_binary_or || 3018 expr -> op == expr_binary_xor || 3019 expr -> op == expr_client_state); 3020} 3021 3022int is_compound_expression (expr) 3023 struct expression *expr; 3024{ 3025 return (expr -> op == expr_ns_add || 3026 expr -> op == expr_ns_delete || 3027 expr -> op == expr_ns_exists || 3028 expr -> op == expr_ns_not_exists || 3029 expr -> op == expr_substring || 3030 expr -> op == expr_suffix || 3031 expr -> op == expr_option || 3032 expr -> op == expr_concat || 3033 expr -> op == expr_encode_int8 || 3034 expr -> op == expr_encode_int16 || 3035 expr -> op == expr_encode_int32 || 3036 expr -> op == expr_binary_to_ascii || 3037 expr -> op == expr_reverse || 3038 expr -> op == expr_pick_first_value || 3039 expr -> op == expr_config_option || 3040 expr -> op == expr_extract_int8 || 3041 expr -> op == expr_extract_int16 || 3042 expr -> op == expr_extract_int32 || 3043 expr -> op == expr_dns_transaction); 3044} 3045 3046static int op_val PROTO ((enum expr_op)); 3047 3048static int op_val (op) 3049 enum expr_op op; 3050{ 3051 switch (op) { 3052 case expr_none: 3053 case expr_match: 3054 case expr_static: 3055 case expr_check: 3056 case expr_substring: 3057 case expr_suffix: 3058 case expr_concat: 3059 case expr_encapsulate: 3060 case expr_host_lookup: 3061 case expr_not: 3062 case expr_option: 3063 case expr_hardware: 3064 case expr_packet: 3065 case expr_const_data: 3066 case expr_extract_int8: 3067 case expr_extract_int16: 3068 case expr_extract_int32: 3069 case expr_encode_int8: 3070 case expr_encode_int16: 3071 case expr_encode_int32: 3072 case expr_const_int: 3073 case expr_exists: 3074 case expr_variable_exists: 3075 case expr_known: 3076 case expr_binary_to_ascii: 3077 case expr_reverse: 3078 case expr_filename: 3079 case expr_sname: 3080 case expr_pick_first_value: 3081 case expr_host_decl_name: 3082 case expr_config_option: 3083 case expr_leased_address: 3084 case expr_lease_time: 3085 case expr_dns_transaction: 3086 case expr_null: 3087 case expr_variable_reference: 3088 case expr_ns_add: 3089 case expr_ns_delete: 3090 case expr_ns_exists: 3091 case expr_ns_not_exists: 3092 case expr_arg: 3093 case expr_funcall: 3094 case expr_function: 3095 /* XXXDPN: Need to assign sane precedences to these. */ 3096 case expr_binary_and: 3097 case expr_binary_or: 3098 case expr_binary_xor: 3099 case expr_client_state: 3100 return 100; 3101 3102 case expr_equal: 3103 case expr_not_equal: 3104 return 4; 3105 3106 case expr_or: 3107 case expr_and: 3108 return 3; 3109 3110 case expr_add: 3111 case expr_subtract: 3112 return 2; 3113 3114 case expr_multiply: 3115 case expr_divide: 3116 case expr_remainder: 3117 return 1; 3118 } 3119 return 100; 3120} 3121 3122int op_precedence (op1, op2) 3123 enum expr_op op1, op2; 3124{ 3125 3126 return op_val (op1) - op_val (op2); 3127} 3128 3129enum expression_context expression_context (struct expression *expr) 3130{ 3131 if (is_data_expression (expr)) 3132 return context_data; 3133 if (is_numeric_expression (expr)) 3134 return context_numeric; 3135 if (is_boolean_expression (expr)) 3136 return context_boolean; 3137 if (is_dns_expression (expr)) 3138 return context_dns; 3139 return context_any; 3140} 3141 3142enum expression_context op_context (op) 3143 enum expr_op op; 3144{ 3145 switch (op) { 3146/* XXX Why aren't these specific? */ 3147 case expr_none: 3148 case expr_match: 3149 case expr_static: 3150 case expr_check: 3151 case expr_substring: 3152 case expr_suffix: 3153 case expr_concat: 3154 case expr_encapsulate: 3155 case expr_host_lookup: 3156 case expr_not: 3157 case expr_option: 3158 case expr_hardware: 3159 case expr_packet: 3160 case expr_const_data: 3161 case expr_extract_int8: 3162 case expr_extract_int16: 3163 case expr_extract_int32: 3164 case expr_encode_int8: 3165 case expr_encode_int16: 3166 case expr_encode_int32: 3167 case expr_const_int: 3168 case expr_exists: 3169 case expr_variable_exists: 3170 case expr_known: 3171 case expr_binary_to_ascii: 3172 case expr_reverse: 3173 case expr_filename: 3174 case expr_sname: 3175 case expr_pick_first_value: 3176 case expr_host_decl_name: 3177 case expr_config_option: 3178 case expr_leased_address: 3179 case expr_lease_time: 3180 case expr_null: 3181 case expr_variable_reference: 3182 case expr_ns_add: 3183 case expr_ns_delete: 3184 case expr_ns_exists: 3185 case expr_ns_not_exists: 3186 case expr_dns_transaction: 3187 case expr_arg: 3188 case expr_funcall: 3189 case expr_function: 3190 return context_any; 3191 3192 case expr_equal: 3193 case expr_not_equal: 3194 return context_data; 3195 3196 case expr_and: 3197 return context_boolean; 3198 3199 case expr_or: 3200 return context_boolean; 3201 3202 case expr_add: 3203 case expr_subtract: 3204 case expr_multiply: 3205 case expr_divide: 3206 case expr_remainder: 3207 case expr_binary_and: 3208 case expr_binary_or: 3209 case expr_binary_xor: 3210 case expr_client_state: 3211 return context_numeric; 3212 } 3213 return context_any; 3214} 3215 3216int write_expression (file, expr, col, indent, firstp) 3217 FILE *file; 3218 struct expression *expr; 3219 int col; 3220 int indent; 3221 int firstp; 3222{ 3223 struct expression *e; 3224 const char *s; 3225 char obuf [65]; 3226 int scol; 3227 int width; 3228 3229 /* If this promises to be a fat expression, start a new line. */ 3230 if (!firstp && is_compound_expression (expr)) { 3231 indent_spaces (file, indent); 3232 col = indent; 3233 } 3234 3235 switch (expr -> op) { 3236 case expr_none: 3237 col = token_print_indent (file, col, indent, "", "", "null"); 3238 break; 3239 3240 case expr_check: 3241 col = token_print_indent (file, col, indent, "", "", "check"); 3242 col = token_print_indent_concat (file, col, indent, 3243 " ", "", "\"", 3244 expr -> data.check -> name, 3245 "\"", (char *)0); 3246 break; 3247 3248 case expr_not_equal: 3249 s = "!="; 3250 goto binary; 3251 3252 case expr_equal: 3253 s = "="; 3254 binary: 3255 col = write_expression (file, expr -> data.equal [0], 3256 col, indent, 1); 3257 col = token_print_indent (file, col, indent, " ", " ", s); 3258 col = write_expression (file, expr -> data.equal [1], 3259 col, indent + 2, 0); 3260 break; 3261 3262 case expr_substring: 3263 col = token_print_indent (file, col, indent, "", "", 3264 "substring"); 3265 col = token_print_indent (file, col, indent, " ", "", "("); 3266 scol = col; 3267 col = write_expression (file, expr -> data.substring.expr, 3268 col, scol, 1); 3269 col = token_print_indent (file, col, indent, "", " ", ","); 3270 col = write_expression (file, expr -> data.substring.offset, 3271 col, indent, 0); 3272 col = token_print_indent (file, col, scol, "", " ", ","); 3273 col = write_expression (file, expr -> data.substring.len, 3274 col, scol, 0); 3275 col = token_print_indent (file, col, indent, "", "", ")"); 3276 break; 3277 3278 case expr_suffix: 3279 col = token_print_indent (file, col, indent, "", "", "suffix"); 3280 col = token_print_indent (file, col, indent, " ", "", "("); 3281 scol = col; 3282 col = write_expression (file, expr -> data.suffix.expr, 3283 col, scol, 1); 3284 col = token_print_indent (file, col, scol, "", " ", ","); 3285 col = write_expression (file, expr -> data.suffix.len, 3286 col, scol, 0); 3287 col = token_print_indent (file, col, indent, "", "", ")"); 3288 break; 3289 3290 case expr_concat: 3291 e = expr; 3292 col = token_print_indent (file, col, indent, "", "", 3293 "concat"); 3294 col = token_print_indent (file, col, indent, " ", "", "("); 3295 scol = col; 3296 firstp = 1; 3297 concat_again: 3298 col = write_expression (file, e -> data.concat [0], 3299 col, scol, firstp); 3300 firstp = 0; 3301 if (!e -> data.concat [1]) 3302 goto no_concat_cdr; 3303 col = token_print_indent (file, col, scol, "", " ", ","); 3304 if (e -> data.concat [1] -> op == expr_concat) { 3305 e = e -> data.concat [1]; 3306 goto concat_again; 3307 } 3308 col = write_expression (file, e -> data.concat [1], 3309 col, scol, 0); 3310 no_concat_cdr: 3311 col = token_print_indent (file, col, indent, "", "", ")"); 3312 break; 3313 3314 case expr_host_lookup: 3315 col = token_print_indent (file, col, indent, "", "", 3316 "gethostbyname"); 3317 col = token_print_indent (file, col, indent, " ", "", "("); 3318 col = token_print_indent_concat 3319 (file, col, indent, "", "", 3320 "\"", expr -> data.host_lookup -> hostname, "\"", 3321 (char *)0); 3322 col = token_print_indent (file, col, indent, "", "", ")"); 3323 break; 3324 3325 case expr_add: 3326 s = "+"; 3327 goto binary; 3328 3329 case expr_subtract: 3330 s = "-"; 3331 goto binary; 3332 3333 case expr_multiply: 3334 s = "*"; 3335 goto binary; 3336 3337 case expr_divide: 3338 s = "/"; 3339 goto binary; 3340 3341 case expr_remainder: 3342 s = "%"; 3343 goto binary; 3344 3345 case expr_binary_and: 3346 s = "&"; 3347 goto binary; 3348 3349 case expr_binary_or: 3350 s = "|"; 3351 goto binary; 3352 3353 case expr_binary_xor: 3354 s = "^"; 3355 goto binary; 3356 3357 case expr_and: 3358 s = "and"; 3359 goto binary; 3360 3361 case expr_or: 3362 s = "or"; 3363 goto binary; 3364 3365 case expr_not: 3366 col = token_print_indent (file, col, indent, "", " ", "not"); 3367 col = write_expression (file, 3368 expr -> data.not, col, indent + 2, 1); 3369 break; 3370 3371 case expr_option: 3372 s = "option"; 3373 3374 print_option_name: 3375 col = token_print_indent (file, col, indent, "", "", s); 3376 3377 if (expr -> data.option -> universe != &dhcp_universe) { 3378 col = token_print_indent (file, col, indent, 3379 " ", "", 3380 (expr -> data.option -> 3381 universe -> name)); 3382 col = token_print_indent (file, col, indent, "", "", 3383 "."); 3384 col = token_print_indent (file, col, indent, "", "", 3385 expr -> data.option -> name); 3386 } else { 3387 col = token_print_indent (file, col, indent, " ", "", 3388 expr -> data.option -> name); 3389 } 3390 break; 3391 3392 case expr_hardware: 3393 col = token_print_indent (file, col, indent, "", "", 3394 "hardware"); 3395 break; 3396 3397 case expr_packet: 3398 col = token_print_indent (file, col, indent, "", "", 3399 "packet"); 3400 col = token_print_indent (file, col, indent, " ", "", "("); 3401 scol = col; 3402 col = write_expression (file, expr -> data.packet.offset, 3403 col, indent, 1); 3404 col = token_print_indent (file, col, scol, "", " ", ","); 3405 col = write_expression (file, expr -> data.packet.len, 3406 col, scol, 0); 3407 col = token_print_indent (file, col, indent, "", "", ")"); 3408 break; 3409 3410 case expr_const_data: 3411 col = token_indent_data_string (file, col, indent, "", "", 3412 &expr -> data.const_data); 3413 break; 3414 3415 case expr_extract_int8: 3416 width = 8; 3417 extract_int: 3418 col = token_print_indent (file, col, indent, "", "", 3419 "extract-int"); 3420 col = token_print_indent (file, col, indent, " ", "", "("); 3421 scol = col; 3422 col = write_expression (file, expr -> data.extract_int, 3423 col, indent, 1); 3424 col = token_print_indent (file, col, scol, "", " ", ","); 3425 sprintf (obuf, "%d", width); 3426 col = token_print_indent (file, col, scol, " ", "", obuf); 3427 col = token_print_indent (file, col, indent, "", "", ")"); 3428 break; 3429 3430 case expr_extract_int16: 3431 width = 16; 3432 goto extract_int; 3433 3434 case expr_extract_int32: 3435 width = 32; 3436 goto extract_int; 3437 3438 case expr_encode_int8: 3439 width = 8; 3440 encode_int: 3441 col = token_print_indent (file, col, indent, "", "", 3442 "encode-int"); 3443 col = token_print_indent (file, col, indent, " ", "", "("); 3444 scol = col; 3445 col = write_expression (file, expr -> data.extract_int, 3446 col, indent, 1); 3447 col = token_print_indent (file, col, scol, "", " ", ","); 3448 sprintf (obuf, "%d", width); 3449 col = token_print_indent (file, col, scol, " ", "", obuf); 3450 col = token_print_indent (file, col, indent, "", "", 3451 ")"); 3452 break; 3453 3454 case expr_encode_int16: 3455 width = 16; 3456 goto encode_int; 3457 3458 case expr_encode_int32: 3459 width = 32; 3460 goto encode_int; 3461 3462 case expr_const_int: 3463 sprintf (obuf, "%lu", expr -> data.const_int); 3464 col = token_print_indent (file, col, indent, "", "", obuf); 3465 break; 3466 3467 case expr_exists: 3468 s = "exists"; 3469 goto print_option_name; 3470 3471 case expr_encapsulate: 3472 col = token_print_indent (file, col, indent, "", "", 3473 "encapsulate"); 3474 col = token_indent_data_string (file, col, indent, " ", "", 3475 &expr -> data.encapsulate); 3476 break; 3477 3478 case expr_known: 3479 col = token_print_indent (file, col, indent, "", "", "known"); 3480 break; 3481 3482 case expr_reverse: 3483 col = token_print_indent (file, col, indent, "", "", 3484 "reverse"); 3485 col = token_print_indent (file, col, indent, " ", "", "("); 3486 scol = col; 3487 col = write_expression (file, expr -> data.reverse.width, 3488 col, scol, 1); 3489 col = token_print_indent (file, col, scol, "", " ", ","); 3490 col = write_expression (file, expr -> data.reverse.buffer, 3491 col, scol, 0); 3492 col = token_print_indent (file, col, indent, "", "", 3493 ")"); 3494 break; 3495 3496 case expr_leased_address: 3497 col = token_print_indent (file, col, indent, "", "", 3498 "leased-address"); 3499 break; 3500 3501 case expr_client_state: 3502 col = token_print_indent (file, col, indent, "", "", 3503 "client-state"); 3504 break; 3505 3506 case expr_binary_to_ascii: 3507 col = token_print_indent (file, col, indent, "", "", 3508 "binary-to-ascii"); 3509 col = token_print_indent (file, col, indent, " ", "", 3510 "("); 3511 scol = col; 3512 col = write_expression (file, expr -> data.b2a.base, 3513 col, scol, 1); 3514 col = token_print_indent (file, col, scol, "", " ", 3515 ","); 3516 col = write_expression (file, expr -> data.b2a.width, 3517 col, scol, 0); 3518 col = token_print_indent (file, col, scol, "", " ", 3519 ","); 3520 col = write_expression (file, expr -> data.b2a.seperator, 3521 col, scol, 0); 3522 col = token_print_indent (file, col, scol, "", " ", 3523 ","); 3524 col = write_expression (file, expr -> data.b2a.buffer, 3525 col, scol, 0); 3526 col = token_print_indent (file, col, indent, "", "", 3527 ")"); 3528 break; 3529 3530 case expr_config_option: 3531 s = "config-option"; 3532 goto print_option_name; 3533 3534 case expr_host_decl_name: 3535 col = token_print_indent (file, col, indent, "", "", 3536 "host-decl-name"); 3537 break; 3538 3539 case expr_pick_first_value: 3540 e = expr; 3541 col = token_print_indent (file, col, indent, "", "", 3542 "concat"); 3543 col = token_print_indent (file, col, indent, " ", "", 3544 "("); 3545 scol = col; 3546 firstp = 1; 3547 pick_again: 3548 col = write_expression (file, 3549 e -> data.pick_first_value.car, 3550 col, scol, firstp); 3551 firstp = 0; 3552 /* We're being very lisp-like right now - instead of 3553 representing this expression as (first middle . last) we're 3554 representing it as (first middle last), which means that the 3555 tail cdr is always nil. Apologies to non-wisp-lizards - may 3556 this obscure way of describing the problem motivate you to 3557 learn more about the one true computing language. */ 3558 if (!e -> data.pick_first_value.cdr) 3559 goto no_pick_cdr; 3560 col = token_print_indent (file, col, scol, "", " ", 3561 ","); 3562 if (e -> data.pick_first_value.cdr -> op == 3563 expr_pick_first_value) { 3564 e = e -> data.pick_first_value.cdr; 3565 goto pick_again; 3566 } 3567 col = write_expression (file, 3568 e -> data.pick_first_value.cdr, 3569 col, scol, 0); 3570 no_pick_cdr: 3571 col = token_print_indent (file, col, indent, "", "", 3572 ")"); 3573 break; 3574 3575 case expr_lease_time: 3576 col = token_print_indent (file, col, indent, "", "", 3577 "lease-time"); 3578 break; 3579 3580 case expr_dns_transaction: 3581 col = token_print_indent (file, col, indent, "", "", 3582 "ns-update"); 3583 col = token_print_indent (file, col, indent, " ", "", 3584 "("); 3585 scol = 0; 3586 for (e = expr; 3587 e && e -> op == expr_dns_transaction; 3588 e = e -> data.dns_transaction.cdr) { 3589 if (!scol) { 3590 scol = col; 3591 firstp = 1; 3592 } else 3593 firstp = 0; 3594 col = write_expression (file, 3595 e -> data.dns_transaction.car, 3596 col, scol, firstp); 3597 if (e -> data.dns_transaction.cdr) 3598 col = token_print_indent (file, col, scol, 3599 "", " ", ","); 3600 } 3601 if (e) 3602 col = write_expression (file, e, col, scol, 0); 3603 col = token_print_indent (file, col, indent, "", "", ")"); 3604 break; 3605 3606 case expr_ns_add: 3607 col = token_print_indent (file, col, indent, "", "", 3608 "update"); 3609 col = token_print_indent (file, col, indent, " ", "", 3610 "("); 3611 scol = col; 3612 sprintf (obuf, "%d", expr -> data.ns_add.rrclass); 3613 col = token_print_indent (file, col, scol, "", "", obuf); 3614 col = token_print_indent (file, col, scol, "", " ", 3615 ","); 3616 sprintf (obuf, "%d", expr -> data.ns_add.rrtype); 3617 col = token_print_indent (file, col, scol, "", "", obuf); 3618 col = token_print_indent (file, col, scol, "", " ", 3619 ","); 3620 col = write_expression (file, expr -> data.ns_add.rrname, 3621 col, scol, 0); 3622 col = token_print_indent (file, col, scol, "", " ", 3623 ","); 3624 col = write_expression (file, expr -> data.ns_add.rrdata, 3625 col, scol, 0); 3626 col = token_print_indent (file, col, scol, "", " ", 3627 ","); 3628 col = write_expression (file, expr -> data.ns_add.ttl, 3629 col, scol, 0); 3630 col = token_print_indent (file, col, indent, "", "", 3631 ")"); 3632 break; 3633 3634 case expr_ns_delete: 3635 col = token_print_indent (file, col, indent, "", "", 3636 "delete"); 3637 col = token_print_indent (file, col, indent, " ", "", 3638 "("); 3639 finish_ns_small: 3640 scol = col; 3641 sprintf (obuf, "%d", expr -> data.ns_add.rrclass); 3642 col = token_print_indent (file, col, scol, "", "", obuf); 3643 col = token_print_indent (file, col, scol, "", " ", 3644 ","); 3645 sprintf (obuf, "%d", expr -> data.ns_add.rrtype); 3646 col = token_print_indent (file, col, scol, "", "", obuf); 3647 col = token_print_indent (file, col, scol, "", " ", 3648 ","); 3649 col = write_expression (file, expr -> data.ns_add.rrname, 3650 col, scol, 0); 3651 col = token_print_indent (file, col, scol, "", " ", 3652 ","); 3653 col = write_expression (file, expr -> data.ns_add.rrdata, 3654 col, scol, 0); 3655 col = token_print_indent (file, col, indent, "", "", 3656 ")"); 3657 break; 3658 3659 case expr_ns_exists: 3660 col = token_print_indent (file, col, indent, "", "", 3661 "exists"); 3662 col = token_print_indent (file, col, indent, " ", "", 3663 "("); 3664 goto finish_ns_small; 3665 3666 case expr_ns_not_exists: 3667 col = token_print_indent (file, col, indent, "", "", 3668 "not exists"); 3669 col = token_print_indent (file, col, indent, " ", "", 3670 "("); 3671 goto finish_ns_small; 3672 3673 case expr_static: 3674 col = token_print_indent (file, col, indent, "", "", 3675 "static"); 3676 break; 3677 3678 case expr_null: 3679 col = token_print_indent (file, col, indent, "", "", "null"); 3680 break; 3681 3682 case expr_variable_reference: 3683 col = token_print_indent (file, indent, indent, "", "", 3684 expr -> data.variable); 3685 break; 3686 3687 case expr_variable_exists: 3688 col = token_print_indent (file, indent, indent, "", "", 3689 "defined"); 3690 col = token_print_indent (file, col, indent, " ", "", "("); 3691 col = token_print_indent (file, col, indent, "", "", 3692 expr -> data.variable); 3693 col = token_print_indent (file, col, indent, "", "", ")"); 3694 break; 3695 3696 default: 3697 log_fatal ("invalid expression type in print_expression: %d", 3698 expr -> op); 3699 } 3700 return col; 3701} 3702 3703struct binding *find_binding (struct binding_scope *scope, const char *name) 3704{ 3705 struct binding *bp; 3706 struct binding_scope *s; 3707 3708 for (s = scope; s; s = s -> outer) { 3709 for (bp = s -> bindings; bp; bp = bp -> next) { 3710 if (!strcasecmp (name, bp -> name)) { 3711 return bp; 3712 } 3713 } 3714 } 3715 return (struct binding *)0; 3716} 3717 3718int free_bindings (struct binding_scope *scope, const char *file, int line) 3719{ 3720 struct binding *bp, *next; 3721 3722 for (bp = scope -> bindings; bp; bp = next) { 3723 next = bp -> next; 3724 if (bp -> name) 3725 dfree (bp -> name, file, line); 3726 if (bp -> value) 3727 binding_value_dereference (&bp -> value, file, line); 3728 dfree (bp, file, line); 3729 } 3730 scope -> bindings = (struct binding *)0; 3731 return 1; 3732} 3733 3734int binding_scope_dereference (ptr, file, line) 3735 struct binding_scope **ptr; 3736 const char *file; 3737 int line; 3738{ 3739 struct binding_scope *binding_scope; 3740 3741 if (!ptr || !*ptr) { 3742 log_error ("%s(%d): null pointer", file, line); 3743#if defined (POINTER_DEBUG) 3744 abort (); 3745#else 3746 return 0; 3747#endif 3748 } 3749 3750 binding_scope = *ptr; 3751 *ptr = (struct binding_scope *)0; 3752 --binding_scope -> refcnt; 3753 rc_register (file, line, ptr, 3754 binding_scope, binding_scope -> refcnt, 1, RC_MISC); 3755 if (binding_scope -> refcnt > 0) 3756 return 1; 3757 3758 if (binding_scope -> refcnt < 0) { 3759 log_error ("%s(%d): negative refcnt!", file, line); 3760#if defined (DEBUG_RC_HISTORY) 3761 dump_rc_history (binding_scope); 3762#endif 3763#if defined (POINTER_DEBUG) 3764 abort (); 3765#else 3766 return 0; 3767#endif 3768 } 3769 3770 free_bindings (binding_scope, file, line); 3771 if (binding_scope -> outer) 3772 binding_scope_dereference (&binding_scope -> outer, MDL); 3773 dfree (binding_scope, file, line); 3774 return 1; 3775} 3776 3777int fundef_dereference (ptr, file, line) 3778 struct fundef **ptr; 3779 const char *file; 3780 int line; 3781{ 3782 struct fundef *bp = *ptr; 3783 struct string_list *sp, *next; 3784 3785 if (!ptr) { 3786 log_error ("%s(%d): null pointer", file, line); 3787#if defined (POINTER_DEBUG) 3788 abort (); 3789#else 3790 return 0; 3791#endif 3792 } 3793 3794 if (!bp) { 3795 log_error ("%s(%d): null pointer", file, line); 3796#if defined (POINTER_DEBUG) 3797 abort (); 3798#else 3799 return 0; 3800#endif 3801 } 3802 3803 bp -> refcnt--; 3804 rc_register (file, line, ptr, bp, bp -> refcnt, 1, RC_MISC); 3805 if (bp -> refcnt < 0) { 3806 log_error ("%s(%d): negative refcnt!", file, line); 3807#if defined (DEBUG_RC_HISTORY) 3808 dump_rc_history (bp); 3809#endif 3810#if defined (POINTER_DEBUG) 3811 abort (); 3812#else 3813 return 0; 3814#endif 3815 } 3816 if (!bp -> refcnt) { 3817 for (sp = bp -> args; sp; sp = next) { 3818 next = sp -> next; 3819 dfree (sp, file, line); 3820 } 3821 if (bp -> statements) 3822 executable_statement_dereference (&bp -> statements, 3823 file, line); 3824 dfree (bp, file, line); 3825 } 3826 *ptr = (struct fundef *)0; 3827 return 1; 3828} 3829 3830#if defined (NOTYET) /* Post 3.0 final. */ 3831int data_subexpression_length (int *rv, 3832 struct expression *expr) 3833{ 3834 int crhs, clhs, llhs, lrhs; 3835 switch (expr -> op) { 3836 case expr_substring: 3837 if (expr -> data.substring.len && 3838 expr -> data.substring.len -> op == expr_const_int) { 3839 (*rv = 3840 (int)expr -> data.substring.len -> data.const_int); 3841 return 1; 3842 } 3843 return 0; 3844 3845 case expr_packet: 3846 case expr_suffix: 3847 if (expr -> data.suffix.len && 3848 expr -> data.suffix.len -> op == expr_const_int) { 3849 (*rv = 3850 (int)expr -> data.suffix.len -> data.const_int); 3851 return 1; 3852 } 3853 return 0; 3854 3855 case expr_concat: 3856 clhs = data_subexpression_length (&llhs, 3857 expr -> data.concat [0]); 3858 crhs = data_subexpression_length (&lrhs, 3859 expr -> data.concat [1]); 3860 if (crhs == 0 || clhs == 0) 3861 return 0; 3862 *rv = llhs + lrhs; 3863 return 1; 3864 break; 3865 3866 case expr_hardware: 3867 return 0; 3868 3869 case expr_const_data: 3870 *rv = expr -> data.const_data.len; 3871 return 2; 3872 3873 case expr_reverse: 3874 return data_subexpression_length (rv, 3875 expr -> data.reverse.buffer); 3876 3877 case expr_leased_address: 3878 case expr_lease_time: 3879 *rv = 4; 3880 return 2; 3881 3882 case expr_pick_first_value: 3883 clhs = data_subexpression_length (&llhs, 3884 expr -> data.concat [0]); 3885 crhs = data_subexpression_length (&lrhs, 3886 expr -> data.concat [1]); 3887 if (crhs == 0 || clhs == 0) 3888 return 0; 3889 if (llhs > lrhs) 3890 *rv = llhs; 3891 else 3892 *rv = lrhs; 3893 return 1; 3894 3895 case expr_binary_to_ascii: 3896 case expr_config_option: 3897 case expr_host_decl_name: 3898 case expr_encapsulate: 3899 case expr_filename: 3900 case expr_sname: 3901 case expr_host_lookup: 3902 case expr_option: 3903 case expr_none: 3904 case expr_match: 3905 case expr_check: 3906 case expr_equal: 3907 case expr_and: 3908 case expr_or: 3909 case expr_not: 3910 case expr_extract_int8: 3911 case expr_extract_int16: 3912 case expr_extract_int32: 3913 case expr_encode_int8: 3914 case expr_encode_int16: 3915 case expr_encode_int32: 3916 case expr_const_int: 3917 case expr_exists: 3918 case expr_known: 3919 case expr_dns_transaction: 3920 case expr_static: 3921 case expr_ns_add: 3922 case expr_ns_delete: 3923 case expr_ns_exists: 3924 case expr_ns_not_exists: 3925 case expr_not_equal: 3926 case expr_null: 3927 case expr_variable_exists: 3928 case expr_variable_reference: 3929 case expr_arg: 3930 case expr_funcall: 3931 case expr_function: 3932 case expr_add: 3933 case expr_subtract: 3934 case expr_multiply: 3935 case expr_divide: 3936 case expr_remainder: 3937 case expr_binary_and: 3938 case expr_binary_or: 3939 case expr_binary_xor: 3940 case expr_client_state: 3941 return 0; 3942 } 3943 return 0; 3944} 3945 3946int expr_valid_for_context (struct expression *expr, 3947 enum expression_context context) 3948{ 3949 /* We don't know at parse time what type of value a function may 3950 return, so we can't flag an error on it. */ 3951 if (expr -> op == expr_funcall || 3952 expr -> op == expr_variable_reference) 3953 return 1; 3954 3955 switch (context) { 3956 case context_any: 3957 return 1; 3958 3959 case context_boolean: 3960 if (is_boolean_expression (expr)) 3961 return 1; 3962 return 0; 3963 3964 case context_data: 3965 if (is_data_expression (expr)) 3966 return 1; 3967 return 0; 3968 3969 case context_numeric: 3970 if (is_numeric_expression (expr)) 3971 return 1; 3972 return 0; 3973 3974 case context_dns: 3975 if (is_dns_expression (expr)) { 3976 return 1; 3977 } 3978 return 0; 3979 3980 case context_data_or_numeric: 3981 if (is_numeric_expression (expr) || 3982 is_data_expression (expr)) { 3983 return 1; 3984 } 3985 return 0; 3986 3987 case context_function: 3988 if (expr -> op == expr_function) 3989 return 1; 3990 return 0; 3991 } 3992 return 0; 3993} 3994#endif /* NOTYET */ 3995 3996struct binding *create_binding (struct binding_scope **scope, const char *name) 3997{ 3998 struct binding *binding; 3999 4000 if (!*scope) { 4001 if (!binding_scope_allocate (scope, MDL)) 4002 return (struct binding *)0; 4003 } 4004 4005 binding = find_binding (*scope, name); 4006 if (!binding) { 4007 binding = dmalloc (sizeof *binding, MDL); 4008 if (!binding) 4009 return (struct binding *)0; 4010 4011 memset (binding, 0, sizeof *binding); 4012 binding -> name = dmalloc (strlen (name) + 1, MDL); 4013 if (!binding -> name) { 4014 dfree (binding, MDL); 4015 return (struct binding *)0; 4016 } 4017 strcpy (binding -> name, name); 4018 4019 binding -> next = (*scope) -> bindings; 4020 (*scope) -> bindings = binding; 4021 } 4022 4023 return binding; 4024} 4025 4026 4027int bind_ds_value (struct binding_scope **scope, 4028 const char *name, 4029 struct data_string *value) 4030{ 4031 struct binding *binding; 4032 4033 binding = create_binding (scope, name); 4034 if (!binding) 4035 return 0; 4036 4037 if (binding -> value) 4038 binding_value_dereference (&binding -> value, MDL); 4039 4040 if (!binding_value_allocate (&binding -> value, MDL)) 4041 return 0; 4042 4043 data_string_copy (&binding -> value -> value.data, value, MDL); 4044 binding -> value -> type = binding_data; 4045 4046 return 1; 4047} 4048 4049 4050int find_bound_string (struct data_string *value, 4051 struct binding_scope *scope, 4052 const char *name) 4053{ 4054 struct binding *binding; 4055 4056 binding = find_binding (scope, name); 4057 if (!binding || 4058 !binding -> value || 4059 binding -> value -> type != binding_data) 4060 return 0; 4061 4062 if (binding -> value -> value.data.terminated) { 4063 data_string_copy (value, &binding -> value -> value.data, MDL); 4064 } else { 4065 buffer_allocate (&value -> buffer, 4066 binding -> value -> value.data.len, 4067 MDL); 4068 if (!value -> buffer) 4069 return 0; 4070 4071 memcpy (value -> buffer -> data, 4072 binding -> value -> value.data.data, 4073 binding -> value -> value.data.len); 4074 value -> data = value -> buffer -> data; 4075 value -> len = binding -> value -> value.data.len; 4076 } 4077 4078 return 1; 4079} 4080 4081int unset (struct binding_scope *scope, const char *name) 4082{ 4083 struct binding *binding; 4084 4085 binding = find_binding (scope, name); 4086 if (binding) { 4087 if (binding -> value) 4088 binding_value_dereference 4089 (&binding -> value, MDL); 4090 return 1; 4091 } 4092 return 0; 4093} 4094 4095/* vim: set tabstop=8: */ 4096