diff options
-rw-r--r-- | client/dhclient.c | 4 | ||||
-rw-r--r-- | common/options.c | 470 | ||||
-rw-r--r-- | includes/dhcp.h | 12 | ||||
-rw-r--r-- | includes/dhcpd.h | 17 | ||||
-rw-r--r-- | server/bootp.c | 2 |
5 files changed, 270 insertions, 235 deletions
diff --git a/client/dhclient.c b/client/dhclient.c index a0c9536d..3a74269a 100644 --- a/client/dhclient.c +++ b/client/dhclient.c @@ -1410,7 +1410,7 @@ struct client_lease *packet_to_lease (packet, client) if (!(i & 2) && packet -> raw -> sname [0]) { unsigned len; /* Don't count on the NUL terminator. */ - for (len = 0; len < 64; len++) + for (len = 0; len < DHCP_SNAME_LEN; len++) if (!packet -> raw -> sname [len]) break; lease -> server_name = dmalloc (len + 1, MDL); @@ -1429,7 +1429,7 @@ struct client_lease *packet_to_lease (packet, client) if (!(i & 1) && packet -> raw -> file [0]) { unsigned len; /* Don't count on the NUL terminator. */ - for (len = 0; len < 64; len++) + for (len = 0; len < DHCP_FILE_LEN; len++) if (!packet -> raw -> file [len]) break; lease -> filename = dmalloc (len + 1, MDL); diff --git a/common/options.c b/common/options.c index 28f3ebcb..0dd3b594 100644 --- a/common/options.c +++ b/common/options.c @@ -505,94 +505,129 @@ int fqdn_universe_decode (struct option_state *options, return 1; } -/* cons options into a big buffer, and then split them out into the - three separate buffers if needed. This allows us to cons up a set - of vendor options using the same routine. */ - -int cons_options (inpacket, outpacket, lease, client_state, - mms, in_options, cfg_options, - scope, overload, terminate, bootpp, prl, vuname) - struct packet *inpacket; - struct dhcp_packet *outpacket; - struct lease *lease; - struct client_state *client_state; - int mms; - struct option_state *in_options; - struct option_state *cfg_options; - struct binding_scope **scope; - int overload; /* Overload flags that may be set. */ - int terminate; - int bootpp; - struct data_string *prl; - const char *vuname; +/* + * Load all options into a buffer, and then split them out into the three + * separate fields in the dhcp packet (options, file, and sname) where + * options can be stored. + */ +int +cons_options(struct packet *inpacket, struct dhcp_packet *outpacket, + struct lease *lease, struct client_state *client_state, + int mms, struct option_state *in_options, + struct option_state *cfg_options, + struct binding_scope **scope, + int overload_avail, int terminate, int bootpp, + struct data_string *prl, const char *vuname) { #define PRIORITY_COUNT 300 - unsigned priority_list [PRIORITY_COUNT]; + unsigned priority_list[PRIORITY_COUNT]; int priority_len; - unsigned char buffer [4096]; /* Really big buffer... */ - unsigned main_buffer_size, mb_max; - unsigned mainbufix, agentix; - unsigned option_size; + unsigned char buffer[4096], agentopts[1024]; + unsigned index = 0; + unsigned mb_size = 0, mb_max = 0; + unsigned option_size = 0, agent_size = 0; unsigned length; int i; struct option_cache *op; struct data_string ds; pair pp, *hash; - int need_endopt = 0; - int ocount = 0; - int ofbuf1=0, ofbuf2=0; + int overload_used = 0; + int of1 = 0, of2 = 0; - memset (&ds, 0, sizeof ds); + memset(&ds, 0, sizeof ds); - /* If there's a Maximum Message Size option in the incoming packet - and no alternate maximum message size has been specified, take the - one in the packet. */ + /* + * If there's a Maximum Message Size option in the incoming packet + * and no alternate maximum message size has been specified, or + * if the one specified in the packet is shorter than the + * alternative, take the one in the packet. + */ if (inpacket && - (op = lookup_option (&dhcp_universe, inpacket -> options, + (op = lookup_option(&dhcp_universe, inpacket->options, DHO_DHCP_MAX_MESSAGE_SIZE))) { - evaluate_option_cache (&ds, inpacket, + evaluate_option_cache(&ds, inpacket, lease, client_state, in_options, cfg_options, scope, op, MDL); if (ds.len >= sizeof (u_int16_t)) { - i = getUShort (ds.data); - + i = getUShort(ds.data); if(!mms || (i < mms)) mms = i; } - data_string_forget (&ds, MDL); + data_string_forget(&ds, MDL); } - /* If the client has provided a maximum DHCP message size, - use that; otherwise, if it's BOOTP, only 64 bytes; otherwise - use up to the minimum IP MTU size (576 bytes). */ - /* XXX if a BOOTP client specifies a max message size, we will - honor it. */ - + /* + * If the client has provided a maximum DHCP message size, + * use that, up to the MTU limit. Otherwise, if it's BOOTP, + * only 64 bytes; otherwise use up to the minimum IP MTU size + * (576 bytes). + * + * XXX if a BOOTP client specifies a max message size, we will + * honor it. + */ if (mms) { - main_buffer_size = mms - DHCP_FIXED_LEN; - - /* Enforce a minimum packet size... */ - if (main_buffer_size < (576 - DHCP_FIXED_LEN)) - main_buffer_size = 576 - DHCP_FIXED_LEN; + if (mms < DHCP_MTU_MIN) + /* Enforce minimum packet size, per RFC 2132 */ + mb_size = DHCP_MIN_OPTION_LEN; + else if (mms > DHCP_MTU_MAX) + /* + * TODO: Packets longer than 1500 bytes really + * should be allowed, but it requires upstream + * changes to the way the packet is allocated. For + * now, we forbid them. They won't be needed very + * often anyway. + */ + mb_size = DHCP_MAX_OPTION_LEN; + else + mb_size = mms - DHCP_FIXED_LEN; } else if (bootpp) { - if (inpacket) { - main_buffer_size = - inpacket -> packet_length - DHCP_FIXED_LEN; - if (main_buffer_size < 64) - main_buffer_size = 64; - } else - main_buffer_size = 64; + mb_size = 64; + if (inpacket != NULL && + (inpacket->packet_length - DHCP_FIXED_LEN >= 64)) + mb_size = inpacket->packet_length - DHCP_FIXED_LEN; } else - main_buffer_size = 576 - DHCP_FIXED_LEN; + mb_size = DHCP_MIN_OPTION_LEN; - /* Set a hard limit at the size of the output buffer. */ - mb_max = sizeof(buffer) - (((overload & 1) ? DHCP_FILE_LEN : 0) + - ((overload & 2) ? DHCP_SNAME_LEN : 0)); - if (main_buffer_size > mb_max) - main_buffer_size = mb_max; + /* + * If answering a client message, see whether any relay agent + * options were included with the message. If so, save them + * to copy back in later, and make space in the main buffer + * to accomodate them + */ + if (client_state == NULL) { + priority_list[0] = DHO_DHCP_AGENT_OPTIONS; + priority_len = 1; + agent_size = store_options(NULL, agentopts, 0, + sizeof(agentopts), + inpacket, lease, client_state, + in_options, cfg_options, scope, + priority_list, priority_len, + 0, 0, 0, NULL); + + mb_size += agent_size; + if (mb_size > DHCP_MAX_OPTION_LEN) + mb_size = DHCP_MAX_OPTION_LEN; + } - /* Preload the option priority list with protocol-mandatory options. + /* + * Set offsets for buffer data to be copied into filename + * and servername fields + */ + mb_max = mb_size; + + if (overload_avail & 1) { + of1 = mb_max; + mb_max += DHCP_FILE_LEN; + } + + if (overload_avail & 2) { + of2 = mb_max; + mb_max += DHCP_SNAME_LEN; + } + + /* + * Preload the option priority list with protocol-mandatory options. * This effectively gives these options the highest priority. */ priority_len = 0; @@ -603,25 +638,27 @@ int cons_options (inpacket, outpacket, lease, client_state, priority_list[priority_len++] = DHO_DHCP_REQUESTED_ADDRESS; priority_list[priority_len++] = DHO_ASSOCIATED_IP; - if (prl && prl -> len > 0) { - if ((op = lookup_option (&dhcp_universe, cfg_options, + if (prl != NULL && prl->len > 0) { + if ((op = lookup_option(&dhcp_universe, cfg_options, DHO_SUBNET_SELECTION))) { if (priority_len < PRIORITY_COUNT) - priority_list [priority_len++] = + priority_list[priority_len++] = DHO_SUBNET_SELECTION; } - data_string_truncate (prl, (PRIORITY_COUNT - priority_len)); + data_string_truncate(prl, (PRIORITY_COUNT - priority_len)); - for (i = 0; i < prl -> len; i++) { - /* Prevent client from changing order of delivery - of relay agent information option. */ - if (prl -> data [i] != DHO_DHCP_AGENT_OPTIONS) - priority_list [priority_len++] = - prl -> data [i]; + for (i = 0; i < prl->len; i++) { + /* + * Prevent client from changing order of delivery + * of relay agent information option. + */ + if (prl->data[i] != DHO_DHCP_AGENT_OPTIONS) + priority_list[priority_len++] = prl->data[i]; } - /* If the client doesn't request the FQDN option explicitly, + /* + * If the client doesn't request the FQDN option explicitly, * to indicate priority, consider it lowest priority. Fit * in the packet if there is space. Note that the option * may only be included if the client supplied one. @@ -631,7 +668,8 @@ int cons_options (inpacket, outpacket, lease, client_state, DHO_FQDN) != NULL)) priority_list[priority_len++] = DHO_FQDN; - /* Some DHCP Servers will give the subnet-mask option if + /* + * Some DHCP Servers will give the subnet-mask option if * it is not on the parameter request list - so some client * implementations have come to rely on this - so we will * also make sure we supply this, at lowest priority. @@ -645,9 +683,9 @@ int cons_options (inpacket, outpacket, lease, client_state, ((inpacket->packet_type == DHCPDISCOVER) || (inpacket->packet_type == DHCPREQUEST))) priority_list[priority_len++] = DHO_SUBNET_MASK; - } else { - /* First, hardcode some more options that ought to be + /* + * First, hardcode some more options that ought to be * sent first...these are high priority to have in the * packet. */ @@ -657,154 +695,131 @@ int cons_options (inpacket, outpacket, lease, client_state, priority_list[priority_len++] = DHO_HOST_NAME; priority_list[priority_len++] = DHO_FQDN; - /* Append a list of the standard DHCP options from the - standard DHCP option space. Actually, if a site - option space hasn't been specified, we wind up - treating the dhcp option space as the site option - space, and the first for loop is skipped, because - it's slightly more general to do it this way, - taking the 1Q99 DHCP futures work into account. */ - if (cfg_options -> site_code_min) { + /* + * Append a list of the standard DHCP options from the + * standard DHCP option space. Actually, if a site + * option space hasn't been specified, we wind up + * treating the dhcp option space as the site option + * space, and the first for loop is skipped, because + * it's slightly more general to do it this way, + * taking the 1Q99 DHCP futures work into account. + */ + if (cfg_options->site_code_min) { for (i = 0; i < OPTION_HASH_SIZE; i++) { - hash = cfg_options -> universes [dhcp_universe.index]; + hash = cfg_options->universes[dhcp_universe.index]; if (hash) { - for (pp = hash [i]; pp; pp = pp -> cdr) { - op = (struct option_cache *)(pp -> car); - if (op -> option -> code < - cfg_options -> site_code_min && + for (pp = hash[i]; pp; pp = pp->cdr) { + op = (struct option_cache *)(pp->car); + if (op->option->code < + cfg_options->site_code_min && priority_len < PRIORITY_COUNT && - (op -> option -> code != - DHO_DHCP_AGENT_OPTIONS)) - priority_list [priority_len++] = - op -> option -> code; + op->option->code != DHO_DHCP_AGENT_OPTIONS) + priority_list[priority_len++] = + op->option->code; } } } } - /* Now cycle through the site option space, or if there - is no site option space, we'll be cycling through the - dhcp option space. */ + /* + * Now cycle through the site option space, or if there + * is no site option space, we'll be cycling through the + * dhcp option space. + */ for (i = 0; i < OPTION_HASH_SIZE; i++) { - hash = (cfg_options -> universes - [cfg_options -> site_universe]); - if (hash) - for (pp = hash [i]; pp; pp = pp -> cdr) { - op = (struct option_cache *)(pp -> car); - if (op -> option -> code >= - cfg_options -> site_code_min && + hash = cfg_options->universes[cfg_options->site_universe]; + if (hash != NULL) + for (pp = hash[i]; pp; pp = pp->cdr) { + op = (struct option_cache *)(pp->car); + if (op->option->code >= + cfg_options->site_code_min && priority_len < PRIORITY_COUNT && - (op -> option -> code != - DHO_DHCP_AGENT_OPTIONS)) - priority_list [priority_len++] = - op -> option -> code; + op->option->code != DHO_DHCP_AGENT_OPTIONS) + priority_list[priority_len++] = + op->option->code; } } - /* Put any spaces that are encapsulated on the list, + /* + * Put any spaces that are encapsulated on the list, * sort out whether they contain values later. */ - for (i = 0; i < cfg_options -> universe_count; i++) { + for (i = 0; i < cfg_options->universe_count; i++) { if (universes[i]->enc_opt && priority_len < PRIORITY_COUNT && - universes [i] -> enc_opt -> universe == &dhcp_universe) - { - if (universes [i] -> enc_opt -> code != + universes[i]->enc_opt->universe == &dhcp_universe) { + if (universes[i]->enc_opt->code != DHO_DHCP_AGENT_OPTIONS) - priority_list [priority_len++] = - universes [i] -> enc_opt -> code; + priority_list[priority_len++] = + universes[i]->enc_opt->code; } } - /* The vendor option space can't stand on its own, so always - add it to the list. */ + /* + * The vendor option space can't stand on its own, so always + * add it to the list. + */ if (priority_len < PRIORITY_COUNT) - priority_list [priority_len++] = + priority_list[priority_len++] = DHO_VENDOR_ENCAPSULATED_OPTIONS; } - /* Figure out the overload buffer offset(s). */ - if (overload) { - ofbuf1 = main_buffer_size - 4; - if (overload == 3) - ofbuf2 = main_buffer_size - 4 + DHCP_FILE_LEN; - } + /* Put the cookie up front... */ + memcpy(buffer, DHCP_OPTIONS_COOKIE, 4); + index += 4; /* Copy the options into the big buffer... */ - option_size = store_options (&ocount, buffer, - (main_buffer_size - 4 + - ((overload & 1) ? DHCP_FILE_LEN : 0) + - ((overload & 2) ? DHCP_SNAME_LEN : 0)), - inpacket, lease, client_state, - in_options, cfg_options, scope, - priority_list, priority_len, - ofbuf1, ofbuf2, terminate, vuname); - /* If store_options failed. */ + option_size = store_options(&overload_used, buffer, index, mb_max, + inpacket, lease, client_state, + in_options, cfg_options, scope, + priority_list, priority_len, + of1, of2, terminate, vuname); + + /* If store_options() failed */ if (option_size == 0) return 0; - if (overload) { - if (ocount == 1 && (overload & 1)) - overload = 1; - else if (ocount == 1 && (overload & 2)) - overload = 2; - else if (ocount == 3) - overload = 3; - else - overload = 0; - } - /* Put the cookie up front... */ - memcpy (outpacket -> options, DHCP_OPTIONS_COOKIE, 4); - mainbufix = 4; - - /* If we're going to have to overload, store the overload - option at the beginning. If we can, though, just store the - whole thing in the packet's option buffer and leave it at - that. */ - memcpy (&outpacket -> options [mainbufix], - buffer, option_size); - mainbufix += option_size; - if (overload) { - outpacket -> options [mainbufix++] = DHO_DHCP_OPTION_OVERLOAD; - outpacket -> options [mainbufix++] = 1; - outpacket -> options [mainbufix++] = overload; - - if (overload & 1) { - memcpy (outpacket -> file, - &buffer [ofbuf1], DHCP_FILE_LEN); - } - if (overload & 2) { - if (ofbuf2) { - memcpy (outpacket -> sname, &buffer [ofbuf2], - DHCP_SNAME_LEN); - } else { - memcpy (outpacket -> sname, &buffer [ofbuf1], - DHCP_SNAME_LEN); - } - } + /* How much was stored in the main buffer? */ + index += option_size; + + /* + * If we're going to have to overload, store the overload + * option first. + */ + if (overload_used) { + if (mb_size - agent_size - index < 3) + return 0; + + buffer[index++] = DHO_DHCP_OPTION_OVERLOAD; + buffer[index++] = 1; + buffer[index++] = overload_used; + + if (overload_used & 1) + memcpy(outpacket->file, &buffer[of1], DHCP_FILE_LEN); + + if (overload_used & 2) + memcpy(outpacket->sname, &buffer[of2], DHCP_SNAME_LEN); } - agentix = mainbufix; - if (mainbufix < main_buffer_size) - need_endopt = 1; - length = DHCP_FIXED_NON_UDP + mainbufix; - /* Now hack in the agent options if there are any. */ - priority_list [0] = DHO_DHCP_AGENT_OPTIONS; - priority_len = 1; - agentix += - store_options (0, &outpacket -> options [agentix], - DHCP_OPTION_LEN - agentix, - inpacket, lease, client_state, - in_options, cfg_options, scope, - priority_list, priority_len, - 0, 0, 0, (char *)0); + /* Now copy in preserved agent options, if any */ + if (agent_size) { + if (mb_size - index >= agent_size) { + memcpy(&buffer[index], agentopts, agent_size); + index += agent_size; + } else + log_error("Unable to store relay agent information" + "in reply packet."); + } /* Tack a DHO_END option onto the packet if we need to. */ - if (agentix < DHCP_OPTION_LEN && need_endopt) - outpacket -> options [agentix++] = DHO_END; + if (index < mb_size) + buffer[index++] = DHO_END; + + /* Copy main buffer into the options buffer of the packet */ + memcpy(outpacket->options, buffer, index); /* Figure out the length. */ - length = DHCP_FIXED_NON_UDP + agentix; + length = DHCP_FIXED_NON_UDP + index; return length; } @@ -1066,25 +1081,21 @@ store_options6(char *buf, int buflen, return bufpos; } -/* Store all the requested options into the requested buffer. */ - -int store_options (ocount, buffer, buflen, packet, lease, client_state, - in_options, cfg_options, scope, priority_list, priority_len, - first_cutoff, second_cutoff, terminate, vuname) - int *ocount; - unsigned char *buffer; - unsigned buflen; - struct packet *packet; - struct lease *lease; - struct client_state *client_state; - struct option_state *in_options; - struct option_state *cfg_options; - struct binding_scope **scope; - unsigned *priority_list; - int priority_len; - unsigned first_cutoff, second_cutoff; - int terminate; - const char *vuname; +/* + * Store all the requested options into the requested buffer. + * XXX: ought to be static + */ +int +store_options(int *ocount, + unsigned char *buffer, unsigned index, unsigned buflen, + struct packet *packet, struct lease *lease, + struct client_state *client_state, + struct option_state *in_options, + struct option_state *cfg_options, + struct binding_scope **scope, + unsigned *priority_list, int priority_len, + unsigned first_cutoff, int second_cutoff, int terminate, + const char *vuname) { int bufix = 0, six = 0, tix = 0; int i; @@ -1093,24 +1104,39 @@ int store_options (ocount, buffer, buflen, packet, lease, client_state, int bufend, sbufend; struct data_string od; struct option_cache *oc; - struct option *option=NULL; + struct option *option = NULL; unsigned code; + /* + * These arguments are relative to the start of the buffer, so + * reduce them by the current buffer index, and advance the + * buffer pointer to where we're going to start writing. + */ + buffer = &buffer[index]; + buflen -= index; + if (first_cutoff) + first_cutoff -= index; + if (second_cutoff) + second_cutoff -= index; + + /* Calculate the start and end of each section of the buffer */ + bufend = sbufend = buflen; if (first_cutoff) { if (first_cutoff >= buflen) log_fatal("%s:%d:store_options: Invalid first cutoff.", MDL); - bufend = first_cutoff; - } else - bufend = buflen; - if (second_cutoff) { + if (second_cutoff) { + if (second_cutoff >= buflen) + log_fatal("%s:%d:store_options: Invalid second cutoff.", + MDL); + sbufend = second_cutoff; + } + } else if (second_cutoff) { if (second_cutoff >= buflen) log_fatal("%s:%d:store_options: Invalid second cutoff.", MDL); - - sbufend = second_cutoff; - } else - sbufend = buflen; + bufend = second_cutoff; + } memset (&od, 0, sizeof od); @@ -1428,7 +1454,8 @@ int store_options (ocount, buffer, buflen, packet, lease, client_state, log_fatal("Second buffer overflow in overloaded options."); buffer[first_cutoff + six] = DHO_END; - *ocount |= 1; /* So that caller knows there's data there. */ + if (ocount != NULL) + *ocount |= 1; /* So that caller knows there's data there. */ } if (second_cutoff && tix) { @@ -1439,7 +1466,8 @@ int store_options (ocount, buffer, buflen, packet, lease, client_state, log_fatal("Third buffer overflow in overloaded options."); buffer[second_cutoff + tix] = DHO_END; - *ocount |= 2; /* So that caller knows there's data there. */ + if (ocount != NULL) + *ocount |= 2; /* So that caller knows there's data there. */ } if ((six || tix) && (bufix + 3 > bufend)) @@ -2674,7 +2702,7 @@ int option_space_encapsulate (result, packet, lease, client_state, universe_hash_lookup(&u, universe_hash, (const char *)name->data, name->len, MDL); if (u == NULL) { - log_error("option_space_encapsulate: option space %.*s does " + log_error("option_space_encapsulate: option space '%.*s' does " "not exist, but is configured.", (int)name->len, name->data); return status; @@ -2685,7 +2713,7 @@ int option_space_encapsulate (result, packet, lease, client_state, in_options, cfg_options, scope, u)) status = 1; } else - log_error("encapsulation requested for %s with no support.", + log_error("encapsulation requested for '%s' with no support.", name->data); return status; @@ -2695,7 +2723,7 @@ int option_space_encapsulate (result, packet, lease, client_state, * placed on the option buffer by the above (configuring a value in * the space over-rides any values in the child universe). * - * Note that there are far fewer universes than there will every be + * Note that there are far fewer universes than there will ever be * options in any universe. So it is faster to traverse the * configured universes, checking if each is encapsulated in the * current universe, and if so attempting to do so. diff --git a/includes/dhcp.h b/includes/dhcp.h index 1ee7b7b9..ee23a29d 100644 --- a/includes/dhcp.h +++ b/includes/dhcp.h @@ -34,17 +34,19 @@ #define DHCP_H #define DHCP_UDP_OVERHEAD (20 + /* IP header */ \ - 8) /* UDP header */ + 8) /* UDP header */ #define DHCP_SNAME_LEN 64 #define DHCP_FILE_LEN 128 #define DHCP_FIXED_NON_UDP 236 #define DHCP_FIXED_LEN (DHCP_FIXED_NON_UDP + DHCP_UDP_OVERHEAD) /* Everything but options. */ +#define BOOTP_MIN_LEN 300 + #define DHCP_MTU_MAX 1500 -#define DHCP_OPTION_LEN (DHCP_MTU_MAX - DHCP_FIXED_LEN) +#define DHCP_MTU_MIN 576 -#define BOOTP_MIN_LEN 300 -#define DHCP_MIN_LEN 548 +#define DHCP_MAX_OPTION_LEN (DHCP_MTU_MAX - DHCP_FIXED_LEN) +#define DHCP_MIN_OPTION_LEN (DHCP_MTU_MIN - DHCP_FIXED_LEN) struct dhcp_packet { u_int8_t op; /* 0: Message opcode/type */ @@ -61,7 +63,7 @@ struct dhcp_packet { unsigned char chaddr [16]; /* 24: Client hardware address */ char sname [DHCP_SNAME_LEN]; /* 40: Server name */ char file [DHCP_FILE_LEN]; /* 104: Boot filename */ - unsigned char options [DHCP_OPTION_LEN]; + unsigned char options [DHCP_MAX_OPTION_LEN]; /* 212: Optional parameters (actual length dependent on MTU). */ }; diff --git a/includes/dhcpd.h b/includes/dhcpd.h index d80b5fc9..7c7ddba9 100644 --- a/includes/dhcpd.h +++ b/includes/dhcpd.h @@ -1399,12 +1399,17 @@ fqdn6_universe_decode(struct option_state *options, struct universe *u); int append_option(struct data_string *dst, struct universe *universe, struct option *option, struct data_string *src); -int store_options PROTO ((int *, unsigned char *, unsigned, struct packet *, - struct lease *, struct client_state *, - struct option_state *, - struct option_state *, struct binding_scope **, - unsigned *, int, unsigned, unsigned, - int, const char *)); +int +store_options(int *ocount, + unsigned char *buffer, unsigned buflen, unsigned index, + struct packet *packet, struct lease *lease, + struct client_state *client_state, + struct option_state *in_options, + struct option_state *cfg_options, + struct binding_scope **scope, + unsigned *priority_list, int priority_len, + unsigned first_cutoff, int second_cutoff, int terminate, + const char *vuname); int store_options6(char *, int, struct option_state *, struct packet *, const int *, struct data_string *); int format_has_text(const char *); diff --git a/server/bootp.c b/server/bootp.c index 24afe939..aff4a33a 100644 --- a/server/bootp.c +++ b/server/bootp.c @@ -218,7 +218,7 @@ void bootp (packet) lookup_option (&server_universe, options, SV_ALWAYS_REPLY_RFC1048), MDL))) { memcpy (outgoing.raw -> options, - packet -> raw -> options, DHCP_OPTION_LEN); + packet -> raw -> options, DHCP_MAX_OPTION_LEN); outgoing.packet_length = BOOTP_MIN_LEN; } else { |