From: Ted Lemon Date: Tue, 28 Nov 2000 23:27:24 +0000 (+0000) Subject: Pass client state to eval functions. Lots of other stuff. X-Git-Tag: V3-BETA-1-PATCH-11~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9e3831637a3a456632948252a193f7076122e46f;p=thirdparty%2Fdhcp.git Pass client state to eval functions. Lots of other stuff. --- diff --git a/server/bootp.c b/server/bootp.c index 87176ecdf..b32e27bd1 100644 --- a/server/bootp.c +++ b/server/bootp.c @@ -43,7 +43,7 @@ #ifndef lint static char copyright[] = -"$Id: bootp.c,v 1.67 2000/10/10 23:01:05 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n"; +"$Id: bootp.c,v 1.68 2000/11/28 23:27:13 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -93,7 +93,8 @@ void bootp (packet) packet -> raw -> hlen, MDL); lease = (struct lease *)0; - find_lease (&lease, packet, packet -> shared_network, 0, 0, MDL); + find_lease (&lease, packet, packet -> shared_network, + 0, 0, (struct lease *)0, MDL); /* Find an IP address in the host_decl that matches the specified network. */ @@ -156,7 +157,8 @@ void bootp (packet) /* Execute the subnet statements. */ execute_statements_in_scope ((struct binding_value **)0, - packet, lease, packet -> options, options, + packet, lease, (struct client_state *)0, + packet -> options, options, &lease -> scope, lease -> subnet -> group, (struct group *)0); @@ -164,20 +166,23 @@ void bootp (packet) for (i = packet -> class_count; i > 0; i--) { execute_statements_in_scope ((struct binding_value **)0, - packet, lease, packet -> options, options, + packet, lease, (struct client_state *)0, + packet -> options, options, &lease -> scope, packet -> classes [i - 1] -> group, lease -> subnet -> group); } /* Execute the host statements. */ execute_statements_in_scope ((struct binding_value **)0, - packet, lease, packet -> options, options, + packet, lease, (struct client_state *)0, + packet -> options, options, &lease -> scope, hp -> group, subnet -> group); /* Drop the request if it's not allowed for this client. */ if ((oc = lookup_option (&server_universe, options, SV_ALLOW_BOOTP)) && !evaluate_boolean_option_cache (&ignorep, packet, lease, + (struct client_state *)0, packet -> options, options, &lease -> scope, oc, MDL)) { if (!ignorep) @@ -188,6 +193,7 @@ void bootp (packet) if ((oc = lookup_option (&server_universe, options, SV_ALLOW_BOOTING)) && !evaluate_boolean_option_cache (&ignorep, packet, lease, + (struct client_state *)0, packet -> options, options, &lease -> scope, oc, MDL)) { if (!ignorep) @@ -204,8 +210,8 @@ void bootp (packet) just copy the input options to the output. */ if (!packet -> options_valid && !(evaluate_boolean_option_cache - (&ignorep, packet, lease, packet -> options, options, - &lease -> scope, + (&ignorep, packet, lease, (struct client_state *)0, + packet -> options, options, &lease -> scope, lookup_option (&server_universe, options, SV_ALWAYS_REPLY_RFC1048), MDL))) { memcpy (outgoing.raw -> options, @@ -238,7 +244,8 @@ void bootp (packet) name buffers. */ outgoing.packet_length = - cons_options (packet, outgoing.raw, lease, 0, + cons_options (packet, outgoing.raw, lease, + (struct client_state *)0, 0, packet -> options, options, &lease -> scope, 0, 0, 1, (struct data_string *)0, @@ -264,6 +271,7 @@ void bootp (packet) if ((oc = lookup_option (&server_universe, options, SV_ALWAYS_BROADCAST)) && evaluate_boolean_option_cache (&ignorep, packet, lease, + (struct client_state *)0, packet -> options, options, &lease -> scope, oc, MDL)) raw.flags |= htons (BOOTP_BROADCAST); @@ -273,6 +281,7 @@ void bootp (packet) oc = lookup_option (&server_universe, options, SV_NEXT_SERVER); if (oc && evaluate_option_cache (&d1, packet, lease, + (struct client_state *)0, packet -> options, options, &lease -> scope, oc, MDL)) { /* If there was more than one answer, take the first. */ @@ -293,6 +302,7 @@ void bootp (packet) oc = lookup_option (&server_universe, options, SV_FILENAME); if (oc && evaluate_option_cache (&d1, packet, lease, + (struct client_state *)0, packet -> options, options, &lease -> scope, oc, MDL)) { memcpy (raw.file, d1.data, @@ -308,6 +318,7 @@ void bootp (packet) oc = lookup_option (&server_universe, options, SV_SERVER_NAME); if (oc && evaluate_option_cache (&d1, packet, lease, + (struct client_state *)0, packet -> options, options, &lease -> scope, oc, MDL)) { memcpy (raw.sname, d1.data, @@ -320,7 +331,8 @@ void bootp (packet) /* Execute the commit statements, if there are any. */ execute_statements ((struct binding_value **)0, - packet, lease, packet -> options, + packet, lease, (struct client_state *)0, + packet -> options, options, &lease -> scope, lease -> on_commit); /* We're done with the option state. */ diff --git a/server/class.c b/server/class.c index ad08b2cc3..b1b0621f8 100644 --- a/server/class.c +++ b/server/class.c @@ -43,7 +43,7 @@ #ifndef lint static char copyright[] = -"$Id: class.c,v 1.26 2000/09/30 01:31:09 mellon Exp $ Copyright (c) 1998-2000 The Internet Software Consortium. All rights reserved.\n"; +"$Id: class.c,v 1.27 2000/11/28 23:27:14 mellon Exp $ Copyright (c) 1998-2000 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ @@ -84,10 +84,10 @@ void classification_setup () void classify_client (packet) struct packet *packet; { - execute_statements ((struct binding_value **)0, - packet, (struct lease *)0, packet -> options, - (struct option_state *)0, &global_scope, - default_classification_rules); + execute_statements ((struct binding_value **)0, packet, + (struct lease *)0, (struct client_state *)0, + packet -> options, (struct option_state *)0, + &global_scope, default_classification_rules); } int check_collection (packet, lease, collection) @@ -116,6 +116,7 @@ int check_collection (packet, lease, collection) if (class -> expr) { status = (evaluate_boolean_expression_result (&ignorep, packet, lease, + (struct client_state *)0, packet -> options, (struct option_state *)0, lease ? &lease -> scope : &global_scope, class -> expr)); @@ -138,6 +139,7 @@ int check_collection (packet, lease, collection) if (class -> submatch) { status = (evaluate_data_expression (&data, packet, lease, + (struct client_state *)0, packet -> options, (struct option_state *)0, lease ? &lease -> scope : &global_scope, class -> submatch)); diff --git a/server/confpars.c b/server/confpars.c index c197e288b..9281f63c9 100644 --- a/server/confpars.c +++ b/server/confpars.c @@ -1,3 +1,4 @@ +XXX Do tokens for client states! /* confpars.c Parser for dhcpd config file... */ @@ -43,7 +44,7 @@ #ifndef lint static char copyright[] = -"$Id: confpars.c,v 1.126 2000/09/01 19:35:38 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n"; +"$Id: confpars.c,v 1.127 2000/11/28 23:27:15 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -1728,14 +1729,20 @@ int parse_class_declaration (cp, cfile, group, type) if (token != IF) goto submatch; token = next_token (&val, cfile); - parse_boolean_expression (&class -> expr, cfile, - &lose); - if (lose) - break; + if (!parse_boolean_expression (&class -> expr, cfile, + &lose)) { + if (!lose) { + parse_warn (cfile, + "expecting boolean expr."); + skip_to_semi (cfile); + } + } else { #if defined (DEBUG_EXPRESSION_PARSE) - print_expression ("class match", class -> expr); + print_expression ("class match", + class -> expr); #endif - parse_semi (cfile); + parse_semi (cfile); + } } else if (token == SPAWN) { if (pc) { parse_warn (cfile, @@ -1760,15 +1767,20 @@ int parse_class_declaration (cp, cfile, group, type) skip_to_semi (cfile); break; } - parse_data_expression (&class -> submatch, - cfile, &lose); - if (lose) - break; + if (!parse_data_expression (&class -> submatch, + cfile, &lose)) { + if (!lose) { + parse_warn (cfile, + "expecting data expr."); + skip_to_semi (cfile); + } + } else { #if defined (DEBUG_EXPRESSION_PARSE) - print_expression ("class submatch", - class -> submatch); + print_expression ("class submatch", + class -> submatch); #endif - parse_semi (cfile); + parse_semi (cfile); + } } else if (token == LEASE) { next_token (&val, cfile); token = next_token (&val, cfile); @@ -2217,6 +2229,7 @@ int parse_lease_declaration (struct lease **lp, struct parse *cfile) struct binding *binding; isc_result_t status; binding_state_t *statep; + struct option_cache *oc, *optr; lease = (struct lease *)0; status = lease_allocate (&lease, MDL); @@ -2524,6 +2537,33 @@ int parse_lease_declaration (struct lease **lp, struct parse *cfile) executable_statement_dereference (&on, MDL); break; + case OPTION: + noequal = 0; + seenbit = 0; + oc = (struct option_cache *)0; + if (parse_option_decl (&oc, cfile)) { + if (oc -> option -> universe != + &agent_universe) { + parse_warn (cfile, + "agent option expected."); + option_cache_dereference (&oc, MDL); + break; + } + if (lease -> agent_options) { + for (optr = lease -> agent_options; + optr -> next; + optr = optr -> next) + ; + option_cache_reference (&optr -> next, + oc, MDL); + } else + option_cache_reference + (&lease -> agent_options, + oc, MDL); + option_cache_dereference (&oc, MDL); + } + break; + case TOKEN_SET: noequal = 0; diff --git a/server/db.c b/server/db.c index 9ec9dc6a7..e2134908b 100644 --- a/server/db.c +++ b/server/db.c @@ -43,7 +43,7 @@ #ifndef lint static char copyright[] = -"$Id: db.c,v 1.58 2000/09/04 22:28:38 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n"; +"$Id: db.c,v 1.59 2000/11/28 23:27:16 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -260,6 +260,25 @@ int write_lease (lease) } } } + if (lease -> agent_options) { + struct option_cache *oc; + struct data_string ds; + + memset (&ds, 0, sizeof ds); + for (oc = lease -> agent_options; oc; oc = oc -> next) { + if (oc -> data.len) { + errno = 0; + fprintf (db_file, "\n option agent.%s %s;", + oc -> option -> name, + pretty_print_option (oc -> option, + oc -> data.data, + oc -> data.len, + 1, 1)); + if (errno) + ++errors; + } + } + } if (lease -> client_hostname && db_printable (lease -> client_hostname)) { errno = 0; @@ -384,6 +403,7 @@ int write_host (host) if (host -> fixed_addr && evaluate_option_cache (&ip_addrs, (struct packet *)0, (struct lease *)0, + (struct client_state *)0, (struct option_state *)0, (struct option_state *)0, &global_scope, diff --git a/server/dhcp.c b/server/dhcp.c index e2273d464..5bf5667df 100644 --- a/server/dhcp.c +++ b/server/dhcp.c @@ -43,7 +43,7 @@ #ifndef lint static char copyright[] = -"$Id: dhcp.c,v 1.169 2000/10/13 18:58:12 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n"; +"$Id: dhcp.c,v 1.170 2000/11/28 23:27:17 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -57,9 +57,146 @@ void dhcp (packet) { int ms_nulltp = 0; struct option_cache *oc; + struct lease *lease = (struct lease *)0; + const char *errmsg; + struct data_string data; - if (!locate_network (packet) && packet -> packet_type != DHCPREQUEST) - return; + if (!locate_network (packet) && + packet -> packet_type != DHCPREQUEST && + packet -> packet_type != DHCPINFORM) { + static const char *dhcp_type_names [] = { + "DHCPDISCOVER", + "DHCPOFFER", + "DHCPREQUEST", + "DHCPDECLINE", + "DHCPACK", + "DHCPNAK", + "DHCPRELEASE", + "DHCPINFORM" + }; + const int dhcp_type_name_max = ((sizeof dhcp_type_names) / + sizeof (char *)); + const char *s; + char typebuf [32]; + errmsg = "unknown network segment"; + bad_packet: + + if (packet -> packet_type > 0 && + packet -> packet_type < dhcp_type_name_max - 1) { + s = dhcp_type_names [packet -> packet_type - 1]; + } else { +#if defined (HAVE_SNPRINTF) + snprintf (typebuf, sizeof typebuf, + "type %d", packet -> packet_type); +#else + sprintf (typebuf, + "type %d", packet -> packet_type); +#endif + s = typebuf; + } + + log_info ("%s from %s via %s: %s", s, + (packet -> raw -> htype + ? print_hw_addr (packet -> raw -> htype, + packet -> raw -> hlen, + packet -> raw -> chaddr) + : ""), + packet -> raw -> giaddr.s_addr + ? inet_ntoa (packet -> raw -> giaddr) + : packet -> interface -> name, errmsg); + goto out; + } + + /* There is a problem with the relay agent information option, + which is that in order for a normal relay agent to append + this option, the relay agent has to have been involved in + getting the packet from the client to the server. Note + that this is the software entity known as the relay agent, + _not_ the hardware entity known as a router in which the + relay agent may be running, so the fact that a router has + forwarded a packet does not mean that the relay agent in + the router was involved. + + So when the client is in INIT or INIT-REBOOT or REBINDING + state, the relay agent gets to tack on its options, but + when it's not, the relay agent doesn't get to do this, + which means that any decisions the DHCP server may make + based on the agent options will be made incorrectly. + + We work around this in the following way: if this is a + DHCPREQUEST and doesn't have relay agent information + options, we see if there's an existing lease for this IP + address and this client that _does_ have stashed agent + options. If so, then we tack those options onto the + packet as if they came from the client. Later on, when we + are deciding whether to steal the agent options from the + packet, if the agent options stashed on the lease are the + same as those stashed on the packet, we don't steal them - + this ensures that the client never receives its agent + options. */ + + if (packet -> packet_type == DHCPREQUEST && + packet -> raw -> ciaddr.s_addr && + !packet -> raw -> giaddr.s_addr && + (packet -> options -> universe_count < agent_universe.index || + !packet -> options -> universes [agent_universe.index])) + { + struct iaddr cip; + + cip.len = sizeof packet -> raw -> ciaddr; + memcpy (cip.iabuf, &packet -> raw -> ciaddr, + sizeof packet -> raw -> ciaddr); + if (!find_lease_by_ip_addr (&lease, cip, MDL)) + goto nolease; + + /* If there are no agent options on the lease, it's not + interesting. */ + if (!lease -> agent_options) + goto nolease; + + /* The client should not be unicasting a renewal if its lease + has expired, so make it go through the process of getting + its agent options legally. */ + if (lease -> ends < cur_time) + goto nolease; + + if (lease -> uid_len) { + oc = lookup_option (&dhcp_universe, packet -> options, + DHO_DHCP_CLIENT_IDENTIFIER); + if (!oc) + goto nolease; + + memset (&data, 0, sizeof data); + if (!evaluate_option_cache (&data, + packet, (struct lease *)0, + (struct client_state *)0, + packet -> options, + (struct option_state *)0, + &global_scope, oc, MDL)) + goto nolease; + if (lease -> uid_len != data.len || + memcmp (lease -> uid, data.data, data.len)) { + data_string_forget (&data, MDL); + goto nolease; + } + data_string_forget (&data, MDL); + } else + if ((lease -> hardware_addr.hbuf [0] != + packet -> raw -> htype) || + (lease -> hardware_addr.hlen - 1 != + packet -> raw -> hlen) || + memcmp (&lease -> hardware_addr.hbuf [1], + packet -> raw -> chaddr, + packet -> raw -> hlen)) + goto nolease; + + /* Okay, so we found a lease that matches the client. */ + option_cache_reference ((struct option_cache **) + &(packet -> options -> universes + [agent_universe.index]), + lease -> agent_options, MDL); + } + nolease: /* Classify the client. */ if ((oc = lookup_option (&dhcp_universe, packet -> options, @@ -80,7 +217,7 @@ void dhcp (packet) break; case DHCPREQUEST: - dhcprequest (packet, ms_nulltp); + dhcprequest (packet, ms_nulltp, lease); break; case DHCPRELEASE: @@ -95,9 +232,19 @@ void dhcp (packet) dhcpinform (packet, ms_nulltp); break; - default: + + case DHCPACK: + case DHCPOFFER: + case DHCPNAK: break; + + default: + errmsg = "unknown packet type"; + goto bad_packet; } + out: + if (lease) + lease_dereference (&lease, MDL); } void dhcpdiscover (packet, ms_nulltp) @@ -115,7 +262,7 @@ void dhcpdiscover (packet, ms_nulltp) #endif find_lease (&lease, packet, packet -> shared_network, - 0, &allocatedp, MDL); + 0, &allocatedp, (struct lease *)0, MDL); if (lease && lease -> client_hostname && db_printable (lease -> client_hostname)) @@ -216,9 +363,10 @@ void dhcpdiscover (packet, ms_nulltp) lease_dereference (&lease, MDL); } -void dhcprequest (packet, ms_nulltp) +void dhcprequest (packet, ms_nulltp, ip_lease) struct packet *packet; int ms_nulltp; + struct lease *ip_lease; { struct lease *lease; struct iaddr cip; @@ -238,6 +386,7 @@ void dhcprequest (packet, ms_nulltp) memset (&data, 0, sizeof data); if (oc && evaluate_option_cache (&data, packet, (struct lease *)0, + (struct client_state *)0, packet -> options, (struct option_state *)0, &global_scope, oc, MDL)) { cip.len = 4; @@ -256,7 +405,7 @@ void dhcprequest (packet, ms_nulltp) lease = (struct lease *)0; if (find_subnet (&subnet, cip, MDL)) find_lease (&lease, packet, - subnet -> shared_network, &ours, 0, MDL); + subnet -> shared_network, &ours, 0, ip_lease, MDL); /* XXX consider using allocatedp arg to find_lease to see XXX that this isn't a compliant DHCPREQUEST. */ @@ -351,8 +500,8 @@ void dhcprequest (packet, ms_nulltp) RENEWING client, so we can punt on this issue. */ if (!packet -> shared_network || - (packet -> raw -> ciaddr.s_addr && - packet -> raw -> giaddr.s_addr) || + (packet -> raw -> ciaddr.s_addr /* && + packet -> raw -> giaddr.s_addr */) || (oc && !packet -> raw -> ciaddr.s_addr)) { /* If we don't know where it came from but we do know @@ -436,6 +585,7 @@ void dhcprelease (packet, ms_nulltp) memset (&data, 0, sizeof data); if (oc && evaluate_option_cache (&data, packet, (struct lease *)0, + (struct client_state *)0, packet -> options, (struct option_state *)0, &global_scope, oc, MDL)) { find_lease_by_uid (&lease, data.data, data.len, MDL); @@ -519,15 +669,15 @@ void dhcpdecline (packet, ms_nulltp) int ms_nulltp; { struct lease *lease = (struct lease *)0; - struct iaddr cip; - struct option_cache *oc; - struct data_string data; struct option_state *options = (struct option_state *)0; int ignorep = 0; int i; const char *status; char *s; char msgbuf [1024]; /* XXX */ + struct iaddr cip; + struct option_cache *oc; + struct data_string data; /* DHCPDECLINE must specify address. */ if (!(oc = lookup_option (&dhcp_universe, packet -> options, @@ -535,6 +685,7 @@ void dhcpdecline (packet, ms_nulltp) return; memset (&data, 0, sizeof data); if (!evaluate_option_cache (&data, packet, (struct lease *)0, + (struct client_state *)0, packet -> options, (struct option_state *)0, &global_scope, oc, MDL)) @@ -572,6 +723,7 @@ void dhcpdecline (packet, ms_nulltp) if (lease) execute_statements_in_scope ((struct binding_value **)0, packet, (struct lease *)0, + (struct client_state *)0, packet -> options, options, &global_scope, lease -> subnet -> group, @@ -580,8 +732,8 @@ void dhcpdecline (packet, ms_nulltp) /* Execute statements in the class scopes. */ for (i = packet -> class_count; i > 0; i--) { execute_statements_in_scope - ((struct binding_value **)0, - packet, (struct lease *)0, packet -> options, options, + ((struct binding_value **)0, packet, (struct lease *)0, + (struct client_state *)0, packet -> options, options, &global_scope, packet -> classes [i - 1] -> group, lease ? lease -> subnet -> group : (struct group *)0); } @@ -590,6 +742,7 @@ void dhcpdecline (packet, ms_nulltp) oc = lookup_option (&server_universe, options, SV_DECLINES); if (!oc || evaluate_boolean_option_cache (&ignorep, packet, lease, + (struct client_state *)0, packet -> options, options, &lease -> scope, oc, MDL)) { /* If we found a lease, mark it as unusable and complain. */ @@ -714,6 +867,7 @@ void dhcpinform (packet, ms_nulltp) if (subnet) execute_statements_in_scope ((struct binding_value **)0, packet, (struct lease *)0, + (struct client_state *)0, packet -> options, options, &global_scope, subnet -> group, (struct group *)0); @@ -721,8 +875,8 @@ void dhcpinform (packet, ms_nulltp) /* Execute statements in the class scopes. */ for (i = packet -> class_count; i > 0; i--) { execute_statements_in_scope - ((struct binding_value **)0, - packet, (struct lease *)0, packet -> options, options, + ((struct binding_value **)0, packet, (struct lease *)0, + (struct client_state *)0, packet -> options, options, &global_scope, packet -> classes [i - 1] -> group, subnet ? subnet -> group : (struct group *)0); } @@ -732,6 +886,7 @@ void dhcpinform (packet, ms_nulltp) oc = lookup_option (&server_universe, options, SV_FILENAME); if (oc && evaluate_option_cache (&d1, packet, (struct lease *)0, + (struct client_state *)0, packet -> options, (struct option_state *)0, &global_scope, oc, MDL)) { i = d1.len; @@ -746,7 +901,8 @@ void dhcpinform (packet, ms_nulltp) /* Choose a server name as above. */ oc = lookup_option (&server_universe, options, SV_SERVER_NAME); if (oc && - evaluate_option_cache (&d1, packet, (struct lease *)0, + evaluate_option_cache (&d1, packet, (struct lease *)0, + (struct client_state *)0, packet -> options, (struct option_state *)0, &global_scope, oc, MDL)) { i = d1.len; @@ -763,7 +919,8 @@ void dhcpinform (packet, ms_nulltp) nulltp = 0; if ((oc = lookup_option (&dhcp_universe, packet -> options, DHO_HOST_NAME))) { - if (evaluate_option_cache (&d1, packet, (struct lease *)0, + if (evaluate_option_cache (&d1, packet, (struct lease *)0, + (struct client_state *)0, packet -> options, options, &global_scope, oc, MDL)) { if (d1.data [d1.len - 1] == '\0') @@ -804,6 +961,7 @@ void dhcpinform (packet, ms_nulltp) from = packet -> interface -> primary_address; } else { if (evaluate_option_cache (&d1, packet, (struct lease *)0, + (struct client_state *)0, packet -> options, options, &global_scope, oc, MDL)) { if (!d1.len || d1.len != sizeof from) { @@ -837,6 +995,7 @@ void dhcpinform (packet, ms_nulltp) i = SV_SITE_OPTION_SPACE; if ((oc = lookup_option (&server_universe, options, i)) && evaluate_option_cache (&d1, packet, (struct lease *)0, + (struct client_state *)0, packet -> options, options, &global_scope, oc, MDL)) { struct universe *u = (struct universe *)0; @@ -875,6 +1034,7 @@ void dhcpinform (packet, ms_nulltp) if (oc) evaluate_option_cache (&prl, packet, (struct lease *)0, + (struct client_state *)0, packet -> options, options, &global_scope, oc, MDL); @@ -890,6 +1050,7 @@ void dhcpinform (packet, ms_nulltp) if ((oc = lookup_option (&server_universe, options, SV_NEXT_SERVER))) { if (evaluate_option_cache (&d1, packet, (struct lease *)0, + (struct client_state *)0, packet -> options, options, &global_scope, oc, MDL)) { /* If there was more than one answer, @@ -903,6 +1064,7 @@ void dhcpinform (packet, ms_nulltp) /* Set up the option buffer... */ outgoing.packet_length = cons_options (packet, outgoing.raw, (struct lease *)0, + (struct client_state *)0, 0, packet -> options, options, &global_scope, 0, nulltp, 0, prl.len ? &prl : (struct data_string *)0, @@ -1034,6 +1196,7 @@ void nak_lease (packet, cip) } else { memset (&data, 0, sizeof data); if (evaluate_option_cache (&data, packet, (struct lease *)0, + (struct client_state *)0, packet -> options, options, &global_scope, oc, MDL)) { if (!data.len || @@ -1055,6 +1218,7 @@ void nak_lease (packet, cip) /* Set up the option buffer... */ outgoing.packet_length = cons_options (packet, outgoing.raw, (struct lease *)0, + (struct client_state *)0, 0, packet -> options, options, &global_scope, 0, 0, 0, (struct data_string *)0, (char *)0); option_state_dereference (&options, MDL); @@ -1181,12 +1345,20 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) packet -> options, DHO_DHCP_SERVER_IDENTIFIER)) state -> got_server_identifier = 1; - /* Steal the agent options from the packet. */ - if (packet -> options -> universes [agent_universe.index]) { - option_state_reference - ((struct option_state **) + /* If this is not a unicast DHCPREQUEST, steal the agent options + from the packet. Do not do this if the packet looks like + it came from a client in the RENEWING state or if it was not + relayed (giaddr is not set). */ + if (!packet -> raw -> ciaddr.s_addr && + packet -> raw -> giaddr.s_addr && + packet -> options -> universe_count > agent_universe.index && + packet -> options -> universes [agent_universe.index] && + (state -> options -> universe_count <= agent_universe.index || + !state -> options -> universes [agent_universe.index])) { + option_cache_reference + ((struct option_cache **) &(state -> options -> universes [agent_universe.index]), - (struct option_state *) + (struct option_cache *) packet -> options -> universes [agent_universe.index], MDL); } @@ -1213,7 +1385,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) /* Execute statements in scope starting with the subnet scope. */ execute_statements_in_scope ((struct binding_value **)0, - packet, lease, + packet, lease, (struct client_state *)0, packet -> options, state -> options, &lease -> scope, lease -> subnet -> group, @@ -1223,6 +1395,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) if (lease -> pool) execute_statements_in_scope ((struct binding_value **)0, packet, lease, + (struct client_state *)0, packet -> options, state -> options, &lease -> scope, lease -> pool -> group, @@ -1232,7 +1405,8 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) for (i = packet -> class_count; i > 0; i--) { execute_statements_in_scope ((struct binding_value **)0, - packet, lease, packet -> options, state -> options, + packet, lease, (struct client_state *)0, + packet -> options, state -> options, &lease -> scope, packet -> classes [i - 1] -> group, (lease -> pool ? lease -> pool -> group @@ -1243,7 +1417,9 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) with its group. */ if (lease -> host) execute_statements_in_scope ((struct binding_value **)0, - packet, lease, packet -> options, + packet, lease, + (struct client_state *)0, + packet -> options, state -> options, &lease -> scope, lease -> host -> group, (lease -> pool @@ -1263,7 +1439,9 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) (oc = lookup_option (&server_universe, state -> options, SV_ONE_LEASE_PER_CLIENT)) && evaluate_boolean_option_cache (&ignorep, - packet, lease, packet -> options, + packet, lease, + (struct client_state *)0, + packet -> options, state -> options, &lease -> scope, oc, MDL)) { struct lease *seek; @@ -1296,6 +1474,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) (oc = lookup_option (&server_universe, state -> options, SV_DUPLICATES)) && !evaluate_boolean_option_cache (&ignorep, packet, lease, + (struct client_state *)0, packet -> options, state -> options, &lease -> scope, @@ -1330,6 +1509,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) (oc = lookup_option (&server_universe, state -> options, SV_MIN_SECS))) { if (evaluate_option_cache (&d1, packet, lease, + (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL)) { if (d1.len && packet -> raw -> secs < d1.data [0]) { @@ -1358,6 +1538,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) DHO_DHCP_CLIENT_IDENTIFIER); if (oc && evaluate_option_cache (&d1, packet, lease, + (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL)) { find_hosts_by_uid (&hp, d1.data, d1.len, MDL); @@ -1388,7 +1569,9 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) (oc = lookup_option (&server_universe, state -> options, SV_BOOT_UNKNOWN_CLIENTS)) && !evaluate_boolean_option_cache (&ignorep, - packet, lease, packet -> options, + packet, lease, + (struct client_state *)0, + packet -> options, state -> options, &lease -> scope, oc, MDL)) { if (!ignorep) @@ -1403,7 +1586,9 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) (oc = lookup_option (&server_universe, state -> options, SV_ALLOW_BOOTP)) && !evaluate_boolean_option_cache (&ignorep, - packet, lease, packet -> options, + packet, lease, + (struct client_state *)0, + packet -> options, state -> options, &lease -> scope, oc, MDL)) { if (!ignorep) @@ -1418,7 +1603,9 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) SV_ALLOW_BOOTING); if (oc && !evaluate_boolean_option_cache (&ignorep, - packet, lease, packet -> options, + packet, lease, + (struct client_state *)0, + packet -> options, state -> options, &lease -> scope, oc, MDL)) { if (!ignorep) @@ -1472,6 +1659,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) oc = lookup_option (&server_universe, state -> options, SV_FILENAME); if (oc) evaluate_option_cache (&state -> filename, packet, lease, + (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL); @@ -1480,6 +1668,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) SV_SERVER_NAME); if (oc) evaluate_option_cache (&state -> server_name, packet, lease, + (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL); @@ -1510,6 +1699,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) if ((oc = lookup_option (&server_universe, state -> options, SV_DEFAULT_LEASE_TIME))) { if (evaluate_option_cache (&d1, packet, lease, + (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL)) { @@ -1523,6 +1713,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) if ((oc = lookup_option (&dhcp_universe, packet -> options, DHO_DHCP_LEASE_TIME))) s1 = evaluate_option_cache (&d1, packet, lease, + (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL); @@ -1542,6 +1733,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) if ((oc = lookup_option (&server_universe, state -> options, SV_MAX_LEASE_TIME))) { if (evaluate_option_cache (&d1, packet, lease, + (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL)) { @@ -1564,6 +1756,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) if ((oc = lookup_option (&server_universe, state -> options, SV_MIN_LEASE_TIME))) { if (evaluate_option_cache (&d1, packet, lease, + (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL)) { @@ -1650,6 +1843,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) if ((oc = lookup_option (&server_universe, state -> options, SV_BOOTP_LEASE_LENGTH))) { if (evaluate_option_cache (&d1, packet, lease, + (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL)) { @@ -1662,6 +1856,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) if ((oc = lookup_option (&server_universe, state -> options, SV_BOOTP_LEASE_CUTOFF))) { if (evaluate_option_cache (&d1, packet, lease, + (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL)) { @@ -1683,6 +1878,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) DHO_DHCP_CLIENT_IDENTIFIER); if (oc && evaluate_option_cache (&d1, packet, lease, + (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL)) { if (d1.len <= sizeof lt -> uid_buf) { @@ -1725,10 +1921,39 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) binding_scope_dereference (&lease -> scope, MDL); } + /* If we got relay agent information options, and the packet really + looks like it came through a relay agent, and if this feature is + not disabled, save the relay agent information options that came + in with the packet, so that we can use them at renewal time when + the packet won't have gone through a relay agent. */ + if (!packet -> raw -> ciaddr.s_addr && + packet -> raw -> giaddr.s_addr && + packet -> options -> universe_count > agent_universe.index && + packet -> options -> universes [agent_universe.index] && + (state -> options -> universe_count <= agent_universe.index || + state -> options -> universes [agent_universe.index] == + packet -> options -> universes [agent_universe.index])) { + oc = lookup_option (&server_universe, state -> options, + SV_STASH_AGENT_OPTIONS); + if (!oc || + evaluate_boolean_option_cache (&ignorep, packet, lease, + (struct client_state *)0, + packet -> options, + state -> options, + &lease -> scope, oc, MDL)) { + option_cache_reference + (< -> agent_options, + (struct option_cache *) + packet -> options -> universes [agent_universe.index], + MDL); + } + } + /* Replace the old lease hostname with the new one, if it's changed. */ oc = lookup_option (&dhcp_universe, packet -> options, DHO_HOST_NAME); if (oc) s1 = evaluate_option_cache (&d1, packet, (struct lease *)0, + (struct client_state *)0, packet -> options, (struct option_state *)0, &global_scope, oc, MDL); @@ -1755,7 +1980,8 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) committed, execute them. */ if (lease -> on_commit && (!offer || offer == DHCPACK)) { execute_statements ((struct binding_value **)0, - packet, lt, packet -> options, + packet, lt, (struct client_state *)0, + packet -> options, state -> options, < -> scope, lease -> on_commit); if (lease -> on_commit) @@ -1813,6 +2039,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) if ((oc = lookup_option (&server_universe, state -> options, SV_ALWAYS_BROADCAST)) && evaluate_boolean_option_cache (&ignorep, packet, lease, + (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL)) state -> bootp_flags |= htons (BOOTP_BROADCAST); @@ -1823,6 +2050,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) DHO_DHCP_MAX_MESSAGE_SIZE); if (oc && evaluate_option_cache (&d1, packet, lease, + (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL)) { if (d1.len == sizeof (u_int16_t)) @@ -1833,6 +2061,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) DHO_DHCP_MAX_MESSAGE_SIZE); if (oc && evaluate_option_cache (&d1, packet, lease, + (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL)) { if (d1.len == sizeof (u_int16_t)) @@ -1883,6 +2112,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) state -> from.len); } else { if (evaluate_option_cache (&d1, packet, lease, + (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL)) { @@ -1974,6 +2204,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) lookup_option (&server_universe, state -> options, SV_NEXT_SERVER))) { if (evaluate_option_cache (&d1, packet, lease, + (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL)) { /* If there was more than one answer, @@ -2010,8 +2241,8 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) if (!lookup_option (&dhcp_universe, state -> options, i) && lease -> host && lease -> host -> name && (evaluate_boolean_option_cache - (&ignorep, packet, lease, packet -> options, state -> options, - &lease -> scope, + (&ignorep, packet, lease, (struct client_state *)0, + packet -> options, state -> options, &lease -> scope, lookup_option (&server_universe, state -> options, j), MDL))) { oc = (struct option_cache *)0; if (option_cache_allocate (&oc, MDL)) { @@ -2033,9 +2264,9 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) j = SV_GET_LEASE_HOSTNAMES; if (!lookup_option (&server_universe, state -> options, i) && (evaluate_boolean_option_cache - (&ignorep, packet, lease, packet -> options, state -> options, - &lease -> scope, lookup_option (&server_universe, - state -> options, j), MDL))) { + (&ignorep, packet, lease, (struct client_state *)0, + packet -> options, state -> options, &lease -> scope, + lookup_option (&server_universe, state -> options, j), MDL))) { struct in_addr ia; struct hostent *h; @@ -2067,8 +2298,8 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) so if the local router does proxy arp, you win. */ if (evaluate_boolean_option_cache - (&ignorep, packet, lease, packet -> options, state -> options, - &lease -> scope, + (&ignorep, packet, lease, (struct client_state *)0, + packet -> options, state -> options, &lease -> scope, lookup_option (&server_universe, state -> options, SV_USE_LEASE_ADDR_FOR_DEFAULT_ROUTE), MDL)) { i = DHO_ROUTERS; @@ -2095,6 +2326,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) i = SV_SITE_OPTION_SPACE; if ((oc = lookup_option (&server_universe, state -> options, i)) && evaluate_option_cache (&d1, packet, lease, + (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL)) { struct universe *u = (struct universe *)0; @@ -2127,7 +2359,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp) DHO_DHCP_PARAMETER_REQUEST_LIST); if (oc) evaluate_option_cache (&state -> parameter_request_list, - packet, lease, + packet, lease, (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL); @@ -2231,6 +2463,7 @@ void dhcp_reply (lease) /* Insert such options as will fit into the buffer. */ packet_length = cons_options (state -> packet, &raw, lease, + (struct client_state *)0, state -> max_message_size, state -> packet -> options, state -> options, &global_scope, @@ -2376,7 +2609,8 @@ void dhcp_reply (lease) int find_lease (struct lease **lp, struct packet *packet, struct shared_network *share, int *ours, - int *allocatedp, const char *file, int line) + int *allocatedp, struct lease *ip_lease_in, + const char *file, int line) { struct lease *uid_lease = (struct lease *)0; struct lease *ip_lease = (struct lease *)0; @@ -2394,23 +2628,27 @@ int find_lease (struct lease **lp, int status; struct hardware h; - /* Look up the requested address. */ - oc = lookup_option (&dhcp_universe, packet -> options, - DHO_DHCP_REQUESTED_ADDRESS); - memset (&d1, 0, sizeof d1); - if (oc && - evaluate_option_cache (&d1, packet, (struct lease *)0, - packet -> options, (struct option_state *)0, - &global_scope, oc, MDL)) { - packet -> got_requested_address = 1; - cip.len = 4; - memcpy (cip.iabuf, d1.data, cip.len); - data_string_forget (&d1, MDL); - } else if (packet -> raw -> ciaddr.s_addr) { + if (packet -> raw -> ciaddr.s_addr) { cip.len = 4; memcpy (cip.iabuf, &packet -> raw -> ciaddr, 4); - } else - cip.len = 0; + } else { + /* Look up the requested address. */ + oc = lookup_option (&dhcp_universe, packet -> options, + DHO_DHCP_REQUESTED_ADDRESS); + memset (&d1, 0, sizeof d1); + if (oc && + evaluate_option_cache (&d1, packet, (struct lease *)0, + (struct client_state *)0, + packet -> options, + (struct option_state *)0, + &global_scope, oc, MDL)) { + packet -> got_requested_address = 1; + cip.len = 4; + memcpy (cip.iabuf, d1.data, cip.len); + data_string_forget (&d1, MDL); + } else + cip.len = 0; + } /* Try to find a host or lease that's been assigned to the specified unique client identifier. */ @@ -2420,6 +2658,7 @@ int find_lease (struct lease **lp, if (oc && evaluate_option_cache (&client_identifier, packet, (struct lease *)0, + (struct client_state *)0, packet -> options, (struct option_state *)0, &global_scope, oc, MDL)) { /* Remember this for later. */ @@ -2594,7 +2833,9 @@ int find_lease (struct lease **lp, /* Try to find a lease that's been allocated to the client's IP address. */ - if (cip.len) + if (ip_lease_in) + lease_reference (&ip_lease, ip_lease_in, MDL); + else if (cip.len) find_lease_by_ip_addr (&ip_lease, cip, MDL); #if defined (DEBUG_FIND_LEASE) @@ -2722,6 +2963,13 @@ int find_lease (struct lease **lp, strcpy (dhcp_message, "database conflict - call for help!"); } + + if (ip_lease && ip_lease != uid_lease) { +#if defined (DEBUG_FIND_LEASE) + log_info ("requested address not available."); +#endif + lease_dereference (&ip_lease, MDL); + } } /* If we get to here with both fixed_lease and ip_lease not @@ -2999,6 +3247,8 @@ void static_lease_dereference (lease, file, line) file, line); if (lease -> scope) binding_scope_dereference (&lease -> scope, file, line); + if (lease -> agent_options) + option_cache_dereference (&lease -> agent_options, file, line); if (lease -> uid != lease -> uid_buf) { dfree (lease -> uid, file, line); lease -> uid = (unsigned char *)0; @@ -3196,6 +3446,7 @@ int locate_network (packet) if (oc) { memset (&data, 0, sizeof data); if (!evaluate_option_cache (&data, packet, (struct lease *)0, + (struct client_state *)0, packet -> options, (struct option_state *)0, &global_scope, oc, MDL)) { diff --git a/server/dhcpd.c b/server/dhcpd.c index 153eb692a..80c503314 100644 --- a/server/dhcpd.c +++ b/server/dhcpd.c @@ -43,7 +43,7 @@ #ifndef lint static char ocopyright[] = -"$Id: dhcpd.c,v 1.101 2000/09/01 23:06:31 mellon Exp $ Copyright 1995-2000 Internet Software Consortium."; +"$Id: dhcpd.c,v 1.102 2000/11/28 23:27:19 mellon Exp $ Copyright 1995-2000 Internet Software Consortium."; #endif static char copyright[] = @@ -71,62 +71,75 @@ int server_identifier_matched; char std_nsupdate [] = " \n\ on commit { \n\ if (((config-option server.ddns-updates = null) or \n\ - (config-option server.ddns-updates != 0)) and \n\ - (not defined (ddns-fwd-name))) { \n\ - set ddns-fwd-name = concat (pick (config-option server.ddns-hostname, \n\ - option host-name), \".\", \n\ - pick (config-option server.ddns-domainname, \n\ - config-option domain-name)); \n\ - if defined (ddns-fwd-name) { \n\ - switch (ns-update (not exists (IN, A, ddns-fwd-name, null), \n\ - add (IN, A, ddns-fwd-name, leased-address, \n\ - lease-time / 2))) { \n\ - default: \n\ - unset ddns-fwd-name; \n\ - break; \n\ + (config-option server.ddns-updates != 0))) { \n\ + set new-ddns-fwd-name = \n\ + concat (pick (config-option server.ddns-hostname, \n\ + option host-name), \".\", \n\ + pick (config-option server.ddns-domainname, \n\ + config-option domain-name)); \n\ + if (defined (ddns-fwd-name) and ddns-fwd-name != new-ddns-fwd-name) { \n\ + switch (ns-update (delete (IN, A, ddns-fwd-name, leased-address))) { \n\ + case NOERROR: \n\ + unset ddns-fwd-name; \n\ + on expiry or release { \n\ + } + } \n\ + } \n\ \n\ - case NOERROR: \n\ - set ddns-rev-name = \n\ - concat (binary-to-ascii (10, 8, \".\", \n\ - reverse (1, \n\ - leased-address)), \".\", \n\ - pick (config-option server.ddns-rev-domainname, \n\ - \"in-addr.arpa.\")); \n\ - switch (ns-update (delete (IN, PTR, ddns-rev-name, null), \n\ - add (IN, PTR, ddns-rev-name, ddns-fwd-name, \n\ - lease-time / 2))) \n\ - { \n\ - default: \n\ - unset ddns-rev-name; \n\ - on release or expiry { \n\ - switch (ns-update (delete (IN, A, ddns-fwd-name, \n\ - leased-address))) { \n\ - case NOERROR: \n\ - unset ddns-fwd-name; \n\ - break; \n\ - } \n\ - on release or expiry; \n\ - } \n\ + if (not defined (ddns-fwd-name)) { \n\ + set ddns-fwd-name = new-ddns-fwd-name; \n\ + if defined (ddns-fwd-name) { \n\ + switch (ns-update (not exists (IN, A, ddns-fwd-name, null), \n\ + add (IN, A, ddns-fwd-name, leased-address, \n\ + lease-time / 2))) { \n\ + default: \n\ + unset ddns-fwd-name; \n\ break; \n\ \n\ - case NOERROR: \n\ - on release or expiry { \n\ - switch (ns-update (delete (IN, PTR, ddns-rev-name, null))) { \n\ - case NOERROR: \n\ - unset ddns-rev-name; \n\ - break; \n\ - } \n\ - switch (ns-update (delete (IN, A, ddns-fwd-name, \n\ - leased-address))) { \n\ - case NOERROR: \n\ - unset ddns-fwd-name; \n\ - break; \n\ + case NOERROR: \n\ + set ddns-rev-name = \n\ + concat (binary-to-ascii (10, 8, \".\", \n\ + reverse (1, \n\ + leased-address)), \".\", \n\ + pick (config-option server.ddns-rev-domainname, \n\ + \"in-addr.arpa.\")); \n\ + switch (ns-update (delete (IN, PTR, ddns-rev-name, null), \n\ + add (IN, PTR, ddns-rev-name, ddns-fwd-name, \n\ + lease-time / 2))) \n\ + { \n\ + default: \n\ + unset ddns-rev-name; \n\ + on release or expiry { \n\ + switch (ns-update (delete (IN, A, ddns-fwd-name, \n\ + leased-address))) { \n\ + case NOERROR: \n\ + unset ddns-fwd-name; \n\ + break; \n\ + } \n\ + on release or expiry; \n\ + } \n\ + break; \n\ + \n\ + case NOERROR: \n\ + on release or expiry { \n\ + switch (ns-update (delete (IN, PTR, ddns-rev-name, null))) {\n\ + case NOERROR: \n\ + unset ddns-rev-name; \n\ + break; \n\ + } \n\ + switch (ns-update (delete (IN, A, ddns-fwd-name, \n\ + leased-address))) { \n\ + case NOERROR: \n\ + unset ddns-fwd-name; \n\ + break; \n\ + } \n\ + on release or expiry; \n\ + } \n\ } \n\ - on release or expiry; \n\ - } \n\ - } \n\ + } \n\ } \n\ } \n\ + unset new-ddns-fwd-name; \n\ } \n\ }"; #endif /* NSUPDATE */ @@ -380,6 +393,7 @@ int main (argc, argv, envp) execute_statements_in_scope ((struct binding_value **)0, (struct packet *)0, (struct lease *)0, + (struct client_state *)0, (struct option_state *)0, options, &global_scope, root_group, @@ -388,8 +402,8 @@ int main (argc, argv, envp) oc = lookup_option (&server_universe, options, SV_LEASE_FILE_NAME); if (oc && evaluate_option_cache (&db, (struct packet *)0, - (struct lease *)0, options, - (struct option_state *)0, + (struct lease *)0, (struct client_state *)0, + options, (struct option_state *)0, &global_scope, oc, MDL)) { s = dmalloc (db.len + 1, MDL); if (!s) @@ -403,8 +417,8 @@ int main (argc, argv, envp) oc = lookup_option (&server_universe, options, SV_PID_FILE_NAME); if (oc && evaluate_option_cache (&db, (struct packet *)0, - (struct lease *)0, options, - (struct option_state *)0, + (struct lease *)0, (struct client_state *)0, + options, (struct option_state *)0, &global_scope, oc, MDL)) { s = dmalloc (db.len + 1, MDL); if (!s) @@ -419,8 +433,8 @@ int main (argc, argv, envp) oc = lookup_option (&server_universe, options, SV_OMAPI_PORT); if (oc && evaluate_option_cache (&db, (struct packet *)0, - (struct lease *)0, options, - (struct option_state *)0, + (struct lease *)0, (struct client_state *)0, + options, (struct option_state *)0, &global_scope, oc, MDL)) { if (db.len == 2) { omapi_port = getUShort (db.data); @@ -432,7 +446,8 @@ int main (argc, argv, envp) oc = lookup_option (&server_universe, options, SV_OMAPI_KEY); if (oc && evaluate_option_cache (&db, (struct packet *)0, - (struct lease *)0, options, + (struct lease *)0, (struct client_state *)0, + options, (struct option_state *)0, &global_scope, oc, MDL)) { s = dmalloc (db.len + 1, MDL); @@ -450,7 +465,8 @@ int main (argc, argv, envp) oc = lookup_option (&server_universe, options, SV_LOCAL_PORT); if (oc && evaluate_option_cache (&db, (struct packet *)0, - (struct lease *)0, options, + (struct lease *)0, (struct client_state *)0, + options, (struct option_state *)0, &global_scope, oc, MDL)) { if (db.len == 2) { @@ -463,8 +479,8 @@ int main (argc, argv, envp) oc = lookup_option (&server_universe, options, SV_REMOTE_PORT); if (oc && evaluate_option_cache (&db, (struct packet *)0, - (struct lease *)0, options, - (struct option_state *)0, + (struct lease *)0, (struct client_state *)0, + options, (struct option_state *)0, &global_scope, oc, MDL)) { if (db.len == 2) { remote_port = htons (getUShort (db.data)); @@ -477,8 +493,8 @@ int main (argc, argv, envp) SV_LIMITED_BROADCAST_ADDRESS); if (oc && evaluate_option_cache (&db, (struct packet *)0, - (struct lease *)0, options, - (struct option_state *)0, + (struct lease *)0, (struct client_state *)0, + options, (struct option_state *)0, &global_scope, oc, MDL)) { if (db.len == 4) { memcpy (&limited_broadcast, db.data, 4); @@ -491,8 +507,8 @@ int main (argc, argv, envp) SV_LOCAL_ADDRESS); if (oc && evaluate_option_cache (&db, (struct packet *)0, - (struct lease *)0, options, - (struct option_state *)0, + (struct lease *)0, (struct client_state *)0, + options, (struct option_state *)0, &global_scope, oc, MDL)) { if (db.len == 4) { memcpy (&local_address, db.data, 4); diff --git a/server/failover.c b/server/failover.c index f3d44a70a..6e7e7c106 100644 --- a/server/failover.c +++ b/server/failover.c @@ -43,7 +43,7 @@ #ifndef lint static char copyright[] = -"$Id: failover.c,v 1.29 2000/11/24 04:19:05 mellon Exp $ Copyright (c) 1999-2000 The Internet Software Consortium. All rights reserved.\n"; +"$Id: failover.c,v 1.30 2000/11/28 23:27:20 mellon Exp $ Copyright (c) 1999-2000 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -190,6 +190,7 @@ isc_result_t dhcp_failover_link_initiate (omapi_object_t *h) memset (&ds, 0, sizeof ds); if (!evaluate_option_cache (&ds, (struct packet *)0, (struct lease *)0, + (struct client_state *)0, (struct option_state *)0, (struct option_state *)0, &global_scope, obj -> peer_address, MDL)) { @@ -218,6 +219,7 @@ isc_result_t dhcp_failover_link_initiate (omapi_object_t *h) if (!state -> me.address || !evaluate_option_cache (&ds, (struct packet *)0, (struct lease *)0, + (struct client_state *)0, (struct option_state *)0, (struct option_state *)0, &global_scope, state -> me.address, @@ -2248,6 +2250,7 @@ isc_result_t dhcp_failover_state_get_value (omapi_object_t *h, memset (&ds, 0, sizeof ds); if (!evaluate_option_cache (&ds, (struct packet *)0, (struct lease *)0, + (struct client_state *)0, (struct option_state *)0, (struct option_state *)0, &global_scope, oc, MDL)) { @@ -2645,6 +2648,7 @@ int dhcp_failover_state_match (dhcp_failover_state_t *state, memset (&ds, 0, sizeof ds); if (evaluate_option_cache (&ds, (struct packet *)0, (struct lease *)0, + (struct client_state *)0, (struct option_state *)0, (struct option_state *)0, &global_scope, @@ -4293,6 +4297,7 @@ int load_balance_mine (struct packet *packet, dhcp_failover_state_t *state) memset (&ds, 0, sizeof ds); if (oc && evaluate_option_cache (&ds, packet, (struct lease *)0, + (struct client_state *)0, packet -> options, (struct option_state *)0, &global_scope, oc, MDL)) { hbaix = loadb_p_hash (ds.data, ds.len); diff --git a/server/mdb.c b/server/mdb.c index ce40563f8..4d095307b 100644 --- a/server/mdb.c +++ b/server/mdb.c @@ -43,7 +43,7 @@ #ifndef lint static char copyright[] = -"$Id: mdb.c,v 1.43 2000/09/29 18:21:33 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium. All rights reserved.\n"; +"$Id: mdb.c,v 1.44 2000/11/28 23:27:21 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -154,7 +154,8 @@ isc_result_t enter_host (hd, dynamicp, commit) DHO_DHCP_CLIENT_IDENTIFIER)) { evaluate_option_cache (&hd -> client_identifier, (struct packet *)0, - (struct lease *)0, (struct option_state *)0, + (struct lease *)0, (struct client_state *)0, + (struct option_state *)0, (struct option_state *)0, &global_scope, esp -> data.option, MDL); break; @@ -377,6 +378,7 @@ int find_host_for_network (struct subnet **sp, struct host_decl **host, continue; if (!evaluate_option_cache (&fixed_addr, (struct packet *)0, (struct lease *)0, + (struct client_state *)0, (struct option_state *)0, (struct option_state *)0, &global_scope, @@ -875,6 +877,21 @@ int supersede_lease (comp, lease, commit, propogate, pimmediate) binding_scope_dereference (&lease -> scope, MDL); } + if (comp -> agent_options) + option_cache_dereference (&comp -> agent_options, MDL); + if (lease -> agent_options) { + /* Only retain the agent options if the lease is still + affirmatively associated with a client. */ + if (lease -> binding_state == FTS_ACTIVE || + lease -> binding_state == FTS_EXPIRED || + lease -> binding_state == FTS_ABANDONED || + lease -> binding_state == FTS_RESERVED || + lease -> binding_state == FTS_BOOTP) + option_cache_reference (&comp -> agent_options, + lease -> agent_options, MDL); + option_cache_dereference (&lease -> agent_options, MDL); + } + /* Record the hostname information in the lease. */ if (comp -> hostname) dfree (comp -> hostname, MDL); @@ -1048,6 +1065,7 @@ void process_state_transition (struct lease *lease) if (lease -> on_expiry) { execute_statements ((struct binding_value **)0, (struct packet *)0, lease, + (struct client_state *)0, (struct option_state *)0, (struct option_state *)0, /* XXX */ &lease -> scope, @@ -1074,6 +1092,7 @@ void process_state_transition (struct lease *lease) if (lease -> on_release) { execute_statements ((struct binding_value **)0, (struct packet *)0, lease, + (struct client_state *)0, (struct option_state *)0, (struct option_state *)0, /* XXX */ &lease -> scope, @@ -1152,6 +1171,9 @@ int lease_copy (struct lease **lp, } if (lease -> scope) binding_scope_reference (< -> scope, lease -> scope, MDL); + if (lease -> agent_options) + option_cache_reference (< -> agent_options, + lease -> agent_options, MDL); host_reference (< -> host, lease -> host, file, line); subnet_reference (< -> subnet, lease -> subnet, file, line); pool_reference (< -> pool, lease -> pool, file, line); @@ -1190,7 +1212,8 @@ void release_lease (lease, packet) released, execute them. */ if (lease -> on_release) { execute_statements ((struct binding_value **)0, - packet, lease, packet -> options, + packet, lease, (struct client_state *)0, + packet -> options, (struct option_state *)0, /* XXX */ &lease -> scope, lease -> on_release); if (lease -> on_release) diff --git a/server/omapi.c b/server/omapi.c index 557f97ad8..4d227c87d 100644 --- a/server/omapi.c +++ b/server/omapi.c @@ -50,7 +50,7 @@ #ifndef lint static char copyright[] = -"$Id: omapi.c,v 1.40 2000/10/20 01:01:41 neild Exp $ Copyright (c) 1999-2000 The Internet Software Consortium. All rights reserved.\n"; +"$Id: omapi.c,v 1.41 2000/11/28 23:27:22 mellon Exp $ Copyright (c) 1999-2000 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -934,6 +934,7 @@ isc_result_t dhcp_host_get_value (omapi_object_t *h, omapi_object_t *id, if (host -> fixed_addr && evaluate_option_cache (&ip_addrs, (struct packet *)0, (struct lease *)0, + (struct client_state *)0, (struct option_state *)0, (struct option_state *)0, &global_scope, @@ -1067,6 +1068,7 @@ isc_result_t dhcp_host_stuff_values (omapi_object_t *c, if (host -> fixed_addr && evaluate_option_cache (&ip_addrs, (struct packet *)0, (struct lease *)0, + (struct client_state *)0, (struct option_state *)0, (struct option_state *)0, &global_scope, diff --git a/server/stables.c b/server/stables.c index 8b0031372..4d8f894b1 100644 --- a/server/stables.c +++ b/server/stables.c @@ -43,7 +43,7 @@ #ifndef lint static char copyright[] = -"$Id: stables.c,v 1.18 2000/10/10 23:09:17 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n"; +"$Id: stables.c,v 1.19 2000/11/28 23:27:24 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -482,7 +482,7 @@ struct option server_options [256] = { { "remote-port", "S", &server_universe, 34 }, { "local-address", "I", &server_universe, 35 }, { "omapi-key", "t", &server_universe, 36 }, - { "option-37", "X", &server_universe, 37 }, + { "stash-agent-options", "f", &server_universe, 37 }, { "option-38", "X", &server_universe, 38 }, { "option-39", "X", &server_universe, 39 }, { "option-40", "X", &server_universe, 40 },