diff -rNc2 dhcp-3.0-alpha-19990330/Makefile.conf dhcp-3.0-alpha-19990408/Makefile.conf *** dhcp-3.0-alpha-19990330/Makefile.conf Fri Mar 26 11:22:13 1999 --- dhcp-3.0-alpha-19990408/Makefile.conf Thu Apr 8 10:44:17 1999 *************** *** 26,29 **** --- 26,30 ---- FFMANDIR = /usr/share/man/cat5 FFMANEXT = .0 + MANCAT = cat INSTALL = install -c -m 444 MANINSTALL = install -c *************** *** 182,185 **** --- 183,187 ---- #FFMANDIR = /usr/man/man5 #FFMANEXT = .5 + #MANCAT = #VARRUN = /var/run #VARDB = /var/state/dhcp *************** *** 195,198 **** --- 197,201 ---- #FFMANDIR = /usr/man/man5 #FFMANEXT = .5 + #MANCAT = #VARRUN = /var/run #VARDB = /var/state/dhcp *************** *** 208,211 **** --- 211,215 ---- #FFMANDIR = /usr/man/man5 #FFMANEXT = .5 + #MANCAT = #VARRUN = /var/run #VARDB = /var/state/dhcp *************** *** 221,224 **** --- 225,229 ---- #FFMANDIR = /usr/man/man5 #FFMANEXT = .5 + #MANCAT = #VARRUN = /var/run #VARDB = /var/dhcpd *************** *** 252,255 **** --- 257,261 ---- #FFMANDIR = /usr/man/man5 #FFMANEXT = .5 + #MANCAT = #VARRUN = /etc #COPTS=-w3 -Dlint *************** *** 281,282 **** --- 287,309 ---- #STRIP=/usr/local/i386-unknown-cygwin32/bin/strip ##--cygwin32-- + + ## IRIX 6.x + ##--irix-- + #LIBS = -lbind + #LFLAGS=$(DEBUG) -L/usr/local/lib -Wl,-woff,84 -Wl,-woff,85 -Wl,-woff,134 + #CC=gcc + #COPTS = -I/usr/local/include + #CF = cf/irix.h + #BINDIR = /usr/local/etc + #ADMMANDIR = /usr/local/man/man8 + #ADMMANEXT = .8 + #FFMANDIR = /usr/local/man/man5 + #FFMANEXT = .5 + #MANCAT = + #INSTALL = install + #MANINSTALL = install + #CHMOD = chmod + #ETC = /etc + #VARRUN = /etc + #VARDB = /usr/local/etc/dhcp + ##--irix-- diff -rNc2 dhcp-3.0-alpha-19990330/README dhcp-3.0-alpha-19990408/README *** dhcp-3.0-alpha-19990330/README Tue Mar 30 07:46:04 1999 --- dhcp-3.0-alpha-19990408/README Thu Apr 8 12:47:54 1999 *************** *** 2,6 **** Dynamic Host Configuration Protocol Distribution Version 3, Alpha Snapshot ! March 30, 1998 This is an alpha test snapshot of Version 3 of the Internet Software --- 2,6 ---- Dynamic Host Configuration Protocol Distribution Version 3, Alpha Snapshot ! April 8, 1999 This is an alpha test snapshot of Version 3 of the Internet Software *************** *** 57,68 **** In this release, the server and relay agent currently work well on ! NetBSD, Linux, FreeBSD, BSD/OS, Ultrix, Digital Alpha OSF/1, and SunOS ! 4.1.4. They can also be run usefully on Solaris as long as only one ! broadcast network interface is configured. They also runs on QNX as ! long as only one broadcast network interface is configured and a host ! route is added from that interface to the 255.255.255.255 broadcast ! address. If you are running a Linux 2.0.30 or previous kernel, the ! DHCP daemons will only be able to operate on machines with a single ! network interface. The DHCP client currently only knows how to configure the network on --- 57,66 ---- In this release, the server and relay agent currently work well on ! NetBSD, Linux after kernel version 2.0.30, FreeBSD, BSD/OS, Ultrix, ! Digital Alpha OSF/1, Solaris and SunOS 4.1.4. They run on AIX, HPUX, ! IRIX and Linux 2.0.30 and earlier kernels but support only a single ! broadcast network interface. They also runs on QNX as long as only ! one broadcast network interface is configured and a host route is ! added from that interface to the 255.255.255.255 broadcast address. The DHCP client currently only knows how to configure the network on *************** *** 92,98 **** the tar utility and the gzip command - type something like: ! zcat dhcp-3.0-alpha-19990330.tar.gz |tar xvf - ! Now, cd to the dhcp-3.0-alpha-19990330 subdirectory that you've just created and configure the source tree by typing: --- 90,99 ---- the tar utility and the gzip command - type something like: ! zcat dhcp-3.0-alpha-19990408.tar.gz |tar xvf - ! On BSD/OS, you have to type gzcat, not zcat, and you may run into ! similar problems on other operating systems. ! ! Now, cd to the dhcp-3.0-alpha-19990408 subdirectory that you've just created and configure the source tree by typing: diff -rNc2 dhcp-3.0-alpha-19990330/RELNOTES dhcp-3.0-alpha-19990408/RELNOTES *** dhcp-3.0-alpha-19990330/RELNOTES Tue Mar 30 13:52:52 1999 --- dhcp-3.0-alpha-19990408/RELNOTES Thu Apr 8 13:58:49 1999 *************** *** 2,6 **** Dynamic Host Configuration Protocol Distribution Version 3, Alpha Snapshot ! March 30, 1999 Release Notes --- 2,6 ---- Dynamic Host Configuration Protocol Distribution Version 3, Alpha Snapshot ! April 8, 1999 Release Notes *************** *** 55,58 **** --- 55,94 ---- when you try to use it. Pointing out inconsistencies between the documentation and the source code will always be appreciated. + + Changes since March 30, 1999 + + - Install unformatted manual pages on Linux + + - SGI Irix support + + - Generalize option support and add parser support for defining new + option spaces. + + - Support for generating vendor-encapsulated-options option from + user-specified option space, rather than having to encode it as + hex. + + - Fix hash table code to do the right thing with nul-terminated + strings - before they'd all get hashed into the same bucket. + + - Fix a parser bug caused by dereferencing an uninitialized variable + that prevented the parser from working correctly on some systems but + allowed it to work on others. + + - Document how to define new options, as well as how to set up + vendor-encapsulated-options option. + + - When responding to bootp clients, use the subnet mask from the + subnet declaration as we do for DHCP clients if no explicit subnet + mask option was defined. + + - Add always-send-rfc1048 option to force the server to send + rfc1048-style options (what everybody uses now) even if the client + doesn't send the right magic cookie. + + - Fix some bugs in class support that became obvious when I tried to + use the vendor-encapsulated-option support in a reasonable way. + + - Fix some memory leaks. Changes since March 29, 1999 (second snapshot) diff -rNc2 dhcp-3.0-alpha-19990330/client/Makefile.dist dhcp-3.0-alpha-19990408/client/Makefile.dist *** dhcp-3.0-alpha-19990330/client/Makefile.dist Mon Mar 15 21:50:29 1999 --- dhcp-3.0-alpha-19990408/client/Makefile.dist Thu Apr 8 13:53:32 1999 *************** *** 52,60 **** $(CHMOD) 700 $(DESTDIR)$(ETC)/dhclient-script; \ fi ! $(MANINSTALL) $(MANFROM) dhclient.cat8 $(MANTO) \ $(DESTDIR)$(ADMMANDIR)/dhclient$(ADMMANEXT) ! $(MANINSTALL) $(MANFROM) dhclient-script.cat8 $(MANTO) \ $(DESTDIR)$(ADMMANDIR)/dhclient-script$(ADMMANEXT) ! $(MANINSTALL) $(MANFROM) dhclient.conf.cat5 $(MANTO) \ $(DESTDIR)$(FFMANDIR)/dhclient.conf$(FFMANEXT) $(MANINSTALL) $(MANFROM) dhclient.leases.cat5 $(MANTO) \ --- 52,60 ---- $(CHMOD) 700 $(DESTDIR)$(ETC)/dhclient-script; \ fi ! $(MANINSTALL) $(MANFROM) dhclient.$(MANCAT)8 $(MANTO) \ $(DESTDIR)$(ADMMANDIR)/dhclient$(ADMMANEXT) ! $(MANINSTALL) $(MANFROM) dhclient-script.$(MANCAT)8 $(MANTO) \ $(DESTDIR)$(ADMMANDIR)/dhclient-script$(ADMMANEXT) ! $(MANINSTALL) $(MANFROM) dhclient.conf.$(MANCAT)5 $(MANTO) \ $(DESTDIR)$(FFMANDIR)/dhclient.conf$(FFMANEXT) $(MANINSTALL) $(MANFROM) dhclient.leases.cat5 $(MANTO) \ diff -rNc2 dhcp-3.0-alpha-19990330/client/clparse.c dhcp-3.0-alpha-19990408/client/clparse.c *** dhcp-3.0-alpha-19990330/client/clparse.c Fri Mar 26 11:19:43 1999 --- dhcp-3.0-alpha-19990408/client/clparse.c Mon Apr 5 08:08:13 1999 *************** *** 23,27 **** #ifndef lint static char copyright[] = ! "$Id: clparse.c,v 1.30 1999/03/26 19:19:43 mellon Exp $ Copyright (c) 1997 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ --- 23,27 ---- #ifndef lint static char copyright[] = ! "$Id: clparse.c,v 1.31 1999/04/05 15:08:13 mellon Exp $ Copyright (c) 1997 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ *************** *** 293,296 **** --- 293,310 ---- case OPTION: token = next_token (&val, cfile); + + token = peek_token (&val, cfile); + if (token == SPACE) { + if (ip) { + parse_warn ("option space definitions %s", + " may not be scoped."); + skip_to_semi (cfile); + free_option (option, "parse_statement"); + break; + } + parse_option_space_decl (cfile); + return; + } + option = parse_option_name (cfile, 1); if (!option) *************** *** 715,718 **** --- 729,735 ---- memset (lease, 0, sizeof *lease); lease -> is_static = is_static; + if (!option_state_allocate (&lease -> options, + "parse_client_lease_statement")) + log_fatal ("no memory for lease options.\n"); do { *************** *** 904,910 **** oc = (struct option_cache *)0; if (parse_option_decl (&oc, cfile)) { ! /* XXX save_option here ought to account for the ! XXX correct option universe, but it doesn't. */ ! save_option (lease -> options.dhcp_hash, oc); option_cache_dereference (&oc, "parse_client_lease_declaration"); --- 921,926 ---- oc = (struct option_cache *)0; if (parse_option_decl (&oc, cfile)) { ! save_option (oc -> option -> universe, ! lease -> options, oc); option_cache_dereference (&oc, "parse_client_lease_declaration"); diff -rNc2 dhcp-3.0-alpha-19990330/client/dhclient.c dhcp-3.0-alpha-19990408/client/dhclient.c *** dhcp-3.0-alpha-19990330/client/dhclient.c Tue Mar 30 13:54:02 1999 --- dhcp-3.0-alpha-19990408/client/dhclient.c Thu Apr 8 12:47:55 1999 *************** *** 23,27 **** #ifndef lint static char ocopyright[] = ! "$Id: dhclient.c,v 1.69 1999/03/30 21:54:02 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ --- 23,27 ---- #ifndef lint static char ocopyright[] = ! "$Id: dhclient.c,v 1.72 1999/04/08 19:47:55 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ *************** *** 55,59 **** "Copyright 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium."; static char arr [] = "All rights reserved."; ! static char message [] = "Internet Software Consortium DHCP Client V3.0-alpha-990330"; static char contrib [] = "\nPlease contribute if you find this software useful."; static char url [] = "For info, please visit http://www.isc.org/dhcp-contrib.html\n"; --- 55,59 ---- "Copyright 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium."; static char arr [] = "All rights reserved."; ! static char message [] = "Internet Software Consortium DHCP Client V3.0-alpha-990408"; static char contrib [] = "\nPlease contribute if you find this software useful."; static char url [] = "For info, please visit http://www.isc.org/dhcp-contrib.html\n"; *************** *** 506,515 **** /* Figure out the lease time. */ ! oc = lookup_option (client -> new -> options.dhcp_hash, DHO_DHCP_LEASE_TIME); memset (&ds, 0, sizeof ds); if (oc && evaluate_option_cache (&ds, packet, ! &client -> new -> options, oc)) { if (ds.len > 3) client -> new -> expiry = getULong (ds.data); --- 506,515 ---- /* Figure out the lease time. */ ! oc = lookup_option (&dhcp_universe, client -> new -> options, DHO_DHCP_LEASE_TIME); memset (&ds, 0, sizeof ds); if (oc && evaluate_option_cache (&ds, packet, ! client -> new -> options, oc)) { if (ds.len > 3) client -> new -> expiry = getULong (ds.data); *************** *** 536,544 **** client -> new -> expiry = TIME_MAX; /* Take the server-provided renewal time if there is one. */ ! oc = lookup_option (client -> new -> options.dhcp_hash, DHO_DHCP_RENEWAL_TIME); if (oc && evaluate_option_cache (&ds, packet, ! &client -> new -> options, oc)) { if (ds.len > 3) client -> new -> renewal = getULong (ds.data); --- 536,544 ---- client -> new -> expiry = TIME_MAX; /* Take the server-provided renewal time if there is one. */ ! oc = lookup_option (&dhcp_universe, client -> new -> options, DHO_DHCP_RENEWAL_TIME); if (oc && evaluate_option_cache (&ds, packet, ! client -> new -> options, oc)) { if (ds.len > 3) client -> new -> renewal = getULong (ds.data); *************** *** 555,563 **** /* Same deal with the rebind time. */ ! oc = lookup_option (client -> new -> options.dhcp_hash, DHO_DHCP_REBINDING_TIME); if (oc && evaluate_option_cache (&ds, packet, ! &client -> new -> options, oc)) { if (ds.len > 3) client -> new -> rebind = getULong (ds.data); --- 555,563 ---- /* Same deal with the rebind time. */ ! oc = lookup_option (&dhcp_universe, client -> new -> options, DHO_DHCP_REBINDING_TIME); if (oc && evaluate_option_cache (&ds, packet, ! client -> new -> options, oc)) { if (ds.len > 3) client -> new -> rebind = getULong (ds.data); *************** *** 663,671 **** memset (&ds, 0, sizeof ds); ! oc = lookup_option (client -> active -> options.dhcp_hash, DHO_DHCP_SERVER_IDENTIFIER); if (oc && evaluate_option_cache (&ds, (struct packet *)0, ! &client -> active -> options, oc)) { if (ds.len > 3) { memcpy (client -> destination.iabuf, ds.data, 4); --- 663,671 ---- memset (&ds, 0, sizeof ds); ! oc = lookup_option (&dhcp_universe, client -> active -> options, DHO_DHCP_SERVER_IDENTIFIER); if (oc && evaluate_option_cache (&ds, (struct packet *)0, ! client -> active -> options, oc)) { if (ds.len > 3) { memcpy (client -> destination.iabuf, ds.data, 4); *************** *** 805,809 **** for (i = 0; client -> config -> required_options [i]; i++) { if (!lookup_option ! (packet -> options.dhcp_hash, client -> config -> required_options [i])) { log_info ("%s isn't satisfactory.", name); --- 805,809 ---- for (i = 0; client -> config -> required_options [i]; i++) { if (!lookup_option ! (&dhcp_universe, packet -> options, client -> config -> required_options [i])) { log_info ("%s isn't satisfactory.", name); *************** *** 894,899 **** /* Copy the lease options. */ ! lease -> options = packet -> options; ! memset (&packet -> options, 0, sizeof packet -> options); lease -> address.len = sizeof (packet -> raw -> yiaddr); --- 894,899 ---- /* Copy the lease options. */ ! option_state_reference (&lease -> options, ! packet -> options, "packet_to_lease"); lease -> address.len = sizeof (packet -> raw -> yiaddr); *************** *** 902,910 **** /* Figure out the overload flag. */ ! oc = lookup_option (lease -> options.dhcp_hash, DHO_DHCP_OPTION_OVERLOAD); memset (&data, 0, sizeof data); if (oc && ! evaluate_option_cache (&data, packet, &lease -> options, oc)) { if (data.len > 0) i = data.data [0]; --- 902,910 ---- /* Figure out the overload flag. */ ! oc = lookup_option (&dhcp_universe, lease -> options, DHO_DHCP_OPTION_OVERLOAD); memset (&data, 0, sizeof data); if (oc && ! evaluate_option_cache (&data, packet, lease -> options, oc)) { if (data.len > 0) i = data.data [0]; *************** *** 1408,1413 **** } ! void make_client_options (client, lease, type, sid, rip, prl, ! options) struct client_state *client; struct client_lease *lease; --- 1408,1412 ---- } ! void make_client_options (client, lease, type, sid, rip, prl, op) struct client_state *client; struct client_lease *lease; *************** *** 1416,1420 **** struct iaddr *rip; u_int32_t *prl; ! struct option_state *options; { int i; --- 1415,1419 ---- struct iaddr *rip; u_int32_t *prl; ! struct option_state **op; { int i; *************** *** 1422,1430 **** struct buffer *bp = (struct buffer *)0; ! memset (options, 0, sizeof *options); /* Send the server identifier if provided. */ if (sid) ! save_option (options -> dhcp_hash, sid); oc = (struct option_cache *)0; --- 1421,1430 ---- struct buffer *bp = (struct buffer *)0; ! /* Allocate space for options. */ ! option_state_allocate (op, "make_client_options"); /* Send the server identifier if provided. */ if (sid) ! save_option (&dhcp_universe, *op, sid); oc = (struct option_cache *)0; *************** *** 1438,1444 **** &dhcp_options [DHO_DHCP_REQUESTED_ADDRESS], "make_client_options"))) ! log_error ("can't make requested address option cache."); else { ! save_option (options -> dhcp_hash, oc); option_cache_dereference (&oc, "make_client_options"); } --- 1438,1444 ---- &dhcp_options [DHO_DHCP_REQUESTED_ADDRESS], "make_client_options"))) ! log_error ("can't make requested address cache."); else { ! save_option (&dhcp_universe, *op, oc); option_cache_dereference (&oc, "make_client_options"); } *************** *** 1453,1457 **** log_error ("can't make message type."); else { ! save_option (options -> dhcp_hash, oc); option_cache_dereference (&oc, "make_client_options"); } --- 1453,1457 ---- log_error ("can't make message type."); else { ! save_option (&dhcp_universe, *op, oc); option_cache_dereference (&oc, "make_client_options"); } *************** *** 1462,1466 **** ; if (!buffer_allocate (&bp, i, "make_client_options")) ! log_error ("can't make buffer for parameter request list."); else { for (i = 0; prl [i]; i++) --- 1462,1466 ---- ; if (!buffer_allocate (&bp, i, "make_client_options")) ! log_error ("can't make parameter list buffer."); else { for (i = 0; prl [i]; i++) *************** *** 1472,1476 **** log_error ("can't make option cache"); else { ! save_option (options -> dhcp_hash, oc); option_cache_dereference (&oc, "make_client_options"); --- 1472,1476 ---- log_error ("can't make option cache"); else { ! save_option (&dhcp_universe, *op, oc); option_cache_dereference (&oc, "make_client_options"); *************** *** 1482,1486 **** if (client -> config -> on_transmission) execute_statements_in_scope ! ((struct packet *)0, &lease -> options, options, client -> config -> on_transmission, (struct group *)0); --- 1482,1488 ---- if (client -> config -> on_transmission) execute_statements_in_scope ! ((struct packet *)0, (lease ! ? lease -> options ! : (struct option_state *)0), *op, client -> config -> on_transmission, (struct group *)0); *************** *** 1494,1498 **** unsigned char discover = DHCPDISCOVER; int i; ! struct option_state options; memset (&client -> packet, 0, sizeof (client -> packet)); --- 1496,1500 ---- unsigned char discover = DHCPDISCOVER; int i; ! struct option_state *options = (struct option_state *)0; memset (&client -> packet, 0, sizeof (client -> packet)); *************** *** 1507,1512 **** client -> packet_length = cons_options ((struct packet *)0, &client -> packet, 0, ! &options, (struct agent_options *)0, ! 0, 0, 0, (struct data_string *)0); if (client -> packet_length < BOOTP_MIN_LEN) client -> packet_length = BOOTP_MIN_LEN; --- 1509,1513 ---- client -> packet_length = cons_options ((struct packet *)0, &client -> packet, 0, ! options, 0, 0, 0, (struct data_string *)0); if (client -> packet_length < BOOTP_MIN_LEN) client -> packet_length = BOOTP_MIN_LEN; *************** *** 1552,1556 **** unsigned char *tmp, *digest; unsigned char *old_digest_loc; ! struct option_state options; struct option_cache *oc; --- 1553,1557 ---- unsigned char *tmp, *digest; unsigned char *old_digest_loc; ! struct option_state *options = (struct option_state *)0; struct option_cache *oc; *************** *** 1558,1562 **** if (client -> state == S_REQUESTING) ! oc = lookup_option (lease -> options.dhcp_hash, DHO_DHCP_SERVER_IDENTIFIER); else --- 1559,1563 ---- if (client -> state == S_REQUESTING) ! oc = lookup_option (&dhcp_universe, lease -> options, DHO_DHCP_SERVER_IDENTIFIER); else *************** *** 1574,1579 **** client -> packet_length = cons_options ((struct packet *)0, &client -> packet, 0, ! &options, (struct agent_options *)0, ! 0, 0, 0, (struct data_string *)0); if (client -> packet_length < BOOTP_MIN_LEN) client -> packet_length = BOOTP_MIN_LEN; --- 1575,1579 ---- client -> packet_length = cons_options ((struct packet *)0, &client -> packet, 0, ! options, 0, 0, 0, (struct data_string *)0); if (client -> packet_length < BOOTP_MIN_LEN) client -> packet_length = BOOTP_MIN_LEN; *************** *** 1627,1647 **** struct option_cache *oc; ! struct option_state options; ! memset (&client -> packet, 0, sizeof (client -> packet)); ! ! oc = lookup_option (lease -> options.dhcp_hash, DHO_DHCP_SERVER_IDENTIFIER); make_client_options (client, lease, &decline, oc, ! &lease -> address, (u_int32_t *)0, ! &options); /* Set up the option buffer... */ client -> packet_length = cons_options ((struct packet *)0, &client -> packet, 0, ! &options, (struct agent_options *)0, ! 0, 0, 0, (struct data_string *)0); if (client -> packet_length < BOOTP_MIN_LEN) client -> packet_length = BOOTP_MIN_LEN; client -> packet.op = BOOTREQUEST; --- 1627,1645 ---- struct option_cache *oc; ! struct option_state *options = (struct option_state *)0; ! oc = lookup_option (&dhcp_universe, lease -> options, DHO_DHCP_SERVER_IDENTIFIER); make_client_options (client, lease, &decline, oc, ! &lease -> address, (u_int32_t *)0, &options); /* Set up the option buffer... */ + memset (&client -> packet, 0, sizeof (client -> packet)); client -> packet_length = cons_options ((struct packet *)0, &client -> packet, 0, ! options, 0, 0, 0, (struct data_string *)0); if (client -> packet_length < BOOTP_MIN_LEN) client -> packet_length = BOOTP_MIN_LEN; + option_state_dereference (&options, "make_decline"); client -> packet.op = BOOTREQUEST; *************** *** 1683,1691 **** struct option_cache *oc; ! struct option_state options; memset (&client -> packet, 0, sizeof (client -> packet)); ! oc = lookup_option (lease -> options.dhcp_hash, DHO_DHCP_SERVER_IDENTIFIER); make_client_options (client, lease, &request, oc, --- 1681,1689 ---- struct option_cache *oc; ! struct option_state *options = (struct option_state *)0; memset (&client -> packet, 0, sizeof (client -> packet)); ! oc = lookup_option (&dhcp_universe, lease -> options, DHO_DHCP_SERVER_IDENTIFIER); make_client_options (client, lease, &request, oc, *************** *** 1696,1703 **** client -> packet_length = cons_options ((struct packet *)0, &client -> packet, 0, ! &options, (struct agent_options *)0, ! 0, 0, 0, (struct data_string *)0); if (client -> packet_length < BOOTP_MIN_LEN) client -> packet_length = BOOTP_MIN_LEN; client -> packet.op = BOOTREQUEST; --- 1694,1701 ---- client -> packet_length = cons_options ((struct packet *)0, &client -> packet, 0, ! options, 0, 0, 0, (struct data_string *)0); if (client -> packet_length < BOOTP_MIN_LEN) client -> packet_length = BOOTP_MIN_LEN; + option_state_dereference (&options, "make_decline"); client -> packet.op = BOOTREQUEST; *************** *** 1736,1740 **** if (lease -> filename) dfree (lease -> filename, "destroy_client_lease"); ! option_state_dereference (&lease -> options); free_client_lease (lease, "destroy_client_lease"); } --- 1734,1738 ---- if (lease -> filename) dfree (lease -> filename, "destroy_client_lease"); ! option_state_dereference (&lease -> options, "destroy_client_lease"); free_client_lease (lease, "destroy_client_lease"); } *************** *** 1792,1795 **** --- 1790,1794 ---- struct option_cache *oc; struct data_string ds; + pair *hash; if (!rewrite) { *************** *** 1831,1840 **** memset (&ds, 0, sizeof ds); for (i = 0; i < OPTION_HASH_SIZE; i++) { pair p; ! for (p = lease -> options.dhcp_hash [i]; p; p = p -> cdr) { oc = (struct option_cache *)p -> car; if (evaluate_option_cache (&ds, (struct packet *)0, ! &lease -> options, oc)) { fprintf (leaseFile, " option %s %s;\n", --- 1830,1842 ---- memset (&ds, 0, sizeof ds); + + hash = lease -> options -> universes [dhcp_universe.index]; for (i = 0; i < OPTION_HASH_SIZE; i++) { pair p; ! /* XXX save _all_ options! XXX */ ! for (p = hash [i]; p; p = p -> cdr) { oc = (struct option_cache *)p -> car; if (evaluate_option_cache (&ds, (struct packet *)0, ! lease -> options, oc)) { fprintf (leaseFile, " option %s %s;\n", *************** *** 1932,1935 **** --- 1934,1938 ---- struct data_string data; struct option_cache *oc; + pair *hash; fprintf (scriptFile, "%sip_address=\"%s\"\n", *************** *** 1945,1951 **** memset (&data, 0, sizeof data); ! oc = lookup_option (lease -> options.dhcp_hash, DHO_SUBNET_MASK); if (oc && evaluate_option_cache (&data, (struct packet *)0, ! &lease -> options, oc)) { if (data.len > 3) { struct iaddr netmask, subnet, broadcast; --- 1948,1954 ---- memset (&data, 0, sizeof data); ! oc = lookup_option (&dhcp_universe, lease -> options, DHO_SUBNET_MASK); if (oc && evaluate_option_cache (&data, (struct packet *)0, ! lease -> options, oc)) { if (data.len > 3) { struct iaddr netmask, subnet, broadcast; *************** *** 1963,1972 **** "export %snetwork_number\n", prefix); ! oc = lookup_option (lease -> options.dhcp_hash, DHO_BROADCAST_ADDRESS); if (!oc || !evaluate_option_cache (&data, (struct packet *)0, ! &lease -> options, oc)) { broadcast = broadcast_addr (subnet, --- 1966,1976 ---- "export %snetwork_number\n", prefix); ! oc = lookup_option (&dhcp_universe, ! lease -> options, DHO_BROADCAST_ADDRESS); if (!oc || !evaluate_option_cache (&data, (struct packet *)0, ! lease -> options, oc)) { broadcast = broadcast_addr (subnet, *************** *** 2000,2016 **** } ! execute_statements_in_scope ((struct packet *)0, &lease -> options, ! &lease -> options, client -> config -> on_receipt, (struct group *)0); for (i = 0; i < OPTION_HASH_SIZE; i++) { pair hp; ! for (hp = lease -> options.dhcp_hash [i]; hp; hp = hp -> cdr) { oc = (struct option_cache *)hp -> car; if (evaluate_option_cache (&data, (struct packet *)0, ! &lease -> options, oc)) { if (data.len) { --- 2004,2021 ---- } ! execute_statements_in_scope ((struct packet *)0, lease -> options, ! lease -> options, client -> config -> on_receipt, (struct group *)0); + hash = lease -> options -> universes [dhcp_universe.index]; for (i = 0; i < OPTION_HASH_SIZE; i++) { pair hp; ! for (hp = hash [i]; hp; hp = hp -> cdr) { oc = (struct option_cache *)hp -> car; if (evaluate_option_cache (&data, (struct packet *)0, ! lease -> options, oc)) { if (data.len) { diff -rNc2 dhcp-3.0-alpha-19990330/common/Makefile.dist dhcp-3.0-alpha-19990408/common/Makefile.dist *** dhcp-3.0-alpha-19990330/common/Makefile.dist Mon Mar 29 13:08:10 1999 --- dhcp-3.0-alpha-19990408/common/Makefile.dist Thu Apr 8 13:53:32 1999 *************** *** 51,56 **** done; \ done ! $(MANINSTALL) $(MANFROM) dhcp-options.cat5 $(MANTO) \ $(DESTDIR)$(FFMANDIR)/dhcp-options$(FFMANEXT) depend: --- 51,60 ---- done; \ done ! $(MANINSTALL) $(MANFROM) dhcp-options.$(MANCAT)5 $(MANTO) \ $(DESTDIR)$(FFMANDIR)/dhcp-options$(FFMANEXT) + $(MANINSTALL) $(MANFROM) dhcp-eval.$(MANCAT)5 $(MANTO) \ + $(DESTDIR)$(FFMANDIR)/dhcp-eval$(FFMANEXT) + $(MANINSTALL) $(MANFROM) dhcp-contrib.$(MANCAT)5 $(MANTO) \ + $(DESTDIR)$(FFMANDIR)/dhcp-contrib$(FFMANEXT) depend: diff -rNc2 dhcp-3.0-alpha-19990330/common/alloc.c dhcp-3.0-alpha-19990408/common/alloc.c *** dhcp-3.0-alpha-19990330/common/alloc.c Thu Mar 25 13:55:14 1999 --- dhcp-3.0-alpha-19990408/common/alloc.c Mon Apr 5 12:02:17 1999 *************** *** 23,27 **** #ifndef lint static char copyright[] = ! "$Id: alloc.c,v 1.26 1999/03/25 21:55:14 mellon Exp $ Copyright (c) 1995, 1996, 1998 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ --- 23,27 ---- #ifndef lint static char copyright[] = ! "$Id: alloc.c,v 1.28 1999/04/05 19:02:17 mellon Exp $ Copyright (c) 1995, 1996, 1998 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ *************** *** 159,164 **** --- 159,170 ---- } else { rval = dmalloc (sizeof (struct lease_state), name); + if (!rval) + return rval; } memset (rval, 0, sizeof *rval); + if (!option_state_allocate (&rval -> options, name)) { + free_lease_state (rval, name); + return (struct lease_state *)0; + } return rval; } *************** *** 209,212 **** --- 215,233 ---- } + struct universe *new_universe (name) + char *name; + { + struct universe *rval = + dmalloc (sizeof (struct universe), name); + return rval; + } + + void free_universe (ptr, name) + struct universe *ptr; + char *name; + { + dfree ((VOIDPTR)ptr, name); + } + void free_domain_search_list (ptr, name) struct domain_search_list *ptr; *************** *** 220,223 **** --- 241,245 ---- char *name; { + option_state_dereference (&ptr -> options, name); ptr -> next = free_lease_states; free_lease_states = ptr; *************** *** 523,527 **** { if (!ptr) { ! log_error ("Null pointer passed to buffer_reference: %s", name); abort (); } --- 545,550 ---- { if (!ptr) { ! log_error ("Null pointer passed to buffer_reference: %s", ! name); abort (); } *************** *** 542,546 **** if (!ptr || !*ptr) { ! log_error ("Null pointer passed to buffer_dereference: %s", name); abort (); } --- 565,570 ---- if (!ptr || !*ptr) { ! log_error ("Null pointer passed to buffer_dereference: %s", ! name); abort (); } *************** *** 575,584 **** { if (!ptr) { ! log_error ("Null pointer in dns_host_entry_reference: %s", name); abort (); } if (*ptr) { log_error ("Non-null pointer in dns_host_entry_reference (%s)", ! name); abort (); } --- 599,609 ---- { if (!ptr) { ! log_error ("Null pointer in dns_host_entry_reference: %s", ! name); abort (); } if (*ptr) { log_error ("Non-null pointer in dns_host_entry_reference (%s)", ! name); abort (); } *************** *** 595,599 **** if (!ptr || !*ptr) { ! log_error ("Null pointer in dns_host_entry_dereference: %s", name); abort (); } --- 620,625 ---- if (!ptr || !*ptr) { ! log_error ("Null pointer in dns_host_entry_dereference: %s", ! name); abort (); } *************** *** 603,606 **** --- 629,710 ---- dfree ((*ptr), name); *ptr = (struct dns_host_entry *)0; + return 1; + } + + int option_state_allocate (ptr, name) + struct option_state **ptr; + char *name; + { + int size; + + if (!ptr) { + log_error ("Null pointer passed to option_state_allocate: %s", + name); + abort (); + } + if (*ptr) { + log_error ("Non-null pointer in option_state_allocate (%s)", + name); + abort (); + } + + size = sizeof **ptr + (universe_count - 1) * sizeof (VOIDPTR); + *ptr = dmalloc (size, name); + if (*ptr) { + memset (*ptr, 0, size); + (*ptr) -> universe_count = universe_count; + (*ptr) -> refcnt = 1; + return 1; + } + return 0; + } + + int option_state_reference (ptr, bp, name) + struct option_state **ptr; + struct option_state *bp; + char *name; + { + if (!ptr) { + log_error ("Null pointer in option_state_reference: %s", + name); + abort (); + } + if (*ptr) { + log_error ("Non-null pointer in option_state_reference (%s)", + name); + abort (); + } + *ptr = bp; + bp -> refcnt++; + return 1; + } + + int option_state_dereference (ptr, name) + struct option_state **ptr; + char *name; + { + int i; + struct option_state *options; + + if (!ptr || !*ptr) { + log_error ("Null pointer in option_state_dereference: %s", + name); + abort (); + } + + options = *ptr; + *ptr = (struct option_state *)0; + --options -> refcnt; + if (options -> refcnt) + return 1; + + /* Loop through the per-universe state. */ + for (i = 0; i < options -> universe_count; i++) + if (options -> universes [i] && + universes [i] -> option_state_dereference) + ((*(universes [i] -> option_state_dereference)) + (universes [i], options)); + + dfree (options, name); return 1; } diff -rNc2 dhcp-3.0-alpha-19990330/common/conflex.c dhcp-3.0-alpha-19990408/common/conflex.c *** dhcp-3.0-alpha-19990330/common/conflex.c Thu Mar 25 13:56:28 1999 --- dhcp-3.0-alpha-19990408/common/conflex.c Thu Apr 8 10:46:15 1999 *************** *** 23,27 **** #ifndef lint static char copyright[] = ! "$Id: conflex.c,v 1.41 1999/03/25 21:56:28 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ --- 23,27 ---- #ifndef lint static char copyright[] = ! "$Id: conflex.c,v 1.43 1999/04/08 17:46:15 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ *************** *** 44,48 **** static int tlpos; static int tline; ! static int token; static int ugflag; static char *tval; --- 44,48 ---- static int tlpos; static int tline; ! static enum dhcp_token token; static int ugflag; static char *tval; *************** *** 56,65 **** static int get_char PROTO ((FILE *)); ! static int get_token PROTO ((FILE *)); static void skip_to_eol PROTO ((FILE *)); ! static int read_string PROTO ((FILE *)); ! static int read_number PROTO ((int, FILE *)); ! static int read_num_or_name PROTO ((int, FILE *)); ! static int intern PROTO ((char *, int)); void new_parse (name) --- 56,65 ---- static int get_char PROTO ((FILE *)); ! static enum dhcp_token get_token PROTO ((FILE *)); static void skip_to_eol PROTO ((FILE *)); ! static enum dhcp_token read_string PROTO ((FILE *)); ! static enum dhcp_token read_number PROTO ((int, FILE *)); ! static enum dhcp_token read_num_or_name PROTO ((int, FILE *)); ! static enum dhcp_token intern PROTO ((char *, enum dhcp_token)); void new_parse (name) *************** *** 103,111 **** } ! static int get_token (cfile) FILE *cfile; { int c; ! int ttok; static char tb [2]; int l, p, u; --- 103,111 ---- } ! static enum dhcp_token get_token (cfile) FILE *cfile; { int c; ! enum dhcp_token ttok; static char tb [2]; int l, p, u; *************** *** 162,166 **** } ! int next_token (rval, cfile) char **rval; FILE *cfile; --- 162,166 ---- } ! enum dhcp_token next_token (rval, cfile) char **rval; FILE *cfile; *************** *** 187,191 **** } ! int peek_token (rval, cfile) char **rval; FILE *cfile; --- 187,191 ---- } ! enum dhcp_token peek_token (rval, cfile) char **rval; FILE *cfile; *************** *** 228,232 **** } ! static int read_string (cfile) FILE *cfile; { --- 228,232 ---- } ! static enum dhcp_token read_string (cfile) FILE *cfile; { *************** *** 262,266 **** } ! static int read_number (c, cfile) int c; FILE *cfile; --- 262,266 ---- } ! static enum dhcp_token read_number (c, cfile) int c; FILE *cfile; *************** *** 298,307 **** } ! static int read_num_or_name (c, cfile) int c; FILE *cfile; { int i = 0; ! int rv = NUMBER_OR_NAME; tokbuf [i++] = c; for (; i < sizeof tokbuf; i++) { --- 298,307 ---- } ! static enum dhcp_token read_num_or_name (c, cfile) int c; FILE *cfile; { int i = 0; ! enum dhcp_token rv = NUMBER_OR_NAME; tokbuf [i++] = c; for (; i < sizeof tokbuf; i++) { *************** *** 326,332 **** } ! static int intern (atom, dfv) char *atom; ! int dfv; { if (!isascii (atom [0])) --- 326,332 ---- } ! static enum dhcp_token intern (atom, dfv) char *atom; ! enum dhcp_token dfv; { if (!isascii (atom [0])) *************** *** 637,640 **** --- 637,642 ---- if (!strcasecmp (atom + 1, "pawn")) return SPAWN; + if (!strcasecmp (atom + 1, "pace")) + return SPACE; break; case 't': diff -rNc2 dhcp-3.0-alpha-19990330/common/convert.c dhcp-3.0-alpha-19990408/common/convert.c *** dhcp-3.0-alpha-19990330/common/convert.c Mon Mar 15 21:50:32 1999 --- dhcp-3.0-alpha-19990408/common/convert.c Mon Apr 5 08:33:52 1999 *************** *** 24,28 **** #ifndef lint static char copyright[] = ! "$Id: convert.c,v 1.6 1999/03/16 05:50:32 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ --- 24,28 ---- #ifndef lint static char copyright[] = ! "$Id: convert.c,v 1.7 1999/04/05 15:33:52 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ *************** *** 47,51 **** } ! u_int16_t getUShort (buf) unsigned char *buf; { --- 47,51 ---- } ! u_int32_t getUShort (buf) unsigned char *buf; { *************** *** 56,60 **** } ! int16_t getShort (buf) unsigned char *buf; { --- 56,60 ---- } ! int32_t getShort (buf) unsigned char *buf; { *************** *** 97,98 **** --- 97,110 ---- } + void putUChar (obuf, val) + unsigned char *obuf; + u_int32_t val; + { + *obuf = val; + } + + u_int32_t getUChar (obuf) + unsigned char *obuf; + { + return obuf [0]; + } diff -rNc2 dhcp-3.0-alpha-19990330/common/dhcp-options.5 dhcp-3.0-alpha-19990408/common/dhcp-options.5 *** dhcp-3.0-alpha-19990330/common/dhcp-options.5 Mon Mar 15 21:50:32 1999 --- dhcp-3.0-alpha-19990408/common/dhcp-options.5 Thu Apr 8 12:14:12 1999 *************** *** 84,90 **** .nf .sp 1 ! option client-identifier "CLIENT-FOO"; or ! option client-identifier 43:4c:49:45:54:2d:46:4f:4f; .fi .PP --- 84,90 ---- .nf .sp 1 ! option dhcp-client-identifier "CLIENT-FOO"; or ! option dhcp-client-identifier 43:4c:49:45:54:2d:46:4f:4f; .fi .PP *************** *** 563,566 **** --- 563,567 ---- useful to specify these options to be sent, nor is it useful to reference them at all in the client. + .PP .B option \fBagent.circuit-id\fR \fIdata-string\fR\fB;\fR .RS 0.25i *************** *** 575,579 **** .RE .PP ! .B option \fBagent.circuit-id\fR \fIdata-string\fR\fB;\fR .RS 0.25i .PP --- 576,580 ---- .RE .PP ! .B option \fBagent.remote-id\fR \fIdata-string\fR\fB;\fR .RS 0.25i .PP *************** *** 585,588 **** --- 586,775 ---- administratively guaranteed to be unique to a particular remote end of a circuit. + .SH DEFINING NEW OPTIONS + The Internet Software Consortium DHCP client and server provide the + capability to define new options. Each DHCP option has a name, a + code, and a structure. The name is used by you to refer to the + option. The code is a number, used by the DHCP server and client to + refer to an option. The structure describes what the contents of an + option looks like. + .PP + To define a new option, you need to choose a name for it that is not + in use for some other option - for example, you can't use "host-name" + because the DHCP protocol already defines a host-name option, which is + documented earlier in this manual page. If an option name doesn't + appear in this manual page, you can use it, but it's probably a good + idea to put some kind of unique string at the beginning so you can be + sure that future options don't take your name. For example, you + might define an option, "local-host-name", feeling some confidence + that no official DHCP option name will ever start with "local". + .PP + Once you have chosen a name, you must choose a code. For site-local + options, all codes between 128 and 254 are reserved for DHCP options, + so you can pick any one of these. In practice, some vendors have + interpreted the protocol rather loosely and have used option code + values greater than 128 themselves. There's no real way to avoid + this problem, but it's not likely to cause too much trouble in + practice. + .PP + The structure of an option is simply the format in which the option + data appears. The ISC DHCP server currently supports a few simple + types, like integers, booleans, strings and IP addresses, and it also + supports the ability to define arrays of single types or arrays of + fixed sequences of types. + .PP + New options are declared as follows: + .PP + .B option + .I new-name + .B code + .I new-code + .B = + .I definition + .B ; + .PP + The values of + .I new-name + and + .I new-code + should be the name you have chosen for the new option and the code you + have chosen. The + .I definition + should be the definition of the structure of the option. + .PP + The following simple option type definitions are supported: + .PP + .B BOOLEAN + .PP + .B option + .I new-name + .B code + .I new-code + .B = + .B boolean + .B ; + .PP + An option of type boolean is a flag with a value of either on or off + (or true or false). So an example use of the boolean type would be: + .nf + + option use-zephyr code 180 = boolean; + option use-zephyr on; + + .fi + .B INTEGER + .PP + .B option + .I new-name + .B code + .I new-code + .B = + .I sign + .B integer + .I width + .B ; + .PP + The \fIsign\fR token should either be blank, \fIunsigned\fR + or \fIsigned\fR. The width can be either 8, 16 or 32, and refers to + the number of bits in the integer. So for example, the following two + lines show a definition of the sql-connection-max option and its use: + .nf + + option sql-connection-max code 192 = unsigned integer 16; + option sql-connection-max 1536; + + .fi + .B IP-ADDRESS + .PP + .B option + .I new-name + .B code + .I new-code + .B = + .B ip-address + .B ; + .PP + An option whose structure is an IP address can be expressed either as + a domain name or as a dotted quad. So the following is an example use + of the ip-address type: + .nf + + option sql-server-address code 193 = ip-address; + option sql-server-address sql.example.com; + + .fi + .PP + .B TEXT + .PP + .B option + .I new-name + .B code + .I new-code + .B = + .B text + .B ; + .PP + An option whose type is text will encode an ASCII text string. For + example: + .nf + + option sql-default-connection-name code 194 = text; + option sql-default-connection-name "PRODZA"; + + .fi + .PP + .B DATA STRING + .PP + .B option + .I new-name + .B code + .I new-code + .B = + .B string + .B ; + .PP + An option whose type is a data string is essentially just a collection + of bytes, and can be specified either as quoted text, like the text + type, or as a list of hexadecimal contents seperated by colons whose + values must be between 0 and FF. For example: + .nf + + option sql-identification-token code 195 = string; + option sql-identification-token 17:23:19:a6:42:ea:99:7c:22; + + .fi + .PP + .B ARRAYS + .PP + Options can contain arrays of any of the above types except for the + text and data string types, which aren't currently supported in + arrays. An example of an array definition is as follows: + .nf + + option kerberos-servers code 200 = array of ip-address; + option kerberos-servers 10.20.10.1, 10.20.11.1; + + .fi + .B RECORDS + .PP + Options can also contain data structures consisting of a sequence of + data types, which is sometimes called a record type. For example: + .nf + + option contrived-001 code 201 = { boolean, integer 32, text }; + option contrived-001 on 1772 "contrivance"; + + .fi + It's also possible to have options that are arrays of records, for + example: + .nf + + option new-static-routes code 201 = array of { + ip-address, ip-address, ip-address, integer 8 }; + option static-routes + 10.0.0.0 255.255.255.0 net-0-rtr.example.com 1, + 10.0.1.0 255.255.255.0 net-1-rtr.example.com 1, + 10.2.0.0 255.255.224.0 net-2-0-rtr.example.com 3; + + .fi .SH SEE ALSO dhcpd.conf(5), dhcpd.leases(5), dhclient.conf(5), dhcp-eval(5), dhcpd(8), diff -rNc2 dhcp-3.0-alpha-19990330/common/execute.c dhcp-3.0-alpha-19990408/common/execute.c *** dhcp-3.0-alpha-19990330/common/execute.c Mon Mar 15 21:50:34 1999 --- dhcp-3.0-alpha-19990408/common/execute.c Mon Apr 5 08:35:54 1999 *************** *** 23,27 **** #ifndef lint static char copyright[] = ! "$Id: execute.c,v 1.8 1999/03/16 05:50:34 mellon Exp $ Copyright (c) 1998, 1999 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ --- 23,27 ---- #ifndef lint static char copyright[] = ! "$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"; #endif /* not lint */ *************** *** 117,124 **** #endif if (r -> data.option -> option -> universe -> set_func) ! (r -> data.option -> option -> ! universe -> set_func) (out_options, ! r -> data.option, ! r -> op); break; --- 117,125 ---- #endif if (r -> data.option -> option -> universe -> set_func) ! ((r -> data.option -> option -> ! universe -> set_func) ! (r -> data.option -> option -> universe, ! out_options, ! r -> data.option, r -> op)); break; diff -rNc2 dhcp-3.0-alpha-19990330/common/hash.c dhcp-3.0-alpha-19990408/common/hash.c *** dhcp-3.0-alpha-19990330/common/hash.c Mon Mar 15 21:50:34 1999 --- dhcp-3.0-alpha-19990408/common/hash.c Mon Apr 5 12:02:42 1999 *************** *** 23,27 **** #ifndef lint static char copyright[] = ! "$Id: hash.c,v 1.12 1999/03/16 05:50:34 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ --- 23,27 ---- #ifndef lint static char copyright[] = ! "$Id: hash.c,v 1.13 1999/04/05 19:02:42 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ *************** *** 82,85 **** --- 82,88 ---- return; + if (!len) + len = strlen (name); + hashno = do_hash (name, len, table -> hash_count); bp = new_hash_bucket ("add_hash"); *************** *** 107,110 **** --- 110,116 ---- return; + if (!len) + len = strlen (name); + hashno = do_hash (name, len, table -> hash_count); *************** *** 138,154 **** if (!table) return (unsigned char *)0; hashno = do_hash (name, len, table -> hash_count); ! if (len) { ! for (bp = table -> buckets [hashno]; bp; bp = bp -> next) { ! if (len == bp -> len ! && !memcmp (bp -> name, name, len)) ! return bp -> value; ! } ! } else { ! for (bp = table -> buckets [hashno]; bp; bp = bp -> next) ! if (!strcmp ((char *)bp -> name, ! (char *)name)) ! return bp -> value; } return (unsigned char *)0; --- 144,156 ---- if (!table) return (unsigned char *)0; + if (!len) + len = strlen (name); + hashno = do_hash (name, len, table -> hash_count); ! for (bp = table -> buckets [hashno]; bp; bp = bp -> next) { ! if (len == bp -> len ! && !memcmp (bp -> name, name, len)) ! return bp -> value; } return (unsigned char *)0; diff -rNc2 dhcp-3.0-alpha-19990330/common/options.c dhcp-3.0-alpha-19990408/common/options.c *** dhcp-3.0-alpha-19990330/common/options.c Mon Mar 15 21:50:35 1999 --- dhcp-3.0-alpha-19990408/common/options.c Thu Apr 8 12:17:48 1999 *************** *** 23,27 **** #ifndef lint static char copyright[] = ! "$Id: options.c,v 1.37 1999/03/16 05:50:35 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ --- 23,27 ---- #ifndef lint static char copyright[] = ! "$Id: options.c,v 1.40 1999/04/08 19:17:48 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ *************** *** 41,46 **** struct option_cache *op = (struct option_cache *)0; ! /* Initially, zero all option pointers. */ ! memset (&packet -> options, 0, sizeof (packet -> options)); /* If we don't see the magic cookie, there's nothing to parse. */ --- 41,49 ---- struct option_cache *op = (struct option_cache *)0; ! /* Allocate a new option state. */ ! if (!option_state_allocate (&packet -> options, "parse_options")) { ! packet -> options_valid = 0; ! return 0; ! } /* If we don't see the magic cookie, there's nothing to parse. */ *************** *** 60,64 **** options out of the buffer(s) containing them. */ if (packet -> options_valid && ! (op = lookup_option (packet -> options.dhcp_hash, DHO_DHCP_OPTION_OVERLOAD))) { if (op -> data.data [0] & 1) { --- 63,67 ---- options out of the buffer(s) containing them. */ if (packet -> options_valid && ! (op = lookup_option (&dhcp_universe, packet -> options, DHO_DHCP_OPTION_OVERLOAD))) { if (op -> data.data [0] & 1) { *************** *** 96,100 **** if (!buffer_allocate (&bp, length, "parse_option_buffer")) { ! log_error ("parse_option_buffer: no memory for option buffer."); return 0; } --- 99,103 ---- if (!buffer_allocate (&bp, length, "parse_option_buffer")) { ! log_error ("no memory for option buffer."); return 0; } *************** *** 115,121 **** /* If the length is outrageous, the options are bad. */ if (offset + len + 2 > length) { ! log_error ("Option %s length %d overflows input buffer.", ! dhcp_options [code].name, ! len); buffer_dereference (&bp, "parse_option_buffer"); return 0; --- 118,123 ---- /* If the length is outrageous, the options are bad. */ if (offset + len + 2 > length) { ! log_error ("Client option %s (%d) larger than buffer.", ! dhcp_options [code].name, len); buffer_dereference (&bp, "parse_option_buffer"); return 0; *************** *** 127,131 **** if (!parse_agent_information_option (packet, len, buffer + offset + 2)) { ! log_error ("malformed agent information option."); buffer_dereference (&bp, "parse_option_buffer"); --- 129,133 ---- if (!parse_agent_information_option (packet, len, buffer + offset + 2)) { ! log_error ("bad agent information option."); buffer_dereference (&bp, "parse_option_buffer"); *************** *** 135,140 **** if (!option_cache_allocate (&op, "parse_option_buffer")) { ! log_error ("Can't allocate storage for option %s.", ! dhcp_options [code].name); buffer_dereference (&bp, "parse_option_buffer"); --- 137,142 ---- if (!option_cache_allocate (&op, "parse_option_buffer")) { ! log_error ("No memory for option %s.", ! dhcp_options [code].name); buffer_dereference (&bp, "parse_option_buffer"); *************** *** 162,166 **** op -> option = &dhcp_options [code]; /* Now store the option. */ ! save_option (packet -> options.dhcp_hash, op); /* And let go of our reference. */ --- 164,168 ---- op -> option = &dhcp_options [code]; /* Now store the option. */ ! save_option (&dhcp_universe, packet -> options, op); /* And let go of our reference. */ *************** *** 197,201 **** "parse_agent_information_option"); if (!t) ! log_fatal ("can't allocate space for option tag data."); /* Link it in at the tail of the list. */ --- 199,203 ---- "parse_agent_information_option"); if (!t) ! log_fatal ("no memory for option tag data."); /* Link it in at the tail of the list. */ *************** *** 216,220 **** /* Find the tail of the list. */ ! for (tail = &packet -> options.agent_options; *tail; tail = &((*tail) -> next)) ; --- 218,223 ---- /* Find the tail of the list. */ ! for (tail = ((struct agent_options **) ! &packet -> options -> universes [agent_universe.index]); *tail; tail = &((*tail) -> next)) ; *************** *** 231,241 **** of vendor options using the same routine. */ ! int cons_options (inpacket, outpacket, mms, options, ! agent_options, overload, terminate, bootpp, prl) struct packet *inpacket; struct dhcp_packet *outpacket; int mms; struct option_state *options; - struct agent_options *agent_options; int overload; /* Overload flags that may be set. */ int terminate; --- 234,243 ---- of vendor options using the same routine. */ ! int cons_options (inpacket, outpacket, ! mms, options, overload, terminate, bootpp, prl) struct packet *inpacket; struct dhcp_packet *outpacket; int mms; struct option_state *options; int overload; /* Overload flags that may be set. */ int terminate; *************** *** 254,258 **** struct option_cache *op; struct data_string ds; ! pair pp; memset (&ds, 0, sizeof ds); --- 256,260 ---- struct option_cache *op; struct data_string ds; ! pair pp, *hash; memset (&ds, 0, sizeof ds); *************** *** 263,270 **** if (!mms && inpacket && ! (op = lookup_option (inpacket -> options.dhcp_hash, DHO_DHCP_MAX_MESSAGE_SIZE))) { evaluate_option_cache (&ds, inpacket, ! &inpacket -> options, op); if (ds.len >= sizeof (u_int16_t)) mms = getUShort (ds.data); --- 265,272 ---- if (!mms && inpacket && ! (op = lookup_option (&dhcp_universe, inpacket -> options, DHO_DHCP_MAX_MESSAGE_SIZE))) { evaluate_option_cache (&ds, inpacket, ! inpacket -> options, op); if (ds.len >= sizeof (u_int16_t)) mms = getUShort (ds.data); *************** *** 323,328 **** and any duplicates will be eliminated. */ for (i = 0; i < OPTION_HASH_SIZE; i++) { ! for (pp = options -> dhcp_hash [i]; ! pp; pp = pp -> cdr) { op = (struct option_cache *)(pp -> car); if (priority_len < PRIORITY_COUNT) --- 325,330 ---- and any duplicates will be eliminated. */ for (i = 0; i < OPTION_HASH_SIZE; i++) { ! hash = options -> universes [dhcp_universe.index]; ! for (pp = hash [i]; pp; pp = pp -> cdr) { op = (struct option_cache *)(pp -> car); if (priority_len < PRIORITY_COUNT) *************** *** 410,414 **** /* We tack any agent options onto the end of the packet after we've put it together. */ ! if (agent_options) { int len = 0; struct agent_options *a; --- 412,417 ---- /* We tack any agent options onto the end of the packet after we've put it together. */ ! if (options -> universe_count > agent_universe.index && ! options -> universes [agent_universe.index]) { int len = 0; struct agent_options *a; *************** *** 417,421 **** /* Cycle through the options, appending them to the buffer. */ ! for (a = options -> agent_options; a; a = a -> next) { if (agentix + a -> length + 3 + DHCP_FIXED_LEN <= dhcp_max_agent_option_packet_length) { --- 420,426 ---- /* Cycle through the options, appending them to the buffer. */ ! for (a = ((struct agent_options *) ! options -> universes [agent_universe.index]); ! a; a = a -> next) { if (agentix + a -> length + 3 + DHCP_FIXED_LEN <= dhcp_max_agent_option_packet_length) { *************** *** 492,502 **** /* If no data is available for this option, skip it. */ ! if (!(oc = lookup_option (options -> dhcp_hash, code))) { continue; } /* Find the value of the option... */ ! evaluate_option_cache (&od, (struct packet *)0, ! (struct option_state *)0, oc); if (!od.len) { continue; --- 497,506 ---- /* If no data is available for this option, skip it. */ ! if (!(oc = lookup_option (&dhcp_universe, options, code))) { continue; } /* Find the value of the option... */ ! evaluate_option_cache (&od, (struct packet *)0, options, oc); if (!od.len) { continue; *************** *** 596,600 **** for (i = 0; dhcp_options [code].format [i]; i++) { if (!numhunk) { ! log_error ("%s: Excess information in format string: %s\n", dhcp_options [code].name, &(dhcp_options [code].format [i])); --- 600,604 ---- for (i = 0; dhcp_options [code].format [i]; i++) { if (!numhunk) { ! log_error ("%s: Extra codes in format string: %s\n", dhcp_options [code].name, &(dhcp_options [code].format [i])); *************** *** 699,707 **** break; case 's': ! sprintf (op, "%d", getShort (dp)); dp += 2; break; case 'S': ! sprintf (op, "%d", getUShort (dp)); dp += 2; break; --- 703,711 ---- break; case 's': ! sprintf (op, "%d", (int)getShort (dp)); dp += 2; break; case 'S': ! sprintf (op, "%d", (unsigned)getUShort (dp)); dp += 2; break; *************** *** 719,723 **** break; default: ! log_error ("Unexpected format code %c", fmtbuf [j]); } op += strlen (op); --- 723,728 ---- break; default: ! log_error ("Unexpected format code %c", ! fmtbuf [j]); } op += strlen (op); *************** *** 754,771 **** if (packet -> hlen > sizeof packet -> chaddr) { ! log_info ("Discarding packet with bogus hardware address length."); return; } if (!parse_options (&tp)) { ! option_state_dereference (&tp.options); return; } if (tp.options_valid && ! (op = lookup_option (tp.options.dhcp_hash, DHO_DHCP_MESSAGE_TYPE))) { struct data_string dp; memset (&dp, 0, sizeof dp); ! evaluate_option_cache (&dp, &tp, &tp.options, op); if (dp.len > 0) tp.packet_type = dp.data [0]; --- 759,777 ---- if (packet -> hlen > sizeof packet -> chaddr) { ! log_info ("Discarding packet with bogus hlen."); return; } if (!parse_options (&tp)) { ! if (tp.options) ! option_state_dereference (&tp.options, "do_packet"); return; } if (tp.options_valid && ! (op = lookup_option (&dhcp_universe, tp.options, DHO_DHCP_MESSAGE_TYPE))) { struct data_string dp; memset (&dp, 0, sizeof dp); ! evaluate_option_cache (&dp, &tp, tp.options, op); if (dp.len > 0) tp.packet_type = dp.data [0]; *************** *** 780,788 **** bootp (&tp); ! option_state_dereference (&tp.options); } ! int dhcp_option_lookup (result, options, code) struct data_string *result; struct option_state *options; int code; --- 786,795 ---- bootp (&tp); ! option_state_dereference (&tp.options, "do_packet"); } ! int hashed_option_get (result, universe, options, code) struct data_string *result; + struct universe *universe; struct option_state *options; int code; *************** *** 790,794 **** struct option_cache *oc; ! if (!(oc = lookup_option (options -> dhcp_hash, code))) return 0; if (!evaluate_option_cache (result, (struct packet *)0, options, oc)) --- 797,804 ---- struct option_cache *oc; ! if (!universe -> lookup_func) ! return 0; ! oc = ((*universe -> lookup_func) (universe, options, code)); ! if (!oc) return 0; if (!evaluate_option_cache (result, (struct packet *)0, options, oc)) *************** *** 797,802 **** } ! int agent_suboption_lookup (result, options, code) struct data_string *result; struct option_state *options; int code; --- 807,813 ---- } ! int agent_option_get (result, universe, options, code) struct data_string *result; + struct universe *universe; struct option_state *options; int code; *************** *** 805,810 **** struct option_tag *t; /* Find the last set of agent options and consider it definitive. */ ! for (ao = options -> agent_options; ao -> next; ao = ao -> next) ; if (ao) { --- 816,827 ---- struct option_tag *t; + /* Make sure there's agent option state. */ + if (universe -> index >= options -> universe_count || + !(options -> universes [universe -> index])) + return 0; + ao = (struct agent_options *)options -> universes [universe -> index]; + /* Find the last set of agent options and consider it definitive. */ ! for (; ao -> next; ao = ao -> next) ; if (ao) { *************** *** 812,823 **** if (t -> data [0] == code) { result -> len = t -> data [1]; ! if (!buffer_allocate (&result -> buffer, ! result -> len + 1, ! "agent_suboption_lookup" ! )) { result -> len = 0; buffer_dereference (&result -> buffer, ! "agent_suboption_lookup"); return 0; } --- 829,839 ---- if (t -> data [0] == code) { result -> len = t -> data [1]; ! if (!(buffer_allocate ! (&result -> buffer, result -> len + 1, ! "agent_suboption_get"))) { result -> len = 0; buffer_dereference (&result -> buffer, ! "agent_suboption_get"); return 0; } *************** *** 834,868 **** } ! int server_option_lookup (result, options, code) ! struct data_string *result; ! struct option_state *options; ! int code; ! { ! return 0; ! } ! ! void dhcp_option_set (options, option, op) ! struct option_state *options; ! struct option_cache *option; ! enum statement_op op; ! { ! struct option_cache *thecache; ! ! do_option_set (options -> dhcp_hash, option, op); ! } ! ! void server_option_set (options, option, op) struct option_state *options; struct option_cache *option; enum statement_op op; { - do_option_set (options -> server_hash, option, op); - } - - static void do_option_set (hash, option, op) - pair *hash; - struct option_cache *option; - enum statement_op op; - { struct option_cache *oc, *noc; --- 850,859 ---- } ! void hashed_option_set (universe, options, option, op) ! struct universe *universe; struct option_state *options; struct option_cache *option; enum statement_op op; { struct option_cache *oc, *noc; *************** *** 877,896 **** case default_option_statement: ! oc = lookup_option (hash, option -> option -> code); if (oc) break; ! save_option (hash, option); break; case supersede_option_statement: /* Install the option, replacing any existing version. */ ! save_option (hash, option); break; case append_option_statement: case prepend_option_statement: ! oc = lookup_option (hash, option -> option -> code); if (!oc) { ! save_option (hash, option); break; } --- 868,889 ---- case default_option_statement: ! oc = lookup_option (universe, options, ! option -> option -> code); if (oc) break; ! save_option (universe, options, option); break; case supersede_option_statement: /* Install the option, replacing any existing version. */ ! save_option (universe, options, option); break; case append_option_statement: case prepend_option_statement: ! oc = lookup_option (universe, options, ! option -> option -> code); if (!oc) { ! save_option (universe, options, option); break; } *************** *** 929,933 **** } noc -> option = oc -> option; ! save_option (hash, noc); option_cache_dereference (&noc, "do_option_set"); break; --- 922,926 ---- } noc -> option = oc -> option; ! save_option (universe, options, noc); option_cache_dereference (&noc, "do_option_set"); break; *************** *** 935,944 **** } ! struct option_cache *lookup_option (hash, code) ! pair *hash; int code; { int hashix; pair bptr; hashix = ((code & 31) + ((code >> 5) & 31)) % 17; --- 928,959 ---- } ! struct option_cache *lookup_option (universe, options, code) ! struct universe *universe; ! struct option_state *options; ! int code; ! { ! if (universe -> lookup_func) ! return (*universe -> lookup_func) (universe, options, code); ! else ! log_error ("can't look up options in %s space.", ! universe -> name); ! return (struct option_cache *)0; ! } ! ! struct option_cache *lookup_hashed_option (universe, options, code) ! struct universe *universe; ! struct option_state *options; int code; { int hashix; pair bptr; + pair *hash; + + /* Make sure there's a hash table. */ + if (universe -> index >= options -> universe_count || + !(options -> universes [universe -> index])) + return (struct option_cache *)0; + + hash = options -> universes [universe -> index]; hashix = ((code & 31) + ((code >> 5) & 31)) % 17; *************** *** 951,997 **** } ! void save_option (hash, oc) ! pair *hash; struct option_cache *oc; { int hashix; pair bptr; ! /* Try to find an existing option matching the new one. */ hashix = ((oc -> option -> code & 31) + ((oc -> option -> code >> 5) & 31)) % 17; - for (bptr = hash [hashix]; bptr; bptr = bptr -> cdr) { - if (((struct option_cache *)(bptr -> car)) -> option -> code == - oc -> option -> code) - break; - } ! /* If we find one, dereference it and put the new one in its place. */ ! if (bptr) { ! option_cache_dereference ((struct option_cache **)&bptr -> car, ! "save_option"); ! option_cache_reference ((struct option_cache **)&bptr -> car, ! oc, "save_option"); } else { ! /* Otherwise, just put the new one at the head of the list. */ ! bptr = new_pair ("save_option"); ! if (!bptr) { ! log_error ("No memory for option_cache reference."); return; } - bptr -> cdr = hash [hashix]; - bptr -> car = 0; - option_cache_reference ((struct option_cache **)&bptr -> car, - oc, "save_option"); - hash [hashix] = bptr; } } ! void delete_option (hash, code) ! pair *hash; int code; { int hashix; pair bptr, prev = (pair)0; /* Try to find an existing option matching the new one. */ --- 966,1064 ---- } ! void save_option (universe, options, oc) ! struct universe *universe; ! struct option_state *options; ! struct option_cache *oc; ! { ! if (universe -> save_func) ! (*universe -> save_func) (universe, options, oc); ! else ! log_error ("can't store options in %s space.", ! universe -> name); ! } ! ! void save_hashed_option (universe, options, oc) ! struct universe *universe; ! struct option_state *options; struct option_cache *oc; { int hashix; pair bptr; + pair *hash = options -> universes [universe -> index]; ! /* Compute the hash. */ hashix = ((oc -> option -> code & 31) + ((oc -> option -> code >> 5) & 31)) % 17; ! /* If there's no hash table, make one. */ ! if (!hash) { ! hash = (pair *)dmalloc (OPTION_HASH_SIZE * sizeof *hash, ! "save_hashed_options"); ! if (!hash) { ! log_error ("no memory to store %s.%s", ! universe -> name, oc -> option -> name); ! return; ! } ! memset (hash, 0, OPTION_HASH_SIZE * sizeof *hash); ! options -> universes [universe -> index] = (VOIDPTR)hash; } else { ! /* Try to find an existing option matching the new one. */ ! for (bptr = hash [hashix]; bptr; bptr = bptr -> cdr) { ! if (((struct option_cache *) ! (bptr -> car)) -> option -> code == ! oc -> option -> code) ! break; ! } ! ! /* If we find one, dereference it and put the new one ! in its place. */ ! if (bptr) { ! option_cache_dereference ! ((struct option_cache **)&bptr -> car, ! "save_option"); ! option_cache_reference ! ((struct option_cache **)&bptr -> car, ! oc, "save_option"); return; } } + + /* Otherwise, just put the new one at the head of the list. */ + bptr = new_pair ("save_option"); + if (!bptr) { + log_error ("No memory for option_cache reference."); + return; + } + bptr -> cdr = hash [hashix]; + bptr -> car = 0; + option_cache_reference ((struct option_cache **)&bptr -> car, + oc, "save_option"); + hash [hashix] = bptr; } ! void delete_option (universe, options, code) ! struct universe *universe; ! struct option_state *options; ! int code; ! { ! if (universe -> delete_func) ! (*universe -> delete_func) (universe, options, code); ! else ! log_error ("can't delete options from %s space.", ! universe -> name); ! } ! ! void delete_hashed_option (universe, options, code) ! struct universe *universe; ! struct option_state *options; int code; { int hashix; pair bptr, prev = (pair)0; + pair *hash = options -> universes [universe -> index]; + + /* There may not be any options in this space. */ + if (!hash) + return; /* Try to find an existing option matching the new one. */ *************** *** 1024,1028 **** { if (!ptr || !*ptr) { ! log_error ("Null pointer in option_cache_dereference: %s", name); abort (); } --- 1091,1096 ---- { if (!ptr || !*ptr) { ! log_error ("Null pointer in option_cache_dereference: %s", ! name); abort (); } *************** *** 1041,1043 **** --- 1109,1258 ---- return 1; + } + + int hashed_option_state_dereference (universe, state) + struct universe *universe; + struct option_state *state; + { + pair *heads; + pair cp, next; + int i; + + /* Get the pointer to the array of hash table bucket heads. */ + heads = (pair *)(state -> universes [universe -> index]); + if (!heads) + return 0; + + /* For each non-null head, loop through all the buckets dereferencing + the attached option cache structures and freeing the buckets. */ + for (i = 0; i < OPTION_HASH_SIZE; i++) { + for (cp = heads [i]; cp; cp = next) { + next = cp -> cdr; + option_cache_dereference + ((struct option_cache **)&cp -> car, + "option_state_dereference"); + free_pair (cp, "hashed_option_state_dereference"); + } + } + + dfree (heads, "hashed_option_state_dereference"); + state -> universes [universe -> index] = (void *)0; + return 1; + } + + int agent_option_state_dereference (universe, state) + struct universe *universe; + struct option_state *state; + { + struct agent_options *a, *na; + struct option_tag *ot, *not; + + if (universe -> index >= state -> universe_count || + !state -> universes [universe -> index]) + return 0; + + /* We can also release the agent options, if any... */ + for (a = (struct agent_options *)(state -> universes + [universe -> index]); a; a = na) { + na = a -> next; + for (ot = a -> first; ot; ot = not) { + not = ot -> next; + free (ot); + } + } + + dfree (state -> universes [universe -> index], + "agent_option_state_dereference"); + state -> universes [universe -> index] = (void *)0; + return 1; + } + + int store_option (result, universe, oc) + struct data_string *result; + struct universe *universe; + struct option_cache *oc; + { + struct data_string d1, d2; + + memset (&d1, 0, sizeof d1); + memset (&d2, 0, sizeof d2); + + if (evaluate_option_cache (&d2, (struct packet *)0, + (struct option_state *)0, oc)) { + if (!buffer_allocate (&d1.buffer, + (result -> len + + universe -> length_size + + universe -> tag_size + + d2.len), "store_option")) { + data_string_forget (result, "store_option"); + data_string_forget (&d2, "store_option"); + return 0; + } + d1.data = &d1.buffer -> data [0]; + if (result -> len) + memcpy (d1.data, result -> data, result -> len); + d1.len = result -> len; + (*universe -> store_tag) (&d1.data [d1.len], + oc -> option -> code); + d1.len += universe -> tag_size; + (*universe -> store_length) (&d1.data [d1.len], d2.len); + d1.len += universe -> length_size; + memcpy (&d1.data [d1.len], d2.data, d2.len); + d1.len += d2.len; + data_string_forget (&d2, "store_option"); + data_string_forget (result, "store_option"); + data_string_copy (result, &d1, "store_option"); + data_string_forget (&d1, "store_option"); + return 1; + } + return 0; + } + + int option_space_encapsulate (result, options, name) + struct data_string *result; + struct option_state *options; + struct data_string *name; + { + struct universe *u; + + u = (struct universe *)hash_lookup (&universe_hash, + name -> data, name -> len); + if (!u) { + log_error ("unknown option space %s.", name -> data); + return 0; + } + + if (u -> encapsulate) + return (*u -> encapsulate) (result, options, u); + log_error ("encapsulation requested for %s with no support.", + name -> data); + return 0; + } + + int hashed_option_space_encapsulate (result, options, universe) + struct data_string *result; + struct option_state *options; + struct universe *universe; + { + pair p, *hash; + int status; + int i; + + if (universe -> index >= options -> universe_count) + return 0; + + hash = options -> universes [universe -> index]; + if (!hash) + return 0; + + status = 0; + for (i = 0; i < OPTION_HASH_SIZE; i++) { + for (p = hash [i]; p; p = p -> cdr) { + if (store_option (result, universe, + (struct option_cache *)p -> car)) + status = 1; + } + } + + return status; } diff -rNc2 dhcp-3.0-alpha-19990330/common/parse.c dhcp-3.0-alpha-19990408/common/parse.c *** dhcp-3.0-alpha-19990330/common/parse.c Tue Mar 30 07:20:09 1999 --- dhcp-3.0-alpha-19990408/common/parse.c Mon Apr 5 08:50:09 1999 *************** *** 23,27 **** #ifndef lint static char copyright[] = ! "$Id: parse.c,v 1.19 1999/03/30 15:20:09 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ --- 23,27 ---- #ifndef lint static char copyright[] = ! "$Id: parse.c,v 1.20 1999/04/05 15:50:09 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ *************** *** 795,798 **** --- 795,856 ---- } + /* IDENTIFIER SEMI */ + + void parse_option_space_decl (cfile) + FILE *cfile; + { + int token; + char *val; + struct universe **ua, *nu; + + next_token (&val, cfile); /* Discard the SPACE token, which was + checked by the caller. */ + token = next_token (&val, cfile); + if (!is_identifier (token)) { + parse_warn ("expecting identifier."); + skip_to_semi (cfile); + return; + } + nu = new_universe ("parse_option_space_decl"); + if (!nu) + log_fatal ("No memory for new option space."); + + /* Set up the server option universe... */ + nu -> name = dmalloc (strlen (val) + 1, "parse_option_space_decl"); + if (!nu -> name) + log_fatal ("No memory for new option space name."); + strcpy (nu -> name, val); + nu -> lookup_func = lookup_hashed_option; + nu -> option_state_dereference = + hashed_option_state_dereference; + nu -> get_func = hashed_option_get; + nu -> set_func = hashed_option_set; + nu -> save_func = save_hashed_option; + nu -> delete_func = delete_hashed_option; + nu -> encapsulate = hashed_option_space_encapsulate; + nu -> length_size = 1; + nu -> tag_size = 1; + nu -> store_tag = putUChar; + nu -> store_length = putUChar; + nu -> index = universe_count++; + if (nu -> index >= universe_max) { + ua = dmalloc (universe_max * 2 * sizeof *ua, + "parse_option_space_decl"); + if (!ua) + log_fatal ("No memory to expand option space array."); + memcpy (ua, universes, universe_max * sizeof *ua); + universe_max *= 2; + dfree (universes, "parse_option_space_decl"); + universes = ua; + } + universes [nu -> index] = nu; + nu -> hash = new_hash (); + if (!nu -> hash) + log_fatal ("Can't allocate %s option hash table.", nu -> name); + add_hash (&universe_hash, + (unsigned char *)nu -> name, 0, (unsigned char *)nu); + parse_semi (cfile); + } + /* This is faked up to look good right now. Ideally, this should do a recursive parse and allow arbitrary data structure definitions, but for *************** *** 1953,1957 **** if (expr && !option_cache (&stmt -> data.option, (struct data_string *)0, expr, option)) ! log_fatal ("no memory for option cache in parse_option_statement"); return stmt; } --- 2011,2015 ---- if (expr && !option_cache (&stmt -> data.option, (struct data_string *)0, expr, option)) ! log_fatal ("no memory for option cache"); return stmt; } *************** *** 1974,1977 **** --- 2032,2047 ---- switch (*fmt) { + case 'U': + token = next_token (&val, cfile); + if (!is_identifier (token)) { + parse_warn ("expecting identifier."); + skip_to_semi (cfile); + return 0; + } + if (!make_const_data (&t, (unsigned char *)val, + strlen (val), 1, 1)) + log_fatal ("No memory for %s", val); + break; + case 'X': token = peek_token (&val, cfile); *************** *** 1984,1990 **** } else if (token == STRING) { token = next_token (&val, cfile); ! if (!make_const_data (&t, (unsigned char *) val, strlen (val), 1, 1)) ! log_fatal ("No memory for concatenation"); } else { parse_warn ("expecting string %s.", --- 2054,2060 ---- } else if (token == STRING) { token = next_token (&val, cfile); ! if (!make_const_data (&t, (unsigned char *)val, strlen (val), 1, 1)) ! log_fatal ("No memory for \"%s\"", val); } else { parse_warn ("expecting string %s.", diff -rNc2 dhcp-3.0-alpha-19990330/common/print.c dhcp-3.0-alpha-19990408/common/print.c *** dhcp-3.0-alpha-19990330/common/print.c Mon Mar 15 21:50:36 1999 --- dhcp-3.0-alpha-19990408/common/print.c Mon Apr 5 09:18:22 1999 *************** *** 23,27 **** #ifndef lint static char copyright[] = ! "$Id: print.c,v 1.21 1999/03/16 05:50:36 mellon Exp $ Copyright (c) 1995, 1996, 1998, 1999 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ --- 23,27 ---- #ifndef lint static char copyright[] = ! "$Id: print.c,v 1.22 1999/04/05 16:18:22 mellon Exp $ Copyright (c) 1995, 1996, 1998, 1999 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ *************** *** 440,443 **** --- 440,454 ---- buf [rv] = 0; return rv; + + case expr_encapsulate: + rv = 13; + strcpy (buf, "(encapsulate "); + rv += expr -> data.encapsulate.len; + if (rv + 2 > len) + rv = len - 2; + strncpy (buf, expr -> data.encapsulate.data, rv - 13); + buf [rv++] = ')'; + buf [rv++] = 0; + break; case expr_extract_int8: diff -rNc2 dhcp-3.0-alpha-19990330/common/tables.c dhcp-3.0-alpha-19990408/common/tables.c *** dhcp-3.0-alpha-19990330/common/tables.c Thu Mar 25 14:01:03 1999 --- dhcp-3.0-alpha-19990408/common/tables.c Thu Apr 8 12:33:00 1999 *************** *** 23,27 **** #ifndef lint static char copyright[] = ! "$Id: tables.c,v 1.23 1999/03/25 22:01:03 mellon Exp $ Copyright (c) 1995, 1996, 1998, 1999 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ --- 23,27 ---- #ifndef lint static char copyright[] = ! "$Id: tables.c,v 1.25 1999/04/08 19:33:00 mellon Exp $ Copyright (c) 1995, 1996, 1998, 1999 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ *************** *** 43,46 **** --- 43,47 ---- f - flag (true or false) A - array of whatever precedes (e.g., IA means array of IP addresses) + U - name of an option space (universe) */ *************** *** 844,849 **** { "next-server", "I", &server_universe, 17 }, { "authoritative", "f", &server_universe, 18 }, ! { "option-19", "X", &server_universe, 19 }, ! { "option-20", "X", &server_universe, 20 }, { "option-21", "X", &server_universe, 21 }, { "option-22", "X", &server_universe, 22 }, --- 845,850 ---- { "next-server", "I", &server_universe, 17 }, { "authoritative", "f", &server_universe, 18 }, ! { "vendor-option-space", "U", &server_universe, 19 }, ! { "always-reply-rfc1048", "f", &server_universe, 20 }, { "option-21", "X", &server_universe, 21 }, { "option-22", "X", &server_universe, 22 }, *************** *** 1084,1087 **** --- 1085,1090 ---- struct hash_table universe_hash; + struct universe **universes; + int universe_count, universe_max; void initialize_universes() *************** *** 1089,1096 **** int i; /* Set up the DHCP option universe... */ dhcp_universe.name = "dhcp"; ! dhcp_universe.lookup_func = dhcp_option_lookup; ! dhcp_universe.set_func = dhcp_option_set; dhcp_universe.hash = new_hash (); if (!dhcp_universe.hash) --- 1092,1119 ---- int i; + universe_max = 10; + universes = ((struct universe **) + dmalloc (universe_max * sizeof (struct universe *), + "initialize_universes")); + if (!universes) + log_fatal ("Can't allocate option space table."); + memset (universes, 0, universe_max * sizeof (struct universe *)); + /* Set up the DHCP option universe... */ dhcp_universe.name = "dhcp"; ! dhcp_universe.lookup_func = lookup_hashed_option; ! dhcp_universe.option_state_dereference = ! hashed_option_state_dereference; ! dhcp_universe.get_func = hashed_option_get; ! dhcp_universe.set_func = hashed_option_set; ! dhcp_universe.save_func = save_hashed_option; ! dhcp_universe.delete_func = delete_hashed_option; ! dhcp_universe.encapsulate = hashed_option_space_encapsulate; ! dhcp_universe.length_size = 1; ! dhcp_universe.tag_size = 1; ! dhcp_universe.store_tag = putUChar; ! dhcp_universe.store_length = putUChar; ! dhcp_universe.index = universe_count++; ! universes [dhcp_universe.index] = &dhcp_universe; dhcp_universe.hash = new_hash (); if (!dhcp_universe.hash) *************** *** 1105,1109 **** /* Set up the Relay Agent Information Option suboption universe... */ agent_universe.name = "agent"; ! agent_universe.lookup_func = agent_suboption_lookup; agent_universe.hash = new_hash (); if (!agent_universe.hash) --- 1128,1140 ---- /* Set up the Relay Agent Information Option suboption universe... */ agent_universe.name = "agent"; ! agent_universe.option_state_dereference = ! agent_option_state_dereference; ! agent_universe.get_func = agent_option_get; ! agent_universe.index = universe_count++; ! agent_universe.length_size = 1; ! agent_universe.tag_size = 1; ! agent_universe.store_tag = putUChar; ! agent_universe.store_length = putUChar; ! universes [agent_universe.index] = &agent_universe; agent_universe.hash = new_hash (); if (!agent_universe.hash) *************** *** 1118,1123 **** /* Set up the server option universe... */ server_universe.name = "server"; ! server_universe.lookup_func = server_option_lookup; ! server_universe.set_func = server_option_set; server_universe.hash = new_hash (); if (!server_universe.hash) --- 1149,1166 ---- /* Set up the server option universe... */ server_universe.name = "server"; ! server_universe.lookup_func = lookup_hashed_option; ! server_universe.option_state_dereference = ! hashed_option_state_dereference; ! server_universe.get_func = hashed_option_get; ! server_universe.set_func = hashed_option_set; ! server_universe.save_func = save_hashed_option; ! server_universe.delete_func = delete_hashed_option; ! server_universe.encapsulate = hashed_option_space_encapsulate; ! server_universe.length_size = 1; ! server_universe.tag_size = 1; ! server_universe.store_tag = putUChar; ! server_universe.store_length = putUChar; ! server_universe.index = universe_count++; ! universes [server_universe.index] = &server_universe; server_universe.hash = new_hash (); if (!server_universe.hash) diff -rNc2 dhcp-3.0-alpha-19990330/common/tree.c dhcp-3.0-alpha-19990408/common/tree.c *** dhcp-3.0-alpha-19990330/common/tree.c Mon Mar 15 21:50:37 1999 --- dhcp-3.0-alpha-19990408/common/tree.c Mon Apr 5 12:06:50 1999 *************** *** 23,27 **** #ifndef lint static char copyright[] = ! "$Id: tree.c,v 1.23 1999/03/16 05:50:37 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ --- 23,27 ---- #ifndef lint static char copyright[] = ! "$Id: tree.c,v 1.25 1999/04/05 19:06:50 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ *************** *** 130,134 **** len + terminated, "make_const_data")) { ! log_error ("Can't allocate const_data buffer."); expression_dereference (expr, "make_const_data"); --- 130,134 ---- len + terminated, "make_const_data")) { ! log_error ("Can't allocate const_data buffer"); expression_dereference (expr, "make_const_data"); *************** *** 182,185 **** --- 182,201 ---- } + int make_encapsulation (expr, name) + struct expression **expr; + struct data_string *name; + { + /* Allocate a new node to store the encapsulation. */ + if (!expression_allocate (expr, "make_encapsulation")) { + log_error ("No memory for encapsulation expression node."); + return 0; + } + + (*expr) -> op = expr_encapsulate; + data_string_copy (&(*expr) -> data.encapsulate, + name, "make_concat"); + return 1; + } + int make_substring (new, expr, offset, length) struct expression **new; *************** *** 469,474 **** case expr_exists: memset (&left, 0, sizeof left); ! if (!((*expr -> data.option -> universe -> lookup_func) ! (&left, options, expr -> data.exists -> code))) *result = 0; else { --- 485,491 ---- case expr_exists: memset (&left, 0, sizeof left); ! if (!((*expr -> data.option -> universe -> get_func) ! (&left, expr -> data.exists -> universe, ! options, expr -> data.exists -> code))) *result = 0; else { *************** *** 491,494 **** --- 508,512 ---- case expr_packet: case expr_concat: + case expr_encapsulate: case expr_host_lookup: log_error ("Data opcode in evaluate_boolean_expression: %d", *************** *** 600,606 **** /* Extract an option. */ case expr_option: ! s0 = ((*expr -> data.option -> universe -> lookup_func) ! (result, &packet -> options, ! expr -> data.option -> code)); #if defined (DEBUG_EXPRESSIONS) log_info ("data: option %s.%s = %s", --- 618,624 ---- /* Extract an option. */ case expr_option: ! s0 = ((*expr -> data.option -> universe -> get_func) ! (result, expr -> data.option -> universe, ! packet -> options, expr -> data.option -> code)); #if defined (DEBUG_EXPRESSIONS) log_info ("data: option %s.%s = %s", *************** *** 680,683 **** --- 698,714 ---- return s2; + /* The encapsulation of all defined options in an + option space... */ + case expr_encapsulate: + s0 = option_space_encapsulate (result, options, + &expr -> data.encapsulate); + #if defined (DEBUG_EXPRESSIONS) + log_info ("data: encapsulate (%s) = %s", + expr -> data.encapsulate.data, + s0 ? print_hex_1 (result -> len, + result -> data, 60) : "null"); + #endif + return s0; + /* Some constant data... */ case expr_const_data: *************** *** 793,796 **** --- 824,828 ---- case expr_packet: case expr_concat: + case expr_encapsulate: case expr_host_lookup: log_error ("Data opcode in evaluate_numeric_expression: %d", *************** *** 1004,1007 **** --- 1036,1040 ---- break; + case expr_encapsulate: case expr_const_data: data_string_forget (&expr -> data.const_data, name); *************** *** 1029,1072 **** } - - /* Free all of the state in an option state buffer. The buffer itself is - not freed, since these buffers are always contained in other structures. */ - - void option_state_dereference (state) - struct option_state *state; - { - int i; - struct agent_options *a, *na; - struct option_tag *ot, *not; - pair cp, next; - - /* Having done the cons_options(), we can release the tree_cache - entries. */ - for (i = 0; i < OPTION_HASH_SIZE; i++) { - for (cp = state -> dhcp_hash [i]; cp; cp = next) { - next = cp -> cdr; - option_cache_dereference - ((struct option_cache **)&cp -> car, - "option_state_dereference"); - free_pair (cp, "option_state_dereference"); - } - for (cp = state -> server_hash [i]; cp; cp = next) { - next = cp -> cdr; - option_cache_dereference - ((struct option_cache **)&cp -> car, - "option_state_dereference"); - } - } - - /* We can also release the agent options, if any... */ - for (a = state -> agent_options; a; a = na) { - na = a -> next; - for (ot = a -> first; ot; ot = not) { - not = ot -> next; - free (ot); - } - } - } - /* Make a copy of the data in data_string, upping the buffer reference count if there's a buffer. */ --- 1062,1065 ---- *************** *** 1129,1132 **** --- 1122,1126 ---- expr -> op == expr_packet || expr -> op == expr_concat || + expr -> op == expr_encapsulate || expr -> op == expr_host_lookup); } *************** *** 1153,1156 **** --- 1147,1151 ---- case expr_suffix: case expr_concat: + case expr_encapsulate: case expr_host_lookup: case expr_not: *************** *** 1196,1199 **** --- 1191,1195 ---- case expr_suffix: case expr_concat: + case expr_encapsulate: case expr_host_lookup: case expr_not: diff -rNc2 dhcp-3.0-alpha-19990330/includes/dhcpd.h dhcp-3.0-alpha-19990408/includes/dhcpd.h *** dhcp-3.0-alpha-19990330/includes/dhcpd.h Tue Mar 30 07:20:10 1999 --- dhcp-3.0-alpha-19990408/includes/dhcpd.h Thu Apr 8 12:34:41 1999 *************** *** 103,109 **** struct option_state { ! pair dhcp_hash [OPTION_HASH_SIZE]; ! pair server_hash [OPTION_HASH_SIZE]; ! struct agent_options *agent_options; }; --- 103,109 ---- struct option_state { ! int refcnt; ! int universe_count; ! VOIDPTR universes [1]; }; *************** *** 129,134 **** struct shared_network *shared_network; ! struct option_state options; ! struct agent_options *agent_options; #if !defined (PACKET_MAX_CLASSES) --- 129,133 ---- struct shared_network *shared_network; ! struct option_state *options; #if !defined (PACKET_MAX_CLASSES) *************** *** 194,199 **** TIME offered_expiry; ! struct option_state options; ! struct agent_options *agent_options; struct data_string parameter_request_list; int max_message_size; --- 193,197 ---- TIME offered_expiry; ! struct option_state *options; struct data_string parameter_request_list; int max_message_size; *************** *** 247,250 **** --- 245,250 ---- #define SV_NEXT_SERVER 17 #define SV_AUTHORITATIVE 18 + #define SV_VENDOR_OPTION_SPACE 19 + #define SV_ALWAYS_REPLY_RFC1048 20 #if !defined (DEFAULT_DEFAULT_LEASE_TIME) *************** *** 490,494 **** unsigned int is_bootp: 1; /* If set, lease was aquired with BOOTP. */ ! struct option_state options; /* Options supplied with lease. */ }; --- 490,494 ---- unsigned int is_bootp: 1; /* If set, lease was aquired with BOOTP. */ ! struct option_state *options; /* Options supplied with lease. */ }; *************** *** 557,561 **** struct iaddrlist *reject_list; /* Servers to reject. */ ! struct option_state send_options; /* Options to send. */ }; --- 557,561 ---- struct iaddrlist *reject_list; /* Servers to reject. */ ! struct option_state *send_options; /* Options to send. */ }; *************** *** 752,756 **** int parse_agent_information_option PROTO ((struct packet *, int, u_int8_t *)); int cons_options PROTO ((struct packet *, struct dhcp_packet *, int, ! struct option_state *, struct agent_options *, int, int, int, struct data_string *)); int store_options PROTO ((unsigned char *, int, struct option_state *, --- 752,756 ---- int parse_agent_information_option PROTO ((struct packet *, int, u_int8_t *)); int cons_options PROTO ((struct packet *, struct dhcp_packet *, int, ! struct option_state *, int, int, int, struct data_string *)); int store_options PROTO ((unsigned char *, int, struct option_state *, *************** *** 761,778 **** struct dhcp_packet *, int, unsigned int, struct iaddr, struct hardware *)); ! int dhcp_option_lookup PROTO ((struct data_string *, ! struct option_state *, int)); ! int agent_suboption_lookup PROTO ((struct data_string *, ! struct option_state *, int)); ! int server_option_lookup PROTO ((struct data_string *, ! struct option_state *, int)); ! void dhcp_option_set PROTO ((struct option_state *, struct option_cache *, ! enum statement_op)); ! void server_option_set PROTO ((struct option_state *, struct option_cache *, enum statement_op)); ! struct option_cache *lookup_option PROTO ((pair *, int)); ! void save_option PROTO ((pair *, struct option_cache *)); ! void delete_option PROTO ((pair *, int)); int option_cache_dereference PROTO ((struct option_cache **, char *)); /* errwarn.c */ --- 761,798 ---- struct dhcp_packet *, int, unsigned int, struct iaddr, struct hardware *)); ! int hashed_option_get PROTO ((struct data_string *, ! struct universe *, struct option_state *, int)); ! int agent_option_get PROTO ((struct data_string *, struct universe *, ! struct option_state *, int)); ! void hashed_option_set PROTO ((struct universe *, struct option_state *, ! struct option_cache *, enum statement_op)); ! struct option_cache *lookup_option PROTO ((struct universe *, ! struct option_state *, int)); ! struct option_cache *lookup_hashed_option PROTO ((struct universe *, ! struct option_state *, int)); ! void save_option PROTO ((struct universe *, ! struct option_state *, struct option_cache *)); ! void save_hashed_option PROTO ((struct universe *, ! struct option_state *, struct option_cache *)); ! void delete_option PROTO ((struct universe *, struct option_state *, int)); ! void delete_hashed_option PROTO ((struct universe *, ! struct option_state *, int)); int option_cache_dereference PROTO ((struct option_cache **, char *)); + int hashed_option_state_dereference PROTO ((struct universe *, + struct option_state *)); + int agent_option_state_dereference PROTO ((struct universe *, + struct option_state *)); + int store_option PROTO ((struct data_string *, + struct universe *, struct option_cache *)); + int option_space_encapsulate PROTO ((struct data_string *, + struct option_state *, + struct data_string *)); + int hashed_option_space_encapsulate PROTO ((struct data_string *, + struct option_state *, + struct universe *)); + int agent_option_space_encapsulate PROTO ((struct data_string *, + struct option_state *, + struct universe *)); /* errwarn.c */ *************** *** 811,816 **** extern int eol_token; void new_parse PROTO ((char *)); ! int next_token PROTO ((char **, FILE *)); ! int peek_token PROTO ((char **, FILE *)); /* confpars.c */ --- 831,836 ---- extern int eol_token; void new_parse PROTO ((char *)); ! enum dhcp_token next_token PROTO ((char **, FILE *)); ! enum dhcp_token peek_token PROTO ((char **, FILE *)); /* confpars.c */ *************** *** 849,852 **** --- 869,873 ---- TIME parse_date PROTO ((FILE *)); struct option *parse_option_name PROTO ((FILE *, int)); + void parse_option_space_decl PROTO ((FILE *)); int parse_option_code_definition PROTO ((FILE *, struct option *)); int parse_cshl PROTO ((struct data_string *, FILE *)); *************** *** 883,886 **** --- 904,908 ---- int make_concat PROTO ((struct expression **, struct expression *, struct expression *)); + int make_encapsulation PROTO ((struct expression **, struct data_string *)); int make_substring PROTO ((struct expression **, struct expression *, struct expression *, struct expression *)); *************** *** 908,912 **** struct expression *)); void expression_dereference PROTO ((struct expression **, char *)); - void option_state_dereference PROTO ((struct option_state *)); void data_string_copy PROTO ((struct data_string *, struct data_string *, char *)); --- 930,933 ---- *************** *** 995,998 **** --- 1016,1021 ---- struct option *new_option PROTO ((char *)); void free_option PROTO ((struct option *, char *)); + struct universe *new_universe PROTO ((char *)); + void free_universe PROTO ((struct universe *, char *)); void free_domain_search_list PROTO ((struct domain_search_list *, char *)); void free_lease_state PROTO ((struct lease_state *, char *)); *************** *** 1033,1036 **** --- 1056,1063 ---- struct dns_host_entry *, char *)); int dns_host_entry_dereference PROTO ((struct dns_host_entry **, char *)); + int option_state_allocate PROTO ((struct option_state **, char *)); + int option_state_reference PROTO ((struct option_state **, + struct option_state *, char *)); + int option_state_dereference PROTO ((struct option_state **, char *)); /* print.c */ *************** *** 1237,1240 **** --- 1264,1269 ---- extern int dhcp_option_default_priority_list_count; extern char *hardware_types [256]; + int universe_count, universe_max; + struct universe **universes; extern struct hash_table universe_hash; void initialize_universes PROTO ((void)); *************** *** 1243,1252 **** u_int32_t getULong PROTO ((unsigned char *)); int32_t getLong PROTO ((unsigned char *)); ! u_int16_t getUShort PROTO ((unsigned char *)); ! int16_t getShort PROTO ((unsigned char *)); void putULong PROTO ((unsigned char *, u_int32_t)); void putLong PROTO ((unsigned char *, int32_t)); void putUShort PROTO ((unsigned char *, u_int32_t)); void putShort PROTO ((unsigned char *, int32_t)); /* inet.c */ --- 1272,1283 ---- u_int32_t getULong PROTO ((unsigned char *)); int32_t getLong PROTO ((unsigned char *)); ! u_int32_t getUShort PROTO ((unsigned char *)); ! int32_t getShort PROTO ((unsigned char *)); ! u_int32_t getUChar PROTO ((unsigned char *)); void putULong PROTO ((unsigned char *, u_int32_t)); void putLong PROTO ((unsigned char *, int32_t)); void putUShort PROTO ((unsigned char *, u_int32_t)); void putShort PROTO ((unsigned char *, int32_t)); + void putUChar PROTO ((unsigned char *, u_int32_t)); /* inet.c */ *************** *** 1287,1291 **** struct client_lease *, u_int8_t *, struct option_cache *, struct iaddr *, ! u_int32_t *, struct option_state *)); void make_discover PROTO ((struct client_state *, struct client_lease *)); void make_request PROTO ((struct client_state *, struct client_lease *)); --- 1318,1322 ---- struct client_lease *, u_int8_t *, struct option_cache *, struct iaddr *, ! u_int32_t *, struct option_state **)); void make_discover PROTO ((struct client_state *, struct client_lease *)); void make_request PROTO ((struct client_state *, struct client_lease *)); *************** *** 1450,1455 **** /* execute.c */ ! int execute_statements PROTO ((struct packet *, struct option_state *, ! struct option_state *, struct executable_statement *)); void execute_statements_in_scope PROTO ((struct packet *, --- 1481,1486 ---- /* execute.c */ ! int execute_statements PROTO ((struct packet *, ! struct option_state *, struct option_state *, struct executable_statement *)); void execute_statements_in_scope PROTO ((struct packet *, diff -rNc2 dhcp-3.0-alpha-19990330/includes/dhctoken.h dhcp-3.0-alpha-19990408/includes/dhctoken.h *** dhcp-3.0-alpha-19990330/includes/dhctoken.h Thu Mar 25 14:03:07 1999 --- dhcp-3.0-alpha-19990408/includes/dhctoken.h Mon Apr 5 07:58:23 1999 *************** *** 175,178 **** --- 175,179 ---- TEXT = 395, STRING_TOKEN = 396, + SPACE = 397, }; diff -rNc2 dhcp-3.0-alpha-19990330/includes/tree.h dhcp-3.0-alpha-19990408/includes/tree.h *** dhcp-3.0-alpha-19990330/includes/tree.h Thu Mar 25 14:03:44 1999 --- dhcp-3.0-alpha-19990408/includes/tree.h Mon Apr 5 07:54:38 1999 *************** *** 77,80 **** --- 77,81 ---- expr_const_int, expr_exists, + expr_encapsulate, }; *************** *** 108,111 **** --- 109,113 ---- struct dns_host_entry *host_lookup; struct option *exists; + struct data_string encapsulate; } data; int flags; *************** *** 129,140 **** struct universe { char *name; ! int (*lookup_func) ! PROTO ((struct data_string *, ! struct option_state *, int)); ! void (*set_func) PROTO ((struct option_state *, ! struct option_cache *, ! enum statement_op)); struct hash_table *hash; struct option *options [256]; }; --- 131,156 ---- struct universe { char *name; ! struct option_cache *(*lookup_func) PROTO ((struct universe *, ! struct option_state *, ! int)); ! void (*save_func) PROTO ((struct universe *, struct option_state *, ! struct option_cache *)); ! int (*get_func) PROTO ((struct data_string *, struct universe *, ! struct option_state *, int)); ! void (*set_func) PROTO ((struct universe *, struct option_state *, ! struct option_cache *, enum statement_op)); ! ! void (*delete_func) PROTO ((struct universe *universe, ! struct option_state *, int)); ! int (*option_state_dereference) PROTO ((struct universe *, ! struct option_state *)); ! int (*encapsulate) PROTO ((struct data_string *, struct option_state *, ! struct universe *)); ! void (*store_tag) PROTO ((unsigned char *, u_int32_t)); ! void (*store_length) PROTO ((unsigned char *, u_int32_t)); ! int tag_size, length_size; struct hash_table *hash; struct option *options [256]; + int index; }; diff -rNc2 dhcp-3.0-alpha-19990330/relay/Makefile.dist dhcp-3.0-alpha-19990408/relay/Makefile.dist *** dhcp-3.0-alpha-19990330/relay/Makefile.dist Mon Mar 15 21:50:41 1999 --- dhcp-3.0-alpha-19990408/relay/Makefile.dist Thu Apr 8 13:53:33 1999 *************** *** 44,48 **** $(INSTALL) dhcrelay $(DESTDIR)$(BINDIR) $(CHMOD) 755 $(DESTDIR)$(BINDIR)/dhcrelay ! $(MANINSTALL) $(MANFROM) dhcrelay.cat8 $(MANTO) \ $(DESTDIR)$(ADMMANDIR)/dhcrelay$(ADMMANEXT) --- 44,48 ---- $(INSTALL) dhcrelay $(DESTDIR)$(BINDIR) $(CHMOD) 755 $(DESTDIR)$(BINDIR)/dhcrelay ! $(MANINSTALL) $(MANFROM) dhcrelay.$(MANCAT)8 $(MANTO) \ $(DESTDIR)$(ADMMANDIR)/dhcrelay$(ADMMANEXT) diff -rNc2 dhcp-3.0-alpha-19990330/relay/dhcrelay.c dhcp-3.0-alpha-19990408/relay/dhcrelay.c *** dhcp-3.0-alpha-19990330/relay/dhcrelay.c Tue Mar 30 13:54:03 1999 --- dhcp-3.0-alpha-19990408/relay/dhcrelay.c Thu Apr 8 12:47:55 1999 *************** *** 23,27 **** #ifndef lint static char ocopyright[] = ! "$Id: dhcrelay.c,v 1.27 1999/03/30 21:54:03 mellon Exp $ Copyright (c) 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ --- 23,27 ---- #ifndef lint static char ocopyright[] = ! "$Id: dhcrelay.c,v 1.28 1999/04/08 19:47:55 mellon Exp $ Copyright (c) 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ *************** *** 92,96 **** "Copyright 1997, 1998, 1999 The Internet Software Consortium."; static char arr [] = "All rights reserved."; ! static char message [] = "Internet Software Consortium DHCP Relay Agent V3.0-alpha 19990330"; static char contrib [] = "\nPlease contribute if you find this software useful."; static char url [] = "For info, please visit http://www.isc.org/dhcp-contrib.html\n"; --- 92,96 ---- "Copyright 1997, 1998, 1999 The Internet Software Consortium."; static char arr [] = "All rights reserved."; ! static char message [] = "Internet Software Consortium DHCP Relay Agent V3.0-alpha 19990408"; static char contrib [] = "\nPlease contribute if you find this software useful."; static char url [] = "For info, please visit http://www.isc.org/dhcp-contrib.html\n"; diff -rNc2 dhcp-3.0-alpha-19990330/server/Makefile.dist dhcp-3.0-alpha-19990408/server/Makefile.dist *** dhcp-3.0-alpha-19990330/server/Makefile.dist Mon Mar 15 21:55:40 1999 --- dhcp-3.0-alpha-19990408/server/Makefile.dist Thu Apr 8 13:53:33 1999 *************** *** 44,52 **** $(INSTALL) dhcpd $(DESTDIR)$(BINDIR) $(CHMOD) 755 $(DESTDIR)$(BINDIR)/dhcpd ! $(MANINSTALL) $(MANFROM) dhcpd.cat8 $(MANTO) \ $(DESTDIR)$(ADMMANDIR)/dhcpd$(ADMMANEXT) ! $(MANINSTALL) $(MANFROM) dhcpd.conf.cat5 $(MANTO) \ $(DESTDIR)$(FFMANDIR)/dhcpd.conf$(FFMANEXT) ! $(MANINSTALL) $(MANFROM) dhcpd.leases.cat5 $(MANTO) \ $(DESTDIR)$(FFMANDIR)/dhcpd.leases$(FFMANEXT) --- 44,52 ---- $(INSTALL) dhcpd $(DESTDIR)$(BINDIR) $(CHMOD) 755 $(DESTDIR)$(BINDIR)/dhcpd ! $(MANINSTALL) $(MANFROM) dhcpd.$(MANCAT)8 $(MANTO) \ $(DESTDIR)$(ADMMANDIR)/dhcpd$(ADMMANEXT) ! $(MANINSTALL) $(MANFROM) dhcpd.conf.$(MANCAT)5 $(MANTO) \ $(DESTDIR)$(FFMANDIR)/dhcpd.conf$(FFMANEXT) ! $(MANINSTALL) $(MANFROM) dhcpd.leases.$(MANCAT)5 $(MANTO) \ $(DESTDIR)$(FFMANDIR)/dhcpd.leases$(FFMANEXT) diff -rNc2 dhcp-3.0-alpha-19990330/server/bootp.c dhcp-3.0-alpha-19990408/server/bootp.c *** dhcp-3.0-alpha-19990330/server/bootp.c Tue Mar 30 10:12:34 1999 --- dhcp-3.0-alpha-19990408/server/bootp.c Thu Apr 8 12:36:23 1999 *************** *** 23,27 **** #ifndef lint static char copyright[] = ! "$Id: bootp.c,v 1.42 1999/03/30 18:12:34 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ --- 23,27 ---- #ifndef lint static char copyright[] = ! "$Id: bootp.c,v 1.44 1999/04/08 19:36:23 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ *************** *** 39,43 **** struct in_addr from; struct hardware hto; ! struct option_state options; struct subnet *subnet; struct lease *lease; --- 39,43 ---- struct in_addr from; struct hardware hto; ! struct option_state *options = (struct option_state *)0; struct subnet *subnet; struct lease *lease; *************** *** 115,142 **** /* Run the executable statements to compute the client and server options. */ ! ! memset (&options, 0, sizeof options); /* Execute the subnet statements. */ ! execute_statements_in_scope (packet, &options, &options, lease -> subnet -> group, (struct group *)0); /* Execute the host statements. */ ! execute_statements_in_scope (packet, &options, &options, hp -> group, lease -> subnet -> group); /* Drop the request if it's not allowed for this client. */ ! if (evaluate_boolean_option_cache (packet, &options, ! lookup_option (options.dhcp_hash, SV_ALLOW_BOOTP))) { log_info ("%s: bootp disallowed", msgbuf); return; } ! if (evaluate_boolean_option_cache (packet, &options, ! lookup_option (options.dhcp_hash, SV_ALLOW_BOOTING))) { log_info ("%s: booting disallowed", msgbuf); return; } --- 115,145 ---- /* Run the executable statements to compute the client and server options. */ ! option_state_allocate (&options, "bootrequest"); /* Execute the subnet statements. */ ! execute_statements_in_scope (packet, options, options, lease -> subnet -> group, (struct group *)0); /* Execute the host statements. */ ! execute_statements_in_scope (packet, options, options, hp -> group, lease -> subnet -> group); /* Drop the request if it's not allowed for this client. */ ! if (evaluate_boolean_option_cache (packet, options, ! lookup_option (&dhcp_universe, ! options, SV_ALLOW_BOOTP))) { log_info ("%s: bootp disallowed", msgbuf); + option_state_dereference (&options, "bootrequest"); return; } ! if (evaluate_boolean_option_cache (packet, options, ! lookup_option (&dhcp_universe, ! options, SV_ALLOW_BOOTING))) { log_info ("%s: booting disallowed", msgbuf); + option_state_dereference (&options, "bootrequest"); return; } *************** *** 149,157 **** /* If we didn't get a known vendor magic number on the way in, just copy the input options to the output. */ ! if (!packet -> options_valid) { memcpy (outgoing.raw -> options, packet -> raw -> options, DHCP_OPTION_LEN); outgoing.packet_length = BOOTP_MIN_LEN; } else { /* Pack the options into the buffer. Unlike DHCP, we can't pack options into the filename and server --- 152,185 ---- /* If we didn't get a known vendor magic number on the way in, just copy the input options to the output. */ ! if (!packet -> options_valid && ! !(evaluate_boolean_option_cache ! (packet, options, ! lookup_option (&dhcp_universe, options, ! SV_ALWAYS_REPLY_RFC1048)))) { memcpy (outgoing.raw -> options, packet -> raw -> options, DHCP_OPTION_LEN); outgoing.packet_length = BOOTP_MIN_LEN; } else { + + /* Use the subnet mask from the subnet declaration if no other + mask has been provided. */ + + oc = (struct option_cache *)0; + i = DHO_SUBNET_MASK; + if (!lookup_option (&dhcp_universe, options, i)) { + if (option_cache_allocate (&oc, "ack_lease")) { + if (make_const_data + (&oc -> expression, + lease -> subnet -> netmask.iabuf, + lease -> subnet -> netmask.len, 0, 0)) { + oc -> option = + dhcp_universe.options [i]; + save_option (&dhcp_universe, + options, oc); + } + option_cache_dereference (&oc, "ack_lease"); + } + } + /* Pack the options into the buffer. Unlike DHCP, we can't pack options into the filename and server *************** *** 159,164 **** outgoing.packet_length = ! cons_options (packet, outgoing.raw, 0, ! &options, (struct agent_options *)0, 0, 0, 1, (struct data_string *)0); if (outgoing.packet_length < BOOTP_MIN_LEN) --- 187,191 ---- outgoing.packet_length = ! cons_options (packet, outgoing.raw, 0, options, 0, 0, 1, (struct data_string *)0); if (outgoing.packet_length < BOOTP_MIN_LEN) *************** *** 182,188 **** interface -> primary_address); memset (&d1, 0, sizeof d1); ! oc = lookup_option (options.dhcp_hash, SV_NEXT_SERVER); if (oc && ! evaluate_option_cache (&d1, packet, &options, oc)) { /* If there was more than one answer, take the first. */ if (d1.len >= 4 && d1.data) --- 209,215 ---- interface -> primary_address); memset (&d1, 0, sizeof d1); ! oc = lookup_option (&dhcp_universe, options, SV_NEXT_SERVER); if (oc && ! evaluate_option_cache (&d1, packet, options, oc)) { /* If there was more than one answer, take the first. */ if (d1.len >= 4 && d1.data) *************** *** 194,200 **** /* Figure out the filename. */ ! oc = lookup_option (options.dhcp_hash, SV_FILENAME); if (oc && ! evaluate_option_cache (&d1, packet, &options, oc)) { memcpy (raw.file, d1.data, d1.len > sizeof raw.file ? sizeof raw.file : d1.len); --- 221,227 ---- /* Figure out the filename. */ ! oc = lookup_option (&dhcp_universe, options, SV_FILENAME); if (oc && ! evaluate_option_cache (&d1, packet, options, oc)) { memcpy (raw.file, d1.data, d1.len > sizeof raw.file ? sizeof raw.file : d1.len); *************** *** 207,213 **** /* Choose a server name as above. */ ! oc = lookup_option (options.dhcp_hash, SV_SERVER_NAME); if (oc && ! evaluate_option_cache (&d1, packet, &options, oc)) { memcpy (raw.sname, d1.data, d1.len > sizeof raw.sname ? sizeof raw.sname : d1.len); --- 234,240 ---- /* Choose a server name as above. */ ! oc = lookup_option (&dhcp_universe, options, SV_SERVER_NAME); if (oc && ! evaluate_option_cache (&d1, packet, options, oc)) { memcpy (raw.sname, d1.data, d1.len > sizeof raw.sname ? sizeof raw.sname : d1.len); *************** *** 217,220 **** --- 244,250 ---- data_string_forget (&d1, "bootrequest"); } + + /* We're done with the option state. */ + option_state_dereference (&options, "bootrequest"); /* Set up the hardware destination address... */ diff -rNc2 dhcp-3.0-alpha-19990330/server/class.c dhcp-3.0-alpha-19990408/server/class.c *** dhcp-3.0-alpha-19990330/server/class.c Mon Mar 15 21:50:42 1999 --- dhcp-3.0-alpha-19990408/server/class.c Mon Apr 5 09:34:33 1999 *************** *** 23,27 **** #ifndef lint static char copyright[] = ! "$Id: class.c,v 1.10 1999/03/16 05:50:42 mellon Exp $ Copyright (c) 1998 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ --- 23,27 ---- #ifndef lint static char copyright[] = ! "$Id: class.c,v 1.11 1999/04/05 16:34:33 mellon Exp $ Copyright (c) 1998 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ *************** *** 71,75 **** struct packet *packet; { ! execute_statements (packet, &packet -> options, (struct option_state *)0, default_classification_rules); --- 71,75 ---- struct packet *packet; { ! execute_statements (packet, packet -> options, (struct option_state *)0, default_classification_rules); *************** *** 94,98 **** if (class -> submatch) { status = evaluate_data_expression (&data, packet, ! &packet -> options, class -> submatch); if (status) { --- 94,98 ---- if (class -> submatch) { status = evaluate_data_expression (&data, packet, ! packet -> options, class -> submatch); if (status) { *************** *** 133,137 **** "check_collection")); if (!nc -> billed_leases) { ! log_error ("no memory for billing"); data_string_forget (&nc -> hash_string, --- 133,138 ---- "check_collection")); if (!nc -> billed_leases) { ! log_error ("no memory for%s", ! " billing"); data_string_forget (&nc -> hash_string, *************** *** 159,163 **** status = (evaluate_boolean_expression_result ! (packet, &packet -> options, class -> expr)); if (status) { matched = 1; --- 160,164 ---- status = (evaluate_boolean_expression_result ! (packet, packet -> options, class -> expr)); if (status) { matched = 1; diff -rNc2 dhcp-3.0-alpha-19990330/server/confpars.c dhcp-3.0-alpha-19990408/server/confpars.c *** dhcp-3.0-alpha-19990330/server/confpars.c Tue Mar 30 07:20:09 1999 --- dhcp-3.0-alpha-19990408/server/confpars.c Thu Apr 8 12:39:54 1999 *************** *** 23,27 **** #ifndef lint static char copyright[] = ! "$Id: confpars.c,v 1.69 1999/03/30 15:20:09 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ --- 23,27 ---- #ifndef lint static char copyright[] = ! "$Id: confpars.c,v 1.71 1999/04/08 19:39:54 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ *************** *** 167,171 **** struct data_string key_id; ! switch (peek_token (&val, cfile)) { case AUTH_KEY: memset (&key_id, 0, sizeof key_id); --- 167,173 ---- struct data_string key_id; ! token = peek_token (&val, cfile); ! ! switch (token) { case AUTH_KEY: memset (&key_id, 0, sizeof key_id); *************** *** 349,371 **** return declaration; - #if 0 - case ALLOW: - case DENY: - token = next_token (&val, cfile); - cache = (struct option_cache *)0; - if (!parse_allow_deny (&cache, cfile, - token == ALLOW ? 1 : 0)) - return declaration; - et = (struct executable_statement *)dmalloc (sizeof *et, - "allow/deny"); - if (!et) - log_fatal ("no memory for %s statement", - token == ALLOW ? "allow" : "deny"); - memset (et, 0, sizeof *et); - et -> op = supersede_option_statement; - et -> data.option = cache; - goto insert_statement; - #endif - case TOKEN_NOT: token = next_token (&val, cfile); --- 351,354 ---- *************** *** 399,402 **** --- 382,398 ---- case OPTION: token = next_token (&val, cfile); + token = peek_token (&val, cfile); + if (token == SPACE) { + if (type != ROOT_GROUP) { + parse_warn ("option space definitions %s", + " may not be scoped."); + skip_to_semi (cfile); + free_option (option, "parse_statement"); + break; + } + parse_option_space_decl (cfile); + return declaration; + } + option = parse_option_name (cfile, 1); if (option) { *************** *** 405,410 **** if (type != ROOT_GROUP) { parse_warn ("option definitions%s%s", ! " may not currently be", ! " scoped."); skip_to_semi (cfile); free_option (option, --- 401,405 ---- if (type != ROOT_GROUP) { parse_warn ("option definitions%s%s", ! " may not be scoped."); skip_to_semi (cfile); free_option (option, *************** *** 1000,1003 **** --- 995,1001 ---- if (!parse_cshl (&data, cfile)) return (struct class *)0; + } else { + parse_warn ("Expecting string or hex list."); + return (struct class *)0; } } *************** *** 1019,1023 **** if (pc) { class -> group = pc -> group; - class -> group = pc -> group; class -> superclass = pc; class -> lease_limit = pc -> lease_limit; --- 1017,1020 ---- *************** *** 1026,1032 **** dmalloc (class -> lease_limit * sizeof (struct lease *), ! "check_collection"); if (!class -> billed_leases) ! log_fatal ("no memory for billed leases"); memset (class -> billed_leases, 0, (class -> lease_limit * --- 1023,1029 ---- dmalloc (class -> lease_limit * sizeof (struct lease *), ! "parse_class_declaration"); if (!class -> billed_leases) ! log_fatal ("no memory for billing"); memset (class -> billed_leases, 0, (class -> lease_limit * *************** *** 1034,1038 **** } data_string_copy (&class -> hash_string, &data, ! "check_collection"); if (!pc -> hash) pc -> hash = new_hash (); --- 1031,1035 ---- } data_string_copy (&class -> hash_string, &data, ! "parse_class_declaration"); if (!pc -> hash) pc -> hash = new_hash (); *************** *** 1074,1083 **** if (type == 0 || type == 1 || type == 3) ! data_string_forget (&data, "check_collection"); /* Spawned classes don't have their own settings. */ if (class -> superclass) { ! parse_semi (cfile); ! return class; } --- 1071,1086 ---- if (type == 0 || type == 1 || type == 3) ! data_string_forget (&data, "parse_class_declaration"); /* Spawned classes don't have their own settings. */ if (class -> superclass) { ! token = peek_token (&val, cfile); ! if (token == SEMI) { ! next_token (&val, cfile); ! return class; ! } ! /* Give the subclass its own group. */ ! class -> group = clone_group (class -> group, ! "parse_class_declaration"); } *************** *** 1106,1112 **** } token = next_token (&val, cfile); ! token = next_token (&val, cfile); if (token != IF) goto submatch; parse_boolean_expression (&class -> expr, cfile, &lose); --- 1109,1116 ---- } token = next_token (&val, cfile); ! token = peek_token (&val, cfile); if (token != IF) goto submatch; + token = next_token (&val, cfile); parse_boolean_expression (&class -> expr, cfile, &lose); *************** *** 1167,1171 **** dmalloc (class -> lease_limit * sizeof (struct lease *), ! "check_collection"); if (!class -> billed_leases) log_fatal ("no memory for billed leases."); --- 1171,1175 ---- dmalloc (class -> lease_limit * sizeof (struct lease *), ! "parse_class_declaration"); if (!class -> billed_leases) log_fatal ("no memory for billed leases."); diff -rNc2 dhcp-3.0-alpha-19990330/server/dhcp.c dhcp-3.0-alpha-19990408/server/dhcp.c *** dhcp-3.0-alpha-19990330/server/dhcp.c Thu Mar 25 14:07:54 1999 --- dhcp-3.0-alpha-19990408/server/dhcp.c Mon Apr 5 09:46:13 1999 *************** *** 23,27 **** #ifndef lint static char copyright[] = ! "$Id: dhcp.c,v 1.84 1999/03/25 22:07:54 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ --- 23,27 ---- #ifndef lint static char copyright[] = ! "$Id: dhcp.c,v 1.85 1999/04/05 16:46:13 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ *************** *** 119,127 **** char msgbuf [1024]; ! oc = lookup_option (packet -> options.dhcp_hash, DHO_DHCP_REQUESTED_ADDRESS); memset (&data, 0, sizeof data); if (oc && ! evaluate_option_cache (&data, packet, &packet -> options, oc)) { cip.len = 4; memcpy (cip.iabuf, data.data, 4); --- 119,127 ---- char msgbuf [1024]; ! oc = lookup_option (&dhcp_universe, packet -> options, DHO_DHCP_REQUESTED_ADDRESS); memset (&data, 0, sizeof data); if (oc && ! evaluate_option_cache (&data, packet, packet -> options, oc)) { cip.len = 4; memcpy (cip.iabuf, data.data, 4); *************** *** 255,259 **** option, but old protocol specs weren't explicit about this, so let it go. */ ! if ((oc = lookup_option (packet -> options.dhcp_hash, DHO_DHCP_REQUESTED_ADDRESS))) { log_info ("DHCPRELEASE from %s specified requested-address.", --- 255,259 ---- option, but old protocol specs weren't explicit about this, so let it go. */ ! if ((oc = lookup_option (&dhcp_universe, packet -> options, DHO_DHCP_REQUESTED_ADDRESS))) { log_info ("DHCPRELEASE from %s specified requested-address.", *************** *** 263,271 **** } ! oc = lookup_option (packet -> options.dhcp_hash, DHO_DHCP_CLIENT_IDENTIFIER); memset (&data, 0, sizeof data); if (oc && ! evaluate_option_cache (&data, packet, &packet -> options, oc)) { lease = find_lease_by_uid (data.data, data.len); data_string_forget (&data, "dhcprelease"); --- 263,271 ---- } ! oc = lookup_option (&dhcp_universe, packet -> options, DHO_DHCP_CLIENT_IDENTIFIER); memset (&data, 0, sizeof data); if (oc && ! evaluate_option_cache (&data, packet, packet -> options, oc)) { lease = find_lease_by_uid (data.data, data.len); data_string_forget (&data, "dhcprelease"); *************** *** 308,316 **** /* DHCPDECLINE must specify address. */ ! if (!(oc = lookup_option (packet -> options.dhcp_hash, DHO_DHCP_REQUESTED_ADDRESS))) return; memset (&data, 0, sizeof data); ! if (!evaluate_option_cache (&data, packet, &packet -> options, oc)) return; --- 308,316 ---- /* DHCPDECLINE must specify address. */ ! if (!(oc = lookup_option (&dhcp_universe, packet -> options, DHO_DHCP_REQUESTED_ADDRESS))) return; memset (&data, 0, sizeof data); ! if (!evaluate_option_cache (&data, packet, packet -> options, oc)) return; *************** *** 355,363 **** int i; struct data_string data; ! struct option_state options; struct expression *expr; struct option_cache *oc = (struct option_cache *)0; ! memset (&options, 0, sizeof options); memset (&outgoing, 0, sizeof outgoing); memset (&raw, 0, sizeof raw); --- 355,363 ---- int i; struct data_string data; ! struct option_state *options = (struct option_state *)0; struct expression *expr; struct option_cache *oc = (struct option_cache *)0; ! option_state_allocate (&options, "nak_lease"); memset (&outgoing, 0, sizeof outgoing); memset (&raw, 0, sizeof raw); *************** *** 367,370 **** --- 367,371 ---- if (!option_cache_allocate (&oc, "nak_lease")) { log_error ("No memory for DHCPNAK message type."); + option_state_dereference (&options, "nak_lease"); return; } *************** *** 372,379 **** log_error ("No memory for expr_const expression."); option_cache_dereference (&oc, "nak_lease"); return; } oc -> option = dhcp_universe.options [DHO_DHCP_MESSAGE_TYPE]; ! save_option (options.dhcp_hash, oc); option_cache_dereference (&oc, "nak_lease"); --- 373,381 ---- log_error ("No memory for expr_const expression."); option_cache_dereference (&oc, "nak_lease"); + option_state_dereference (&options, "nak_lease"); return; } oc -> option = dhcp_universe.options [DHO_DHCP_MESSAGE_TYPE]; ! save_option (&dhcp_universe, options, oc); option_cache_dereference (&oc, "nak_lease"); *************** *** 381,384 **** --- 383,387 ---- if (!option_cache_allocate (&oc, "nak_lease")) { log_error ("No memory for DHCPNAK message type."); + option_state_dereference (&options, "nak_lease"); return; } *************** *** 388,406 **** log_error ("No memory for expr_const expression."); option_cache_dereference (&oc, "nak_lease"); return; } oc -> option = dhcp_universe.options [DHO_DHCP_MESSAGE]; ! save_option (options.dhcp_hash, oc); option_cache_dereference (&oc, "nak_lease"); /* Do not use the client's requested parameter list. */ ! delete_option (packet -> options.dhcp_hash, DHO_DHCP_PARAMETER_REQUEST_LIST); /* Set up the option buffer... */ outgoing.packet_length = ! cons_options (packet, outgoing.raw, 0, &options, ! packet -> agent_options, 0, 0, 0, (struct data_string *)0); /* memset (&raw.ciaddr, 0, sizeof raw.ciaddr);*/ --- 391,411 ---- log_error ("No memory for expr_const expression."); option_cache_dereference (&oc, "nak_lease"); + option_state_dereference (&options, "nak_lease"); return; } oc -> option = dhcp_universe.options [DHO_DHCP_MESSAGE]; ! save_option (&dhcp_universe, options, oc); option_cache_dereference (&oc, "nak_lease"); /* Do not use the client's requested parameter list. */ ! delete_option (&dhcp_universe, packet -> options, DHO_DHCP_PARAMETER_REQUEST_LIST); /* Set up the option buffer... */ outgoing.packet_length = ! cons_options (packet, outgoing.raw, 0, options, ! 0, 0, 0, (struct data_string *)0); + option_state_dereference (&options, "nak_lease"); /* memset (&raw.ciaddr, 0, sizeof raw.ciaddr);*/ *************** *** 509,520 **** if (!state) log_fatal ("unable to allocate lease state!"); - memset (state, 0, sizeof *state); /* Replace the old lease hostname with the new one, if it's changed. */ ! oc = lookup_option (packet -> options.dhcp_hash, DHO_HOST_NAME); memset (&d1, 0, sizeof d1); if (oc) s1 = evaluate_option_cache (&d1, packet, ! &packet -> options, oc); if (oc && status && lease -> client_hostname && --- 514,524 ---- if (!state) log_fatal ("unable to allocate lease state!"); /* Replace the old lease hostname with the new one, if it's changed. */ ! oc = lookup_option (&dhcp_universe, packet -> options, DHO_HOST_NAME); memset (&d1, 0, sizeof d1); if (oc) s1 = evaluate_option_cache (&d1, packet, ! packet -> options, oc); if (oc && status && lease -> client_hostname && *************** *** 540,557 **** } - /* Process all of the executable statements associated with - this lease. */ - memset (&state -> options, 0, sizeof state -> options); - /* Steal the agent options from the packet. */ ! if (packet -> options.agent_options) { ! state -> options.agent_options = ! packet -> options.agent_options; ! packet -> options.agent_options = (struct agent_options *)0; } /* Execute statements in scope starting with the pool group. */ ! execute_statements_in_scope (packet, &state -> options, ! &state -> options, lease -> subnet -> group, (struct group *)0); --- 544,558 ---- } /* Steal the agent options from the packet. */ ! if (packet -> options -> universes [agent_universe.index]) { ! state -> options -> universes [agent_universe.index] = ! packet -> options -> universes [agent_universe.index]; ! packet -> options -> universes [agent_universe.index] = ! (struct agent_options *)0; } /* Execute statements in scope starting with the pool group. */ ! execute_statements_in_scope (packet, state -> options, ! state -> options, lease -> subnet -> group, (struct group *)0); *************** *** 561,566 **** for (i = packet -> class_count; i > 0; i--) { execute_statements_in_scope ! (packet, &state -> options, ! &state -> options, packet -> classes [i - 1] -> group, (lease -> pool --- 562,567 ---- for (i = packet -> class_count; i > 0; i--) { execute_statements_in_scope ! (packet, state -> options, ! state -> options, packet -> classes [i - 1] -> group, (lease -> pool *************** *** 572,577 **** /* If the lease is from a pool, run the pool scope. */ if (lease -> pool) ! execute_statements_in_scope (packet, &state -> options, ! &state -> options, lease -> pool -> group, lease -> subnet -> group); --- 573,578 ---- /* If the lease is from a pool, run the pool scope. */ if (lease -> pool) ! execute_statements_in_scope (packet, state -> options, ! state -> options, lease -> pool -> group, lease -> subnet -> group); *************** *** 580,585 **** with its group. */ if (lease -> host) ! execute_statements_in_scope (packet, &state -> options, ! &state -> options, lease -> host -> group, (lease -> pool --- 581,586 ---- with its group. */ if (lease -> host) ! execute_statements_in_scope (packet, state -> options, ! state -> options, lease -> host -> group, (lease -> pool *************** *** 590,601 **** number of seconds. */ if (offer == DHCPOFFER && ! (oc = lookup_option (state -> options.server_hash, SV_MIN_SECS))) { if (evaluate_option_cache (&d1, packet, ! &packet -> options, oc)) { if (d1.len && packet -> raw -> secs < d1.data [0]) { data_string_forget (&d1, "ack_lease"); log_info ("%s: %d secs < %d", packet -> raw -> secs, d1.data [0]); return; } --- 591,603 ---- number of seconds. */ if (offer == DHCPOFFER && ! (oc = lookup_option (&server_universe, state -> options, SV_MIN_SECS))) { if (evaluate_option_cache (&d1, packet, ! packet -> options, oc)) { if (d1.len && packet -> raw -> secs < d1.data [0]) { data_string_forget (&d1, "ack_lease"); log_info ("%s: %d secs < %d", packet -> raw -> secs, d1.data [0]); + free_lease_state (state, "ack_lease"); return; } *************** *** 613,621 **** it off the lease so that its option definitions can be used. */ ! oc = lookup_option (packet -> options.dhcp_hash, DHO_DHCP_CLIENT_IDENTIFIER); if (oc && evaluate_option_cache (&d1, packet, ! &packet -> options, oc)) { hp = find_hosts_by_uid (d1.data, d1.len); data_string_forget (&d1, "dhcpdiscover"); --- 615,623 ---- it off the lease so that its option definitions can be used. */ ! oc = lookup_option (&dhcp_universe, packet -> options, DHO_DHCP_CLIENT_IDENTIFIER); if (oc && evaluate_option_cache (&d1, packet, ! packet -> options, oc)) { hp = find_hosts_by_uid (d1.data, d1.len); data_string_forget (&d1, "dhcpdiscover"); *************** *** 636,646 **** /* Drop the request if it's not allowed for this client. */ if (!lease -> host && ! (oc = lookup_option (state -> options.server_hash, SV_BOOT_UNKNOWN_CLIENTS))) { if (evaluate_option_cache (&d1, packet, ! &packet -> options, oc)) { if (d1.len && !d1.data [0]) { log_info ("%s: unknown", msg); data_string_forget (&d1, "ack_lease"); return; } --- 638,649 ---- /* Drop the request if it's not allowed for this client. */ if (!lease -> host && ! (oc = lookup_option (&server_universe, state -> options, SV_BOOT_UNKNOWN_CLIENTS))) { if (evaluate_option_cache (&d1, packet, ! packet -> options, oc)) { if (d1.len && !d1.data [0]) { log_info ("%s: unknown", msg); data_string_forget (&d1, "ack_lease"); + free_lease_state (state, "ack_lease"); return; } *************** *** 651,661 **** /* Drop the request if it's not allowed for this client. */ if (!offer && ! (oc = lookup_option (state -> options.server_hash, SV_ALLOW_BOOTP))) { if (evaluate_option_cache (&d1, packet, ! &packet -> options, oc)) { if (d1.len && !d1.data [0]) { data_string_forget (&d1, "ack_lease"); log_info ("%s: bootp disallowed", msg); return; } --- 654,665 ---- /* Drop the request if it's not allowed for this client. */ if (!offer && ! (oc = lookup_option (&server_universe, state -> options, SV_ALLOW_BOOTP))) { if (evaluate_option_cache (&d1, packet, ! packet -> options, oc)) { if (d1.len && !d1.data [0]) { data_string_forget (&d1, "ack_lease"); log_info ("%s: bootp disallowed", msg); + free_lease_state (state, "ack_lease"); return; } *************** *** 665,674 **** /* Drop the request if booting is specifically denied. */ ! oc = lookup_option (state -> options.server_hash, SV_ALLOW_BOOTING); if (oc && ! evaluate_option_cache (&d1, packet, &packet -> options, oc)) { if (d1.len && !d1.data [0]) { log_info ("%s: booting disallowed", msg); data_string_forget (&d1, "ack_lease"); return; } --- 669,680 ---- /* Drop the request if booting is specifically denied. */ ! oc = lookup_option (&server_universe, state -> options, ! SV_ALLOW_BOOTING); if (oc && ! evaluate_option_cache (&d1, packet, packet -> options, oc)) { if (d1.len && !d1.data [0]) { log_info ("%s: booting disallowed", msg); data_string_forget (&d1, "ack_lease"); + free_lease_state (state, "ack_lease"); return; } *************** *** 706,709 **** --- 712,716 ---- log_info ("%s: no available billing", msg); + free_lease_state (state, "ack_lease"); return; } *************** *** 713,726 **** /* Figure out the filename. */ ! oc = lookup_option (state -> options.server_hash, SV_FILENAME); if (oc) evaluate_option_cache (&state -> filename, ! packet, &packet -> options, oc); /* Choose a server name as above. */ ! oc = lookup_option (state -> options.server_hash, SV_SERVER_NAME); if (oc) evaluate_option_cache (&state -> server_name, packet, ! &packet -> options, oc); /* At this point, we have a lease that we can offer the client. --- 720,734 ---- /* Figure out the filename. */ ! oc = lookup_option (&server_universe, state -> options, SV_FILENAME); if (oc) evaluate_option_cache (&state -> filename, ! packet, packet -> options, oc); /* Choose a server name as above. */ ! oc = lookup_option (&server_universe, state -> options, ! SV_SERVER_NAME); if (oc) evaluate_option_cache (&state -> server_name, packet, ! packet -> options, oc); /* At this point, we have a lease that we can offer the client. *************** *** 740,747 **** if (offer) { default_lease_time = DEFAULT_DEFAULT_LEASE_TIME; ! if ((oc = lookup_option (state -> options.server_hash, SV_DEFAULT_LEASE_TIME))) { if (evaluate_option_cache (&d1, packet, ! &packet -> options, oc)) { if (d1.len == sizeof (u_int32_t)) default_lease_time = --- 748,755 ---- if (offer) { default_lease_time = DEFAULT_DEFAULT_LEASE_TIME; ! if ((oc = lookup_option (&server_universe, state -> options, SV_DEFAULT_LEASE_TIME))) { if (evaluate_option_cache (&d1, packet, ! packet -> options, oc)) { if (d1.len == sizeof (u_int32_t)) default_lease_time = *************** *** 751,758 **** } ! if ((oc = lookup_option (packet -> options.dhcp_hash, DHO_DHCP_LEASE_TIME))) s1 = evaluate_option_cache (&d1, packet, ! &packet -> options, oc); else s1 = 0; --- 759,766 ---- } ! if ((oc = lookup_option (&dhcp_universe, packet -> options, DHO_DHCP_LEASE_TIME))) s1 = evaluate_option_cache (&d1, packet, ! packet -> options, oc); else s1 = 0; *************** *** 761,768 **** data_string_forget (&d1, "ack_lease"); max_lease_time = DEFAULT_MAX_LEASE_TIME; ! if ((oc = lookup_option (state -> options.server_hash, SV_MAX_LEASE_TIME))) { if (evaluate_option_cache (&d1, packet, ! &packet -> options, oc)) { if (d1.len == sizeof (u_int32_t)) --- 769,777 ---- data_string_forget (&d1, "ack_lease"); max_lease_time = DEFAULT_MAX_LEASE_TIME; ! if ((oc = lookup_option (&server_universe, ! state -> options, SV_MAX_LEASE_TIME))) { if (evaluate_option_cache (&d1, packet, ! packet -> options, oc)) { if (d1.len == sizeof (u_int32_t)) *************** *** 783,790 **** min_lease_time = DEFAULT_MIN_LEASE_TIME; ! if ((oc = lookup_option (state -> options.server_hash, SV_MIN_LEASE_TIME))) { if (evaluate_option_cache (&d1, packet, ! &packet -> options, oc)) { if (d1.len == sizeof (u_int32_t)) min_lease_time = getULong (d1.data); --- 792,799 ---- min_lease_time = DEFAULT_MIN_LEASE_TIME; ! if ((oc = lookup_option (&server_universe, state -> options, SV_MIN_LEASE_TIME))) { if (evaluate_option_cache (&d1, packet, ! packet -> options, oc)) { if (d1.len == sizeof (u_int32_t)) min_lease_time = getULong (d1.data); *************** *** 808,815 **** lease_time = MAX_TIME - cur_time; ! if ((oc = lookup_option (state -> options.server_hash, SV_BOOTP_LEASE_LENGTH))) { if (evaluate_option_cache (&d1, packet, ! &packet -> options, oc)) { if (d1.len == sizeof (u_int32_t)) lease_time = getULong (d1.data); --- 817,824 ---- lease_time = MAX_TIME - cur_time; ! if ((oc = lookup_option (&server_universe, state -> options, SV_BOOTP_LEASE_LENGTH))) { if (evaluate_option_cache (&d1, packet, ! packet -> options, oc)) { if (d1.len == sizeof (u_int32_t)) lease_time = getULong (d1.data); *************** *** 818,825 **** } ! if ((oc = lookup_option (state -> options.server_hash, SV_BOOTP_LEASE_CUTOFF))) { if (evaluate_option_cache (&d1, packet, ! &packet -> options, oc)) { if (d1.len == sizeof (u_int32_t)) lease_time = (getULong (d1.data) - --- 827,834 ---- } ! if ((oc = lookup_option (&server_universe, state -> options, SV_BOOTP_LEASE_CUTOFF))) { if (evaluate_option_cache (&d1, packet, ! packet -> options, oc)) { if (d1.len == sizeof (u_int32_t)) lease_time = (getULong (d1.data) - *************** *** 836,843 **** /* Record the uid, if given... */ ! oc = lookup_option (packet -> options.dhcp_hash, DHO_DHCP_CLIENT_IDENTIFIER); if (oc && ! evaluate_option_cache (&d1, packet, &packet -> options, oc)) { if (d1.len <= sizeof lt.uid_buf) { memcpy (lt.uid_buf, d1.data, d1.len); --- 845,852 ---- /* Record the uid, if given... */ ! oc = lookup_option (&dhcp_universe, packet -> options, DHO_DHCP_CLIENT_IDENTIFIER); if (oc && ! evaluate_option_cache (&d1, packet, packet -> options, oc)) { if (d1.len <= sizeof lt.uid_buf) { memcpy (lt.uid_buf, d1.data, d1.len); *************** *** 852,856 **** /* XXX inelegant */ if (!lt.uid) ! log_fatal ("can't allocate memory for large uid."); memcpy (lt.uid, d1.data, lt.uid_len); } --- 861,865 ---- /* XXX inelegant */ if (!lt.uid) ! log_fatal ("no memory for large uid."); memcpy (lt.uid, d1.data, lt.uid_len); } *************** *** 885,888 **** --- 894,898 ---- || (offer && offer != DHCPACK))) { log_info ("%s: database update failed", msg); + free_lease_state (state, "ack_lease"); return; } *************** *** 895,902 **** terminates string options and expects us to do likewise. */ lease -> flags &= ~MS_NULL_TERMINATION; ! if ((oc = lookup_option (packet -> options.dhcp_hash, DHO_HOST_NAME))) { if (evaluate_option_cache (&d1, packet, ! &packet -> options, oc)) { if (d1.data [d1.len - 1] == '\0') lease -> flags |= MS_NULL_TERMINATION; --- 905,912 ---- terminates string options and expects us to do likewise. */ lease -> flags &= ~MS_NULL_TERMINATION; ! if ((oc = lookup_option (&dhcp_universe, packet -> options, DHO_HOST_NAME))) { if (evaluate_option_cache (&d1, packet, ! packet -> options, oc)) { if (d1.data [d1.len - 1] == '\0') lease -> flags |= MS_NULL_TERMINATION; *************** *** 916,923 **** /* Get the Maximum Message Size option from the packet, if one was sent. */ ! oc = lookup_option (packet -> options.dhcp_hash, DHO_DHCP_MAX_MESSAGE_SIZE); if (oc && ! evaluate_option_cache (&d1, packet, &packet -> options, oc)) { if (d1.len == sizeof (u_int16_t)) state -> max_message_size = getUShort (d1.data); --- 926,933 ---- /* Get the Maximum Message Size option from the packet, if one was sent. */ ! oc = lookup_option (&dhcp_universe, packet -> options, DHO_DHCP_MAX_MESSAGE_SIZE); if (oc && ! evaluate_option_cache (&d1, packet, packet -> options, oc)) { if (d1.len == sizeof (u_int16_t)) state -> max_message_size = getUShort (d1.data); *************** *** 925,934 **** } - /* Steal the agent options from the packet. */ - if (packet -> agent_options) { - state -> agent_options = packet -> agent_options; - packet -> agent_options = (struct agent_options *)0; - } - /* Now, if appropriate, put in DHCP-specific options that override those. */ --- 935,938 ---- *************** *** 942,951 **** oc -> option = dhcp_universe.options [i]; ! save_option (state -> options.dhcp_hash, oc); } option_cache_dereference (&oc, "ack_lease"); } i = DHO_DHCP_SERVER_IDENTIFIER; ! if (!(oc = lookup_option (state -> options.dhcp_hash, i))) { use_primary: oc = (struct option_cache *)0; --- 946,957 ---- oc -> option = dhcp_universe.options [i]; ! save_option (&dhcp_universe, ! state -> options, oc); } option_cache_dereference (&oc, "ack_lease"); } i = DHO_DHCP_SERVER_IDENTIFIER; ! if (!(oc = lookup_option (&dhcp_universe, ! state -> options, i))) { use_primary: oc = (struct option_cache *)0; *************** *** 959,965 **** oc -> option = dhcp_universe.options [i]; ! save_option ! (state -> options.dhcp_hash, ! oc); } option_cache_dereference (&oc, "ack_lease"); --- 965,970 ---- oc -> option = dhcp_universe.options [i]; ! save_option (&dhcp_universe, ! state -> options, oc); } option_cache_dereference (&oc, "ack_lease"); *************** *** 972,976 **** } else { if (evaluate_option_cache (&d1, packet, ! &packet -> options, oc)) { if (!d1.len || d1.len > sizeof state -> from.iabuf) --- 977,981 ---- } else { if (evaluate_option_cache (&d1, packet, ! packet -> options, oc)) { if (!d1.len || d1.len > sizeof state -> from.iabuf) *************** *** 989,993 **** offered_lease_time); i = DHO_DHCP_LEASE_TIME; ! if (lookup_option (state -> options.dhcp_hash, i)) log_error ("dhcp-lease-time option for %s overridden.", inet_ntoa (state -> ciaddr)); --- 994,998 ---- offered_lease_time); i = DHO_DHCP_LEASE_TIME; ! if (lookup_option (&dhcp_universe, state -> options, i)) log_error ("dhcp-lease-time option for %s overridden.", inet_ntoa (state -> ciaddr)); *************** *** 998,1002 **** sizeof state -> expiry, 0, 0)) { oc -> option = dhcp_universe.options [i]; ! save_option (state -> options.dhcp_hash, oc); } option_cache_dereference (&oc, "ack_lease"); --- 1003,1008 ---- sizeof state -> expiry, 0, 0)) { oc -> option = dhcp_universe.options [i]; ! save_option (&dhcp_universe, ! state -> options, oc); } option_cache_dereference (&oc, "ack_lease"); *************** *** 1008,1014 **** offered_lease_time); i = DHO_DHCP_RENEWAL_TIME; ! if (lookup_option (state -> options.dhcp_hash, i)) ! log_error ("dhcp-renewal-time option for %s overridden.", ! inet_ntoa (state -> ciaddr)); oc = (struct option_cache *)0; if (option_cache_allocate (&oc, "ack_lease")) { --- 1014,1020 ---- offered_lease_time); i = DHO_DHCP_RENEWAL_TIME; ! if (lookup_option (&dhcp_universe, state -> options, i)) ! log_error ("overriding dhcp-renewal-time for %s.", ! inet_ntoa (state -> ciaddr)); oc = (struct option_cache *)0; if (option_cache_allocate (&oc, "ack_lease")) { *************** *** 1018,1022 **** sizeof state -> renewal, 0, 0)) { oc -> option = dhcp_universe.options [i]; ! save_option (state -> options.dhcp_hash, oc); } option_cache_dereference (&oc, "ack_lease"); --- 1024,1029 ---- sizeof state -> renewal, 0, 0)) { oc -> option = dhcp_universe.options [i]; ! save_option (&dhcp_universe, ! state -> options, oc); } option_cache_dereference (&oc, "ack_lease"); *************** *** 1029,1034 **** offered_lease_time); i = DHO_DHCP_REBINDING_TIME; ! if (lookup_option (state -> options.dhcp_hash, i)) ! log_error ("dhcp-rebinding-time option for %s overridden.", inet_ntoa (state -> ciaddr)); oc = (struct option_cache *)0; --- 1036,1041 ---- offered_lease_time); i = DHO_DHCP_REBINDING_TIME; ! if (lookup_option (&dhcp_universe, state -> options, i)) ! log_error ("overriding dhcp-rebinding-time for %s.", inet_ntoa (state -> ciaddr)); oc = (struct option_cache *)0; *************** *** 1038,1042 **** sizeof state -> rebind, 0, 0)) { oc -> option = dhcp_universe.options [i]; ! save_option (state -> options.dhcp_hash, oc); } option_cache_dereference (&oc, "ack_lease"); --- 1045,1050 ---- sizeof state -> rebind, 0, 0)) { oc -> option = dhcp_universe.options [i]; ! save_option (&dhcp_universe, ! state -> options, oc); } option_cache_dereference (&oc, "ack_lease"); *************** *** 1047,1051 **** mask has been provided. */ i = DHO_SUBNET_MASK; ! if (!lookup_option (state -> options.dhcp_hash, i)) { if (option_cache_allocate (&oc, "ack_lease")) { if (make_const_data (&oc -> expression, --- 1055,1059 ---- mask has been provided. */ i = DHO_SUBNET_MASK; ! if (!lookup_option (&dhcp_universe, state -> options, i)) { if (option_cache_allocate (&oc, "ack_lease")) { if (make_const_data (&oc -> expression, *************** *** 1054,1058 **** 0, 0)) { oc -> option = dhcp_universe.options [i]; ! save_option (state -> options.dhcp_hash, oc); } option_cache_dereference (&oc, "ack_lease"); --- 1062,1067 ---- 0, 0)) { oc -> option = dhcp_universe.options [i]; ! save_option (&dhcp_universe, ! state -> options, oc); } option_cache_dereference (&oc, "ack_lease"); *************** *** 1065,1074 **** i = DHO_HOST_NAME; j = SV_USE_HOST_DECL_NAMES; ! if (!lookup_option (state -> options.dhcp_hash, i) && lease -> host && lease -> host -> name && (evaluate_boolean_option_cache ! (packet, &packet -> options, (lookup_option ! (state -> options.server_hash, j))))) { oc = (struct option_cache *)0; if (option_cache_allocate (&oc, "ack_lease")) { --- 1074,1083 ---- i = DHO_HOST_NAME; j = SV_USE_HOST_DECL_NAMES; ! if (!lookup_option (&dhcp_universe, state -> options, i) && lease -> host && lease -> host -> name && (evaluate_boolean_option_cache ! (packet, packet -> options, (lookup_option ! (&server_universe, state -> options, j))))) { oc = (struct option_cache *)0; if (option_cache_allocate (&oc, "ack_lease")) { *************** *** 1079,1083 **** 1, 0)) { oc -> option = dhcp_universe.options [i]; ! save_option (state -> options.dhcp_hash, oc); } option_cache_dereference (&oc, "ack_lease"); --- 1088,1093 ---- 1, 0)) { oc -> option = dhcp_universe.options [i]; ! save_option (&dhcp_universe, ! state -> options, oc); } option_cache_dereference (&oc, "ack_lease"); *************** *** 1088,1095 **** a reverse lookup to find the hostname, do it. */ j = SV_GET_LEASE_HOSTNAMES; ! if (!lookup_option (state -> options.dhcp_hash, i) && (evaluate_boolean_option_cache ! (packet, &packet -> options, ! lookup_option (state -> options.server_hash, j)))) { struct in_addr ia; struct hostent *h; --- 1098,1105 ---- a reverse lookup to find the hostname, do it. */ j = SV_GET_LEASE_HOSTNAMES; ! if (!lookup_option (&dhcp_universe, state -> options, i) && (evaluate_boolean_option_cache ! (packet, packet -> options, ! lookup_option (&server_universe, state -> options, j)))) { struct in_addr ia; struct hostent *h; *************** *** 1110,1116 **** oc -> option = dhcp_universe.options [i]; ! save_option ! (state -> options.dhcp_hash, ! oc); } option_cache_dereference (&oc, "ack_lease"); --- 1120,1125 ---- oc -> option = dhcp_universe.options [i]; ! save_option (&dhcp_universe, ! state -> options, oc); } option_cache_dereference (&oc, "ack_lease"); *************** *** 1124,1132 **** if (evaluate_boolean_option_cache ! (packet, &state -> options, ! lookup_option (state -> options.server_hash, SV_USE_LEASE_ADDR_FOR_DEFAULT_ROUTE))) { i = DHO_ROUTERS; ! oc = lookup_option (state -> options.dhcp_hash, i); if (!oc) { oc = (struct option_cache *)0; --- 1133,1141 ---- if (evaluate_boolean_option_cache ! (packet, state -> options, ! lookup_option (&server_universe, state -> options, SV_USE_LEASE_ADDR_FOR_DEFAULT_ROUTE))) { i = DHO_ROUTERS; ! oc = lookup_option (&dhcp_universe, state -> options, i); if (!oc) { oc = (struct option_cache *)0; *************** *** 1138,1144 **** oc -> option = dhcp_universe.options [i]; ! save_option ! (state -> options.dhcp_hash, ! oc); } } --- 1147,1152 ---- oc -> option = dhcp_universe.options [i]; ! save_option (&dhcp_universe, ! state -> options, oc); } } *************** *** 1148,1161 **** } /* If the client has provided a list of options that it wishes returned, use it to prioritize. Otherwise, prioritize based on the default priority list. */ ! oc = lookup_option (packet -> options.dhcp_hash, DHO_DHCP_PARAMETER_REQUEST_LIST); if (oc) evaluate_option_cache (&state -> parameter_request_list, ! packet, &packet -> options, oc); #ifdef DEBUG_PACKET --- 1156,1190 ---- } + /* If we've been given a vendor option space, and there's something + in it, and we weren't given a vendor-encapsulated-options option, + then cons one up. */ + i = DHO_VENDOR_ENCAPSULATED_OPTIONS; + j = SV_VENDOR_OPTION_SPACE; + if (!lookup_option (&dhcp_universe, state -> options, i) && + (oc = lookup_option (&server_universe, state -> options, j)) && + evaluate_option_cache (&d1, + packet, state -> options, oc)) { + oc = (struct option_cache *)0; + if (option_cache_allocate (&oc, "ack_lease")) { + if (make_encapsulation (&oc -> expression, &d1)) { + oc -> option = dhcp_universe.options [i]; + save_option (&dhcp_universe, + state -> options, oc); + } + option_cache_dereference (&oc, "ack_lease"); + } + data_string_forget (&d1, "ack_lease"); + } + /* If the client has provided a list of options that it wishes returned, use it to prioritize. Otherwise, prioritize based on the default priority list. */ ! oc = lookup_option (&dhcp_universe, packet -> options, DHO_DHCP_PARAMETER_REQUEST_LIST); if (oc) evaluate_option_cache (&state -> parameter_request_list, ! packet, packet -> options, oc); #ifdef DEBUG_PACKET *************** *** 1253,1258 **** packet_length = cons_options ((struct packet *)0, &raw, state -> max_message_size, ! &state -> options, ! state -> agent_options, bufs, nulltp, bootpp, &state -> parameter_request_list); --- 1282,1286 ---- packet_length = cons_options ((struct packet *)0, &raw, state -> max_message_size, ! state -> options, bufs, nulltp, bootpp, &state -> parameter_request_list); *************** *** 1264,1268 **** raw.siaddr = state -> ip -> primary_address; if ((oc = ! lookup_option (state -> options.server_hash, SV_NEXT_SERVER))) { if (evaluate_option_cache (&d1, (struct packet *)0, (struct option_state *)0, oc)) { --- 1292,1297 ---- raw.siaddr = state -> ip -> primary_address; if ((oc = ! lookup_option (&server_universe, ! state -> options, SV_NEXT_SERVER))) { if (evaluate_option_cache (&d1, (struct packet *)0, (struct option_state *)0, oc)) { *************** *** 1280,1285 **** */ - option_state_dereference (&state -> options); - raw.giaddr = state -> giaddr; --- 1309,1312 ---- *************** *** 1405,1413 **** /* Look up the requested address. */ ! oc = lookup_option (packet -> options.dhcp_hash, DHO_DHCP_REQUESTED_ADDRESS); memset (&d1, 0, sizeof d1); if (oc && ! evaluate_option_cache (&d1, packet, &packet -> options, oc)) { cip.len = 4; memcpy (cip.iabuf, d1.data, cip.len); --- 1432,1440 ---- /* 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, packet -> options, oc)) { cip.len = 4; memcpy (cip.iabuf, d1.data, cip.len); *************** *** 1421,1430 **** /* Try to find a host or lease that's been assigned to the specified unique client identifier. */ ! oc = lookup_option (packet -> options.dhcp_hash, DHO_DHCP_CLIENT_IDENTIFIER); memset (&client_identifier, 0, sizeof client_identifier); if (oc && evaluate_option_cache (&client_identifier, ! packet, &packet -> options, oc)) { /* Remember this for later. */ have_client_identifier = 1; --- 1448,1457 ---- /* Try to find a host or lease that's been assigned to the specified unique client identifier. */ ! oc = lookup_option (&dhcp_universe, packet -> options, DHO_DHCP_CLIENT_IDENTIFIER); memset (&client_identifier, 0, sizeof client_identifier); if (oc && evaluate_option_cache (&client_identifier, ! packet, packet -> options, oc)) { /* Remember this for later. */ have_client_identifier = 1; *************** *** 1514,1518 **** } if ((uid_lease -> pool -> prohibit_list && ! permitted (packet, uid_lease -> pool -> prohibit_list)) || (uid_lease -> pool -> permit_list && !permitted (packet, uid_lease -> pool -> permit_list))) { --- 1541,1545 ---- } if ((uid_lease -> pool -> prohibit_list && ! permitted (packet, uid_lease -> pool -> prohibit_list)) || (uid_lease -> pool -> permit_list && !permitted (packet, uid_lease -> pool -> permit_list))) { diff -rNc2 dhcp-3.0-alpha-19990330/server/dhcpd.c dhcp-3.0-alpha-19990408/server/dhcpd.c *** dhcp-3.0-alpha-19990330/server/dhcpd.c Tue Mar 30 13:54:03 1999 --- dhcp-3.0-alpha-19990408/server/dhcpd.c Thu Apr 8 12:47:54 1999 *************** *** 23,27 **** #ifndef lint static char ocopyright[] = ! "$Id: dhcpd.c,v 1.64 1999/03/30 21:54:03 mellon Exp $ Copyright 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium."; #endif --- 23,27 ---- #ifndef lint static char ocopyright[] = ! "$Id: dhcpd.c,v 1.65 1999/04/08 19:47:54 mellon Exp $ Copyright 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium."; #endif *************** *** 29,33 **** "Copyright 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium."; static char arr [] = "All rights reserved."; ! static char message [] = "Internet Software Consortium DHCP Server V3.0-alpha 980330"; static char contrib [] = "\nPlease contribute if you find this software useful."; static char url [] = "For info, please visit http://www.isc.org/dhcp-contrib.html\n"; --- 29,33 ---- "Copyright 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium."; static char arr [] = "All rights reserved."; ! static char message [] = "Internet Software Consortium DHCP Server V3.0-alpha 980408"; static char contrib [] = "\nPlease contribute if you find this software useful."; static char url [] = "For info, please visit http://www.isc.org/dhcp-contrib.html\n"; diff -rNc2 dhcp-3.0-alpha-19990330/server/dhcpd.conf.5 dhcp-3.0-alpha-19990408/server/dhcpd.conf.5 *** dhcp-3.0-alpha-19990330/server/dhcpd.conf.5 Fri Mar 26 11:19:46 1999 --- dhcp-3.0-alpha-19990408/server/dhcpd.conf.5 Thu Apr 8 12:42:16 1999 *************** *** 855,858 **** --- 855,877 ---- .PP .B The + .I always-reply-rfc1048 + .B statement + .PP + \fBalways-reply-rfc1048\fR \fIflag\fR\fB;\fR + .PP + Some BOOTP clients expect RFC1048-style responses, but do not follow + RFC1048 when sending their requests. You can tell that a client is + having this problem if it is not getting the options you have + configured for it and if you see in the server log the message + "(non-rfc1048)" printed with each BOOTREQUEST that is logged. + .PP + If you want to send rfc1048 options to such a client, you can set the + .B always-reply-rfc1048 + option in that client's host declaration, and the DHCP server will + respond with an RFC-1048-style vendor options field. This flag can + be set in any scope, and will affect all clients covered by that + scope. + .PP + .B The .I use-lease-addr-for-default-route .B statement *************** *** 899,902 **** --- 918,995 ---- .B dhcp-options(5) manual page. + .SH VENDOR ENCAPSULATED OPTIONS + The DHCP protocol defines the \fB vendor-encapsulated-options\fR + option, which allows vendors to define their own options that will be + sent encapsulated in a standard DHCP option. The format of the + .B vendor-encapsulated-options + option is either a hunk of opaque data, or an actual option buffer + just like a standard DHCP option buffer. + .PP + You can send this option to clients in one of two ways - either define + the data directly, using a text string or a colon-seperated list of + hexadecimal values, or define an option space, define some options in + that option space, provide values for them, and specify that that + option space should be used to generate the + .B vendor-encapsulated-options + option in some scope. + .PP + To send a simple clump of data, simply provide a value for the option + in the right scope, as in the example shown earlier in the \fBCLIENT + CLASSING\fR section. + .PP + To define a new option space in which vendor options can be stored, + use the \fRoption space\fP statement: + .PP + .B option + .B space + .I name + .B ; + .PP + The name can then be used in option definitions, as described in + the + .B dhcp-options(5) + manual page. For example: + .nf + + option space SUNW; + option SUNW.server-address code 2 = ip-address; + option SUNW.server-name code 3 = text; + option SUNW.root-path code 4 = text; + + .fi + Once you have defined an option space and some options, you can set up + scopes that define values for those options, and you can say when to + use them. For example, suppose you want to handle two different + classes of clients, as in the example in the \fBCLIENT CLASSING\fR + section. Using the option space definition we just did, the + .B CLIENT + .B CLASSING + example can be implemented more legibly as follows: + .nf + class vendor-classes { + match option vendor-class-identifier; + } + + option SUNW.server-address = 172.17.65.1; + option SUNW.server-name = "sundhcp-server17-1"; + + subclass vendor-classes "SUNW.Ultra-5_10" { + vendor-option-space SUNW; + option SUNW.root-path "/export/root/sparc"; + } + + subclass vendor-classes "SUNW.i86pc" { + vendor-option-space SUNW; + option SUNW.root-path "/export/root/i86pc"; + } + + .fi + As you can see in the preceding example, regular scoping rules apply, + so you can define values that are global in the global scope, and only + define values that are specific to a particular class in the local + scope. The \fBvendor-option-space\fR declaration indicates that in + that scope, the \fBvendor-encapsulated-options\fR option should be + constructed using the values of all the options in the SUNW option + space. .SH SEE ALSO dhcpd.conf(5), dhcpd.leases(5), RFC2132, RFC2131.