⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tree.c

📁 DHCP服务器源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* tree.c   Routines for manipulating parse trees... *//* * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") * Copyright (c) 1995-2003 by Internet Software Consortium * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * *   Internet Systems Consortium, Inc. *   950 Charter Street *   Redwood City, CA 94063 *   <info@isc.org> *   http://www.isc.org/ * * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. * To learn more about Internet Systems 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.9 2004/06/17 20:54:39 dhankins Exp $ Copyright (c) 2004 Internet Systems 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;		}		if (binding -> value -> type != binding_function) {			log_error ("%s: not a function.",				   expr -> data.funcall.name);			return 0;		}		/* Create a new binding scope in which to define		   the arguments to the function. */		ns = (struct binding_scope *)0;		if (!binding_scope_allocate (&ns, MDL)) {			log_error ("%s: can't allocate argument scope.",				   expr -> data.funcall.name);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -