1998-06-25 03:57:00 +00:00
|
|
|
/* execute.c
|
|
|
|
|
|
|
|
Support for executable statements. */
|
|
|
|
|
|
|
|
/*
|
1999-03-16 05:50:46 +00:00
|
|
|
* Copyright (c) 1996-1999 Internet Software Consortium.
|
|
|
|
* Use is subject to license terms which appear in the file named
|
|
|
|
* ISC-LICENSE that should have accompanied this file when you
|
|
|
|
* received it. If a file named ISC-LICENSE did not accompany this
|
|
|
|
* file, or you are not sure the one you have is correct, you may
|
|
|
|
* obtain an applicable copy of the license at:
|
1998-06-25 03:57:00 +00:00
|
|
|
*
|
1999-03-16 05:50:46 +00:00
|
|
|
* http://www.isc.org/isc-license-1.0.html.
|
1998-06-25 03:57:00 +00:00
|
|
|
*
|
1999-03-16 05:50:46 +00:00
|
|
|
* This file is part of the ISC DHCP distribution. The documentation
|
|
|
|
* associated with this file is listed in the file DOCUMENTATION,
|
|
|
|
* included in the top-level directory of this release.
|
1998-06-25 03:57:00 +00:00
|
|
|
*
|
1999-03-16 05:50:46 +00:00
|
|
|
* Support and other services are available for ISC products - see
|
|
|
|
* http://www.isc.org for more information.
|
1998-06-25 03:57:00 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef lint
|
|
|
|
static char copyright[] =
|
1999-04-05 15:35:54 +00:00
|
|
|
"$Id: execute.c,v 1.9 1999/04/05 15:35:54 mellon Exp $ Copyright (c) 1998, 1999 The Internet Software Consortium. All rights reserved.\n";
|
1998-06-25 03:57:00 +00:00
|
|
|
#endif /* not lint */
|
|
|
|
|
|
|
|
#include "dhcpd.h"
|
|
|
|
|
1998-11-05 18:40:40 +00:00
|
|
|
int execute_statements (packet, in_options, out_options, statements)
|
1998-06-25 03:57:00 +00:00
|
|
|
struct packet *packet;
|
1998-11-05 18:40:40 +00:00
|
|
|
struct option_state *in_options;
|
|
|
|
struct option_state *out_options;
|
1998-06-25 03:57:00 +00:00
|
|
|
struct executable_statement *statements;
|
|
|
|
{
|
|
|
|
struct executable_statement *r;
|
1998-11-05 18:40:40 +00:00
|
|
|
int result;
|
|
|
|
int status;
|
1998-06-25 03:57:00 +00:00
|
|
|
|
|
|
|
if (!statements)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
for (r = statements; r; r = r -> next) {
|
|
|
|
switch (r -> op) {
|
|
|
|
case if_statement:
|
1998-11-05 18:40:40 +00:00
|
|
|
status = evaluate_boolean_expression
|
|
|
|
(&result, packet,
|
|
|
|
in_options, r -> data.ie.expr);
|
|
|
|
|
|
|
|
#if defined (DEBUG_EXPRESSIONS)
|
1999-02-24 17:56:53 +00:00
|
|
|
log_info ("exec: if %s", (status
|
1998-11-05 18:40:40 +00:00
|
|
|
? (result ? "true" : "false")
|
|
|
|
: "NULL"));
|
|
|
|
#endif
|
|
|
|
/* XXX Treat NULL as false */
|
|
|
|
if (!status)
|
|
|
|
result = 0;
|
1998-06-25 03:57:00 +00:00
|
|
|
if (!execute_statements
|
1998-11-05 18:40:40 +00:00
|
|
|
(packet, in_options, out_options,
|
|
|
|
result ? r -> data.ie.true : r -> data.ie.false))
|
1998-06-25 03:57:00 +00:00
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case eval_statement:
|
1998-11-05 18:40:40 +00:00
|
|
|
status = evaluate_boolean_expression
|
|
|
|
(&result,
|
|
|
|
packet, in_options, r -> data.eval);
|
|
|
|
#if defined (DEBUG_EXPRESSIONS)
|
1999-02-24 17:56:53 +00:00
|
|
|
log_info ("exec: evaluate: %s",
|
1998-11-05 18:40:40 +00:00
|
|
|
(status
|
|
|
|
? (result ? "true" : "false") : "NULL"));
|
|
|
|
#endif
|
1998-06-25 03:57:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case add_statement:
|
1998-11-05 18:40:40 +00:00
|
|
|
#if defined (DEBUG_EXPRESSIONS)
|
1999-02-24 17:56:53 +00:00
|
|
|
log_info ("exec: add %s", (r -> data.add -> name
|
1998-11-05 18:40:40 +00:00
|
|
|
? r -> data.add -> name
|
|
|
|
: "<unnamed class>"));
|
|
|
|
#endif
|
1998-06-25 03:57:00 +00:00
|
|
|
classify (packet, r -> data.add);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case break_statement:
|
1998-11-05 18:40:40 +00:00
|
|
|
#if defined (DEBUG_EXPRESSIONS)
|
1999-02-24 17:56:53 +00:00
|
|
|
log_info ("exec: break");
|
1998-11-05 18:40:40 +00:00
|
|
|
#endif
|
1998-06-25 03:57:00 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
case supersede_option_statement:
|
1998-11-05 18:40:40 +00:00
|
|
|
#if defined (DEBUG_EXPRESSIONS)
|
1999-02-24 17:56:53 +00:00
|
|
|
log_info ("exec: supersede option %s.%s",
|
1998-11-05 18:40:40 +00:00
|
|
|
r -> data.option -> option -> universe -> name,
|
|
|
|
r -> data.option -> option -> name);
|
|
|
|
goto option_statement;
|
|
|
|
#endif
|
1998-06-25 03:57:00 +00:00
|
|
|
case default_option_statement:
|
1998-11-05 18:40:40 +00:00
|
|
|
#if defined (DEBUG_EXPRESSIONS)
|
1999-02-24 17:56:53 +00:00
|
|
|
log_info ("exec: default option %s.%s",
|
1998-11-05 18:40:40 +00:00
|
|
|
r -> data.option -> option -> universe -> name,
|
|
|
|
r -> data.option -> option -> name);
|
|
|
|
goto option_statement;
|
|
|
|
#endif
|
1998-06-25 03:57:00 +00:00
|
|
|
case append_option_statement:
|
1998-11-05 18:40:40 +00:00
|
|
|
#if defined (DEBUG_EXPRESSIONS)
|
1999-02-24 17:56:53 +00:00
|
|
|
log_info ("exec: append option %s.%s",
|
1998-11-05 18:40:40 +00:00
|
|
|
r -> data.option -> option -> universe -> name,
|
|
|
|
r -> data.option -> option -> name);
|
|
|
|
goto option_statement;
|
|
|
|
#endif
|
1998-06-25 03:57:00 +00:00
|
|
|
case prepend_option_statement:
|
1998-11-05 18:40:40 +00:00
|
|
|
#if defined (DEBUG_EXPRESSIONS)
|
1999-02-24 17:56:53 +00:00
|
|
|
log_info ("exec: prepend option %s.%s",
|
1998-11-05 18:40:40 +00:00
|
|
|
r -> data.option -> option -> universe -> name,
|
|
|
|
r -> data.option -> option -> name);
|
|
|
|
option_statement:
|
|
|
|
#endif
|
1998-06-25 03:57:00 +00:00
|
|
|
if (r -> data.option -> option -> universe -> set_func)
|
1999-04-05 15:35:54 +00:00
|
|
|
((r -> data.option -> option ->
|
|
|
|
universe -> set_func)
|
|
|
|
(r -> data.option -> option -> universe,
|
|
|
|
out_options,
|
|
|
|
r -> data.option, r -> op));
|
1998-06-25 03:57:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
1999-02-24 17:56:53 +00:00
|
|
|
log_fatal ("bogus statement type %d\n", r -> op);
|
1998-06-25 03:57:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Execute all the statements in a particular scope, and all statements in
|
|
|
|
scopes outer from that scope, but if a particular limiting scope is
|
|
|
|
reached, do not execute statements in that scope or in scopes outer
|
1998-11-11 07:51:41 +00:00
|
|
|
from it. More specific scopes need to take precedence over less
|
|
|
|
specific scopes, so we recursively traverse the scope list, executing
|
|
|
|
the most outer scope first. */
|
1998-06-25 03:57:00 +00:00
|
|
|
|
1998-11-11 07:51:41 +00:00
|
|
|
void execute_statements_in_scope (packet, in_options, out_options,
|
|
|
|
group, limiting_group)
|
1998-06-25 03:57:00 +00:00
|
|
|
struct packet *packet;
|
1998-11-11 07:51:41 +00:00
|
|
|
struct option_state *in_options;
|
|
|
|
struct option_state *out_options;
|
1998-06-25 03:57:00 +00:00
|
|
|
struct group *group;
|
|
|
|
struct group *limiting_group;
|
|
|
|
{
|
|
|
|
struct group *scope;
|
1999-02-25 23:30:43 +00:00
|
|
|
struct group *limit;
|
|
|
|
|
1999-03-09 23:40:22 +00:00
|
|
|
/* If we've recursed as far as we can, return. */
|
|
|
|
if (!group)
|
|
|
|
return;
|
|
|
|
|
1999-02-25 23:30:43 +00:00
|
|
|
/* As soon as we get to a scope that is outer than the limiting
|
|
|
|
scope, we are done. This is so that if somebody does something
|
|
|
|
like this, it does the expected thing:
|
|
|
|
|
|
|
|
domain-name "fugue.com";
|
|
|
|
shared-network FOO {
|
|
|
|
host bar {
|
|
|
|
domain-name "othello.fugue.com";
|
|
|
|
fixed-address 10.20.30.40;
|
|
|
|
}
|
|
|
|
subnet 10.20.30.0 netmask 255.255.255.0 {
|
|
|
|
domain-name "manhattan.fugue.com";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
The problem with the above arrangement is that the host's
|
|
|
|
group nesting will be host -> shared-network -> top-level,
|
|
|
|
and the limiting scope when we evaluate the host's scope
|
|
|
|
will be the subnet -> shared-network -> top-level, so we need
|
|
|
|
to know when we evaluate the host's scope to stop before we
|
|
|
|
evaluate the shared-networks scope, because it's outer than
|
|
|
|
the limiting scope, which means we've already evaluated it. */
|
|
|
|
|
|
|
|
for (limit = limiting_group; limit; limit = limit -> next) {
|
|
|
|
if (group == limit)
|
|
|
|
return;
|
|
|
|
}
|
1998-06-25 03:57:00 +00:00
|
|
|
|
1998-11-11 07:51:41 +00:00
|
|
|
if (group -> next)
|
|
|
|
execute_statements_in_scope (packet, in_options, out_options,
|
|
|
|
group -> next, limiting_group);
|
|
|
|
execute_statements (packet,
|
|
|
|
in_options, out_options, group -> statements);
|
1998-06-25 03:57:00 +00:00
|
|
|
}
|