diff options
Diffstat (limited to 'common/tree.c')
-rw-r--r-- | common/tree.c | 394 |
1 files changed, 0 insertions, 394 deletions
diff --git a/common/tree.c b/common/tree.c deleted file mode 100644 index 3c667726..00000000 --- a/common/tree.c +++ /dev/null @@ -1,394 +0,0 @@ -/* tree.c - - Routines for manipulating parse trees... */ - -/* - * Copyright (c) 1995 The 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 <mellon@fugue.com> in cooperation with Vixie - * Enterprises. To learn more about the Internet Software Consortium, - * see ``http://www.vix.com/isc''. To learn more about Vixie - * Enterprises, see ``http://www.vix.com''. - */ - -#ifndef lint -static char copyright[] = -"@(#) Copyright (c) 1995 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" - -static TIME tree_evaluate_recurse PROTO ((int *, unsigned char **, int *, - struct tree *)); -static TIME do_host_lookup PROTO ((int *, unsigned char **, int *, - struct dns_host_entry *)); -static void do_data_copy PROTO ((int *, unsigned char **, int *, - unsigned char *, int)); - -pair cons (car, cdr) - caddr_t car; - pair cdr; -{ - pair foo = (pair)dmalloc (sizeof *foo, "cons"); - if (!foo) - error ("no memory for cons."); - foo -> car = car; - foo -> cdr = cdr; - return foo; -} - -struct tree_cache *tree_cache (tree) - struct tree *tree; -{ - struct tree_cache *tc; - - tc = new_tree_cache ("tree_cache"); - if (!tc) - return 0; - tc -> value = (char *)0; - tc -> len = tc -> buf_size = 0; - tc -> timeout = 0; - tc -> tree = tree; - return tc; -} - -struct tree *tree_host_lookup (name) - char *name; -{ - struct tree *nt; - nt = new_tree ("tree_host_lookup"); - if (!nt) - error ("No memory for host lookup tree node."); - nt -> op = TREE_HOST_LOOKUP; - nt -> data.host_lookup.host = enter_dns_host (name); - return nt; -} - -struct dns_host_entry *enter_dns_host (name) - char *name; -{ - struct dns_host_entry *dh; - - if (!(dh = (struct dns_host_entry *)dmalloc - (sizeof (struct dns_host_entry), "enter_dns_host")) - || !(dh -> hostname = dmalloc (strlen (name) + 1, - "enter_dns_host"))) - error ("Can't allocate space for new host."); - strcpy (dh -> hostname, name); - dh -> data = (unsigned char *)0; - dh -> data_len = 0; - dh -> buf_len = 0; - dh -> timeout = 0; - return dh; -} - -struct tree *tree_const (data, len) - unsigned char *data; - int len; -{ - struct tree *nt; - if (!(nt = new_tree ("tree_const")) - || !(nt -> data.const_val.data = - (unsigned char *)dmalloc (len, "tree_const"))) - error ("No memory for constant data tree node."); - nt -> op = TREE_CONST; - memcpy (nt -> data.const_val.data, data, len); - nt -> data.const_val.len = len; - return nt; -} - -struct tree *tree_concat (left, right) - struct tree *left, *right; -{ - struct tree *nt; - - /* 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) - return right; - if (!right) - return left; - - /* If both trees are constant, combine them. */ - if (left -> op == TREE_CONST && right -> op == TREE_CONST) { - unsigned char *buf = dmalloc (left -> data.const_val.len - + right -> data.const_val.len, - "tree_concat"); - if (!buf) - error ("No memory to concatenate constants."); - memcpy (buf, left -> data.const_val.data, - left -> data.const_val.len); - memcpy (buf + left -> data.const_val.len, - right -> data.const_val.data, - right -> data.const_val.len); - dfree (left -> data.const_val.data, "tree_concat"); - dfree (right -> data.const_val.data, "tree_concat"); - left -> data.const_val.data = buf; - left -> data.const_val.len += right -> data.const_val.len; - free_tree (right, "tree_concat"); - return left; - } - - /* Otherwise, allocate a new node to concatenate the two. */ - if (!(nt = new_tree ("tree_concat"))) - error ("No memory for data tree concatenation node."); - nt -> op = TREE_CONCAT; - nt -> data.concat.left = left; - nt -> data.concat.right = right; - return nt; -} - -struct tree *tree_limit (tree, limit) - struct tree *tree; - int limit; -{ - struct tree *rv; - - /* If the tree we're limiting is constant, limit it now. */ - if (tree -> op == TREE_CONST) { - if (tree -> data.const_val.len > limit) - tree -> data.const_val.len = limit; - return tree; - } - - /* Otherwise, put in a node which enforces the limit on evaluation. */ - rv = new_tree ("tree_limit"); - if (!rv) - return (struct tree *)0; - rv -> op = TREE_LIMIT; - rv -> data.limit.tree = tree; - rv -> data.limit.limit = limit; - return rv; -} - -int tree_evaluate (tree_cache) - struct tree_cache *tree_cache; -{ - unsigned char *bp = tree_cache -> value; - int bc = tree_cache -> buf_size; - int bufix = 0; - - /* If there's no tree associated with this cache, it evaluates - to a constant and that was detected at startup. */ - if (!tree_cache -> tree) - return 1; - - /* Try to evaluate the tree without allocating more memory... */ - tree_cache -> timeout = tree_evaluate_recurse (&bufix, &bp, &bc, - tree_cache -> tree); - - /* No additional allocation needed? */ - if (bufix <= bc) { - tree_cache -> len = bufix; - return 1; - } - - /* If we can't allocate more memory, return with what we - have (maybe nothing). */ - if (!(bp = (unsigned char *)dmalloc (bufix, "tree_evaluate"))) - return 0; - - /* Record the change in conditions... */ - bc = bufix; - bufix = 0; - - /* Note that the size of the result shouldn't change on the - second call to tree_evaluate_recurse, since we haven't - changed the ``current'' time. */ - tree_evaluate_recurse (&bufix, &bp, &bc, tree_cache -> tree); - - /* Free the old buffer if needed, then store the new buffer - location and size and return. */ - if (tree_cache -> value) - dfree (tree_cache -> value, "tree_evaluate"); - tree_cache -> value = bp; - tree_cache -> len = bufix; - tree_cache -> buf_size = bc; - return 1; -} - -static TIME tree_evaluate_recurse (bufix, bufp, bufcount, tree) - int *bufix; - unsigned char **bufp; - int *bufcount; - struct tree *tree; -{ - int limit; - TIME t1, t2; - - switch (tree -> op) { - case TREE_CONCAT: - t1 = tree_evaluate_recurse (bufix, bufp, bufcount, - tree -> data.concat.left); - t2 = tree_evaluate_recurse (bufix, bufp, bufcount, - tree -> data.concat.right); - if (t1 > t2) - return t2; - return t1; - - case TREE_HOST_LOOKUP: - return do_host_lookup (bufix, bufp, bufcount, - tree -> data.host_lookup.host); - - case TREE_CONST: - do_data_copy (bufix, bufp, bufcount, - tree -> data.const_val.data, - tree -> data.const_val.len); - t1 = MAX_TIME; - return t1; - - case TREE_LIMIT: - limit = *bufix + tree -> data.limit.limit; - t1 = tree_evaluate_recurse (bufix, bufp, bufcount, - tree -> data.limit.tree); - *bufix = limit; - return t1; - - default: - warn ("Bad node id in tree: %d."); - t1 = MAX_TIME; - return t1; - } -} - -static TIME do_host_lookup (bufix, bufp, bufcount, dns) - int *bufix; - unsigned char **bufp; - int *bufcount; - struct dns_host_entry *dns; -{ - struct hostent *h; - int i; - int new_len; - - debug ("time: now = %d dns = %d %d diff = %d", - cur_time, dns -> timeout, cur_time - dns -> timeout); - - /* If the record hasn't timed out, just copy the data and return. */ - if (cur_time <= dns -> timeout) { - debug ("easy copy: %x %d %x", - dns -> data, dns -> data_len, - dns -> data ? *(int *)(dns -> data) : 0); - do_data_copy (bufix, bufp, bufcount, - dns -> data, dns -> data_len); - return dns -> timeout; - } - debug ("Looking up %s", dns -> hostname); - - /* Otherwise, look it up... */ - h = gethostbyname (dns -> hostname); - if (!h) { - switch (h_errno) { - case HOST_NOT_FOUND: - warn ("%s: host unknown.", dns -> hostname); - break; - case TRY_AGAIN: - warn ("%s: temporary name server failure", - dns -> hostname); - break; - case NO_RECOVERY: - warn ("%s: name server failed", dns -> hostname); - break; - case NO_DATA: - warn ("%s: no A record associated with address", - dns -> hostname); - } - - /* Okay to try again after a minute. */ - return cur_time + 60; - } - - debug ("Lookup succeeded; first address is %x", - h -> h_addr_list [0]); - - /* Count the number of addresses we got... */ - for (i = 0; h -> h_addr_list [i]; i++) - ; - - /* Do we need to allocate more memory? */ - new_len = i * h -> h_length; - if (dns -> buf_len < i) { - unsigned char *buf = - (unsigned char *)dmalloc (new_len, "do_host_lookup"); - /* If we didn't get more memory, use what we have. */ - if (!buf) { - new_len = dns -> buf_len; - if (!dns -> buf_len) { - dns -> timeout = cur_time + 60; - return dns -> timeout; - } - } else { - dfree (dns -> data, "do_host_lookup"); - dns -> data = buf; - dns -> buf_len = new_len; - } - } - - /* Addresses are conveniently stored one to the buffer, so we - have to copy them out one at a time... :'( */ - for (i = 0; i < new_len / h -> h_length; i++) { - memcpy (dns -> data + h -> h_length * i, - h -> h_addr_list [i], h -> h_length); - } - debug ("dns -> data: %x h -> h_addr_list [0]: %x", - *(int *)(dns -> data), h -> h_addr_list [0]); - dns -> data_len = new_len; - - /* Set the timeout for an hour from now. - XXX This should really use the time on the DNS reply. */ - dns -> timeout = cur_time + 3600; - - debug ("hard copy: %x %d %x", - dns -> data, dns -> data_len, *(int *)(dns -> data)); - do_data_copy (bufix, bufp, bufcount, dns -> data, dns -> data_len); - return dns -> timeout; -} - -static void do_data_copy (bufix, bufp, bufcount, data, len) - int *bufix; - unsigned char **bufp; - int *bufcount; - unsigned char *data; - int len; -{ - int space = *bufcount - *bufix; - - /* If there's more space than we need, use only what we need. */ - if (space > len) - space = len; - - /* Copy as much data as will fit, then increment the buffer index - by the amount we actually had to copy, which could be more. */ - if (space > 0) - memcpy (*bufp + *bufix, data, space); - *bufix += len; -} |