tree.c
来自「open source dhcp server client etc...」· C语言 代码 · 共 2,386 行 · 第 1/5 页
C
2,386 行
/* tree.c Routines for manipulating parse trees... *//* * Copyright (c) 1995-2001 Internet Software Consortium. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of The Internet Software Consortium nor the names * of its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * This software has been written for the Internet Software Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. * To learn more about the Internet Software Consortium, see * ``http://www.isc.org/''. To learn more about Vixie Enterprises, * see ``http://www.vix.com''. To learn more about Nominum, Inc., see * ``http://www.nominum.com''. */#ifndef lintstatic char copyright[] ="$Id: tree.c,v 1.101.2.5 2001/10/04 20:38:22 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n";#endif /* not lint */#include "dhcpd.h"#include <omapip/omapip_p.h>struct binding_scope *global_scope;static int do_host_lookup PROTO ((struct data_string *, struct dns_host_entry *));#ifdef NSUPDATEstruct __res_state resolver_state;int resolver_inited = 0;#endifpair cons (car, cdr) caddr_t car; pair cdr;{ pair foo = (pair)dmalloc (sizeof *foo, MDL); if (!foo) log_fatal ("no memory for cons."); foo -> car = car; foo -> cdr = cdr; return foo;}int make_const_option_cache (oc, buffer, data, len, option, file, line) struct option_cache **oc; struct buffer **buffer; u_int8_t *data; unsigned len; struct option *option; const char *file; int line;{ struct buffer *bp; if (buffer) { bp = *buffer; *buffer = 0; } else { bp = (struct buffer *)0; if (!buffer_allocate (&bp, len, file, line)) { log_error ("%s(%d): can't allocate buffer.", file, line); return 0; } } if (!option_cache_allocate (oc, file, line)) { log_error ("%s(%d): can't allocate option cache.", file, line); buffer_dereference (&bp, file, line); return 0; } (*oc) -> data.len = len; (*oc) -> data.buffer = bp; (*oc) -> data.data = &bp -> data [0]; (*oc) -> data.terminated = 0; if (data) memcpy (&bp -> data [0], data, len); (*oc) -> option = option; return 1;}int make_host_lookup (expr, name) struct expression **expr; const char *name;{ if (!expression_allocate (expr, MDL)) { log_error ("No memory for host lookup tree node."); return 0; } (*expr) -> op = expr_host_lookup; if (!enter_dns_host (&((*expr) -> data.host_lookup), name)) { expression_dereference (expr, MDL); return 0; } return 1;}int enter_dns_host (dh, name) struct dns_host_entry **dh; const char *name;{ /* XXX This should really keep a hash table of hostnames XXX and just add a new reference to a hostname that XXX already exists, if possible, rather than creating XXX a new structure. */ if (!dns_host_entry_allocate (dh, name, MDL)) { log_error ("Can't allocate space for new host."); return 0; } return 1;}int make_const_data (struct expression **expr, const unsigned char *data, unsigned len, int terminated, int allocate, const char *file, int line){ struct expression *nt; if (!expression_allocate (expr, file, line)) { log_error ("No memory for make_const_data tree node."); return 0; } nt = *expr; if (len) { if (allocate) { if (!buffer_allocate (&nt -> data.const_data.buffer, len + terminated, file, line)) { log_error ("Can't allocate const_data buffer"); expression_dereference (expr, file, line); return 0; } nt -> data.const_data.data = &nt -> data.const_data.buffer -> data [0]; memcpy (nt -> data.const_data.buffer -> data, data, len + terminated); } else nt -> data.const_data.data = data; nt -> data.const_data.terminated = terminated; } else nt -> data.const_data.data = 0; nt -> op = expr_const_data; nt -> data.const_data.len = len; return 1;}int make_const_int (expr, val) struct expression **expr; unsigned long val;{ if (!expression_allocate (expr, MDL)) { log_error ("No memory for make_const_int tree node."); return 0; } (*expr) -> op = expr_const_int; (*expr) -> data.const_int = val; return 1;}int make_concat (expr, left, right) struct expression **expr; struct expression *left, *right;{ /* If we're concatenating a null tree to a non-null tree, just return the non-null tree; if both trees are null, return a null tree. */ if (!left) { if (!right) return 0; expression_reference (expr, right, MDL); return 1; } if (!right) { expression_reference (expr, left, MDL); return 1; } /* Otherwise, allocate a new node to concatenate the two. */ if (!expression_allocate (expr, MDL)) { log_error ("No memory for concatenation expression node."); return 0; } (*expr) -> op = expr_concat; expression_reference (&(*expr) -> data.concat [0], left, MDL); expression_reference (&(*expr) -> data.concat [1], right, MDL); return 1;}int make_encapsulation (expr, name) struct expression **expr; struct data_string *name;{ /* Allocate a new node to store the encapsulation. */ if (!expression_allocate (expr, MDL)) { log_error ("No memory for encapsulation expression node."); return 0; } (*expr) -> op = expr_encapsulate; data_string_copy (&(*expr) -> data.encapsulate, name, MDL); return 1;}int make_substring (new, expr, offset, length) struct expression **new; struct expression *expr; struct expression *offset; struct expression *length;{ /* Allocate an expression node to compute the substring. */ if (!expression_allocate (new, MDL)) { log_error ("no memory for substring expression."); return 0; } (*new) -> op = expr_substring; expression_reference (&(*new) -> data.substring.expr, expr, MDL); expression_reference (&(*new) -> data.substring.offset, offset, MDL); expression_reference (&(*new) -> data.substring.len, length, MDL); return 1;}int make_limit (new, expr, limit) struct expression **new; struct expression *expr; int limit;{ struct expression *rv; /* Allocate a node to enforce a limit on evaluation. */ if (!expression_allocate (new, MDL)) log_error ("no memory for limit expression"); (*new) -> op = expr_substring; expression_reference (&(*new) -> data.substring.expr, expr, MDL); /* Offset is a constant 0. */ if (!expression_allocate (&(*new) -> data.substring.offset, MDL)) { log_error ("no memory for limit offset expression"); expression_dereference (new, MDL); return 0; } (*new) -> data.substring.offset -> op = expr_const_int; (*new) -> data.substring.offset -> data.const_int = 0; /* Length is a constant: the specified limit. */ if (!expression_allocate (&(*new) -> data.substring.len, MDL)) { log_error ("no memory for limit length expression"); expression_dereference (new, MDL); return 0; } (*new) -> data.substring.len -> op = expr_const_int; (*new) -> data.substring.len -> data.const_int = limit; return 1;}int option_cache (struct option_cache **oc, struct data_string *dp, struct expression *expr, struct option *option, const char *file, int line){ if (!option_cache_allocate (oc, file, line)) return 0; if (dp) data_string_copy (&(*oc) -> data, dp, file, line); if (expr) expression_reference (&(*oc) -> expression, expr, file, line); (*oc) -> option = option; return 1;}int make_let (result, name) struct executable_statement **result; const char *name;{ if (!(executable_statement_allocate (result, MDL))) return 0; (*result) -> op = let_statement; (*result) -> data.let.name = dmalloc (strlen (name) + 1, MDL); if (!(*result) -> data.let.name) { executable_statement_dereference (result, MDL); return 0; } strcpy ((*result) -> data.let.name, name); return 1;} static int do_host_lookup (result, dns) struct data_string *result; struct dns_host_entry *dns;{ struct hostent *h; unsigned i, count; unsigned new_len;#ifdef DEBUG_EVAL log_debug ("time: now = %d dns = %d diff = %d", cur_time, dns -> timeout, cur_time - dns -> timeout);#endif /* If the record hasn't timed out, just copy the data and return. */ if (cur_time <= dns -> timeout) {#ifdef DEBUG_EVAL log_debug ("easy copy: %d %s", dns -> data.len, (dns -> data.len > 4 ? inet_ntoa (*(struct in_addr *)(dns -> data.data)) : 0));#endif data_string_copy (result, &dns -> data, MDL); return 1; }#ifdef DEBUG_EVAL log_debug ("Looking up %s", dns -> hostname);#endif /* Otherwise, look it up... */ h = gethostbyname (dns -> hostname); if (!h) {#ifndef NO_H_ERRNO switch (h_errno) { case HOST_NOT_FOUND:#endif log_error ("%s: host unknown.", dns -> hostname);#ifndef NO_H_ERRNO break; case TRY_AGAIN: log_error ("%s: temporary name server failure", dns -> hostname); break; case NO_RECOVERY: log_error ("%s: name server failed", dns -> hostname); break; case NO_DATA: log_error ("%s: no A record associated with address", dns -> hostname); }#endif /* !NO_H_ERRNO */ /* Okay to try again after a minute. */ dns -> timeout = cur_time + 60; data_string_forget (&dns -> data, MDL); return 0; }#ifdef DEBUG_EVAL log_debug ("Lookup succeeded; first address is %s", inet_ntoa (h -> h_addr_list [0]));#endif /* Count the number of addresses we got... */ for (count = 0; h -> h_addr_list [count]; count++) ; /* Dereference the old data, if any. */ data_string_forget (&dns -> data, MDL); /* Do we need to allocate more memory? */ new_len = count * h -> h_length; if (!buffer_allocate (&dns -> data.buffer, new_len, MDL)) { log_error ("No memory for %s.", dns -> hostname); return 0; } dns -> data.data = &dns -> data.buffer -> data [0]; dns -> data.len = new_len; dns -> data.terminated = 0; /* Addresses are conveniently stored one to the buffer, so we have to copy them out one at a time... :'( */ for (i = 0; i < count; i++) { memcpy (&dns -> data.buffer -> data [h -> h_length * i], h -> h_addr_list [i], (unsigned)(h -> h_length)); }#ifdef DEBUG_EVAL log_debug ("dns -> data: %x h -> h_addr_list [0]: %x", *(int *)(dns -> buffer), h -> h_addr_list [0]);#endif /* XXX Set the timeout for an hour from now. XXX This should really use the time on the DNS reply. */ dns -> timeout = cur_time + 3600;#ifdef DEBUG_EVAL log_debug ("hard copy: %d %s", dns -> data.len, (dns -> data.len > 4 ? inet_ntoa (*(struct in_addr *)(dns -> data.data)) : 0));#endif data_string_copy (result, &dns -> data, MDL); return 1;}int evaluate_expression (result, packet, lease, client_state, in_options, cfg_options, scope, expr, file, line) struct binding_value **result; struct packet *packet; struct lease *lease; struct client_state *client_state; struct option_state *in_options; struct option_state *cfg_options; struct binding_scope **scope; struct expression *expr; const char *file; int line;{ struct binding_value *bv; int status; struct binding *binding; bv = (struct binding_value *)0; if (expr -> op == expr_variable_reference) { if (!scope || !*scope) return 0; binding = find_binding (*scope, expr -> data.variable); if (binding && binding -> value) { if (result) binding_value_reference (result, binding -> value, file, line); return 1; } else return 0; } else if (expr -> op == expr_funcall) { struct string_list *s; struct expression *arg; struct binding_scope *ns; struct binding *nb; if (!scope || !*scope) { log_error ("%s: no such function.", expr -> data.funcall.name); return 0; } binding = find_binding (*scope, expr -> data.funcall.name); if (!binding || !binding -> value) { log_error ("%s: no such function.", expr -> data.funcall.name); return 0; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?