diff --git a/RELNOTES b/RELNOTES index 692af08e..727e0b66 100644 --- a/RELNOTES +++ b/RELNOTES @@ -63,6 +63,10 @@ and for prodding me into improving it. - RFC3942 compliance, site-local option spaces start at 224 now, not 128. ||| THIS NEEDS TO BE SPELLED OUT IN THE NEW FEATURES LIST ||| +- The IO system now tracks all local IP addresses, so that the DHCP + applications (particularly the dhcrelay) can discern between what frames + were tranmsitted to it, and what frames are being carried through it which + it should not intercept. Changes since 3.0.4b2 diff --git a/client/dhclient.c b/client/dhclient.c index 762d6d76..29d600e9 100644 --- a/client/dhclient.c +++ b/client/dhclient.c @@ -32,7 +32,7 @@ #ifndef lint static char ocopyright[] = -"$Id: dhclient.c,v 1.133 2006/02/24 23:16:27 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n"; +"$Id: dhclient.c,v 1.134 2006/02/27 23:56:12 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -227,6 +227,8 @@ int main (argc, argv, envp) } } + limited_broadcast.s_addr = INADDR_BROADCAST; + if (!no_dhclient_conf && (s = getenv ("PATH_DHCLIENT_CONF"))) { path_dhclient_conf = s; } diff --git a/common/ctrace.c b/common/ctrace.c index e5042ec6..5e8bcc09 100644 --- a/common/ctrace.c +++ b/common/ctrace.c @@ -32,7 +32,7 @@ #ifndef lint static char copyright[] = -"$Id: ctrace.c,v 1.4 2005/03/17 20:14:57 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; +"$Id: ctrace.c,v 1.5 2006/02/27 23:56:13 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -46,8 +46,10 @@ void trace_interface_register (trace_type_t *ttype, struct interface_info *ip) memset (&tipkt, 0, sizeof tipkt); memcpy (&tipkt.hw_address, &ip -> hw_address, sizeof ip -> hw_address); - memcpy (&tipkt.primary_address, - &ip -> primary_address, sizeof ip -> primary_address); + if (ip -> address_count > 0) + memcpy (&tipkt.primary_address, + &ip -> addresses [0], + sizeof ip -> addresses [0]); memcpy (tipkt.name, ip -> name, sizeof ip -> name); tipkt.index = htonl (ip -> index); @@ -87,8 +89,12 @@ void trace_interface_input (trace_type_t *ttype, unsigned len, char *buf) memcpy (&ip -> hw_address, &tipkt -> hw_address, sizeof ip -> hw_address); - memcpy (&ip -> primary_address, &tipkt -> primary_address, - sizeof ip -> primary_address); + ip -> address_count = ip -> address_max = 1; + ip -> addresses = dmalloc (sizeof (struct in_addr), MDL); + if (!ip -> addresses) + log_fatal ("Can't allocate address buffer for trace interface"); + memcpy (&ip -> addresses [0], &tipkt -> primary_address, + sizeof ip -> addresses [0]); memcpy (ip -> name, tipkt -> name, sizeof ip -> name); ip -> index = ntohl (tipkt -> index); @@ -102,7 +108,7 @@ void trace_interface_input (trace_type_t *ttype, unsigned len, char *buf) ip -> ifp -> ifr_addr.sa_len = sizeof (struct sockaddr_in); #endif sin = (struct sockaddr_in *)&ip -> ifp -> ifr_addr; - sin -> sin_addr = ip -> primary_address; + sin -> sin_addr = ip -> addresses [0]; addr.len = 4; memcpy (addr.iabuf, &sin -> sin_addr.s_addr, addr.len); diff --git a/common/discover.c b/common/discover.c index 16796d78..4d22d149 100644 --- a/common/discover.c +++ b/common/discover.c @@ -34,7 +34,7 @@ #ifndef lint static char copyright[] = -"$Id: discover.c,v 1.49 2006/02/24 23:16:28 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n"; +"$Id: discover.c,v 1.50 2006/02/27 23:56:13 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -307,8 +307,38 @@ void discover_interfaces (state) if (foo.sin_addr.s_addr == htonl (INADDR_LOOPBACK) && ((tmp -> flags & INTERFACE_AUTOMATIC) && state == DISCOVER_SERVER)) - continue; + continue; + /* If the only address we have is 0.0.0.0, we + shouldn't consider the interface configured. */ + if (foo.sin_addr.s_addr != htonl(INADDR_ANY)) + tmp->configured = 1; + + if (!tmp -> addresses) { + tmp -> addresses = + dmalloc (10 * sizeof (struct in_addr), + MDL); + if (!tmp -> addresses) + log_fatal ("no memory for ifaddrlist"); + tmp -> address_count = 0; + tmp -> address_max = 10; + } else if (tmp -> address_count >= tmp -> address_max) { + struct in_addr *ta; + int newmax = tmp -> address_max * 2; + ta = dmalloc (newmax * + sizeof (struct in_addr), MDL); + if (!ta) + log_fatal ("no memory for new " + "ifaddrlist"); + memcpy (ta, tmp -> addresses, + tmp -> address_max * + sizeof (struct in_addr)); + dfree (tmp -> addresses, MDL); + tmp -> addresses = ta; + tmp -> address_max = newmax; + } + tmp -> addresses [tmp -> address_count++] = + foo.sin_addr; /* If this is the first real IP address we've found, keep a pointer to ifreq structure in @@ -325,7 +355,6 @@ void discover_interfaces (state) log_fatal ("no space for ifp."); memcpy (tif, ifp, len); tmp -> ifp = tif; - tmp -> primary_address = foo.sin_addr; } /* Grab the address... */ @@ -1138,6 +1167,12 @@ void interface_stash (struct interface_info *tptr) } interface_vector = vec; } + if (interface_vector [tptr -> index]) { + log_fatal("invalid tracefile - two interfaces with " + "same index - %s and %s", + interface_vector [tptr->index] -> name, + tptr -> name); + } interface_reference (&interface_vector [tptr -> index], tptr, MDL); if (tptr -> index >= interface_count) interface_count = tptr -> index + 1; diff --git a/common/packet.c b/common/packet.c index 830c276a..57702fcb 100644 --- a/common/packet.c +++ b/common/packet.c @@ -33,7 +33,7 @@ #ifndef lint static char copyright[] = -"$Id: packet.c,v 1.42 2005/03/17 20:14:59 dhankins Exp $ Copyright (c) 2004-2005 Internet Systems Consortium. All rights reserved.\n"; +"$Id: packet.c,v 1.43 2006/02/27 23:56:13 dhankins Exp $ Copyright (c) 2004-2005 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -231,6 +231,8 @@ ssize_t decode_udp_ip_header (interface, buf, bufix, from, buflen) unsigned len; unsigned ulen; int ignore = 0; + struct interface_info *ii; + int i; memcpy(&ip, buf + bufix, sizeof (struct ip)); udp = (struct udphdr *)(buf + bufix + ip_len); @@ -245,6 +247,38 @@ ssize_t decode_udp_ip_header (interface, buf, bufix, from, buflen) return -1; #endif /* USERLAND_FILTER */ + /* Eliminate packets that we might have accidentally intercepted because + we are doing routing. */ + + /* The DHCP client may not have an IP address; in that case, if we + got the packet, we need to look at it. So if address_count is + zero on the interface on which we received the packet, accept the + packet. */ + if (!interface -> configured) + goto good; + + /* XXX we should handle subnet broadcast addresses here. */ + /* XXX we should compare against 255.255.255.255, not limited_broadcast, + XXX because sometimes we tweak limited_broadcast for debugging. + XXX This is only currently a problem on the server. */ + if (ip.ip_dst.s_addr == limited_broadcast.s_addr) + goto good; + + /* Check IP addresses of _all_ interfaces - it's perfectly okay to send + a packet to an IP address on one interface that happens to arrive + through another interface. */ + /* XXX if the user excluded some interfaces, we will not accept packets + XXX for those interfaces. */ + for (ii = interfaces; ii; ii = ii -> next) { + for (i = 0; i < ii -> address_count; i++) { + if (ii -> addresses [i].s_addr == ip.ip_dst.s_addr) + goto good; + } + } + /* The IP destination address didn't match any of our addresses. */ + return -1; + + good: ulen = ntohs (udp -> uh_ulen); if (ulen < sizeof *udp || ((unsigned char *)udp) + ulen > buf + bufix + buflen) { diff --git a/includes/dhcpd.h b/includes/dhcpd.h index d9c911fc..36b74c81 100644 --- a/includes/dhcpd.h +++ b/includes/dhcpd.h @@ -779,6 +779,12 @@ struct client_state { struct option_state *sent_options; /* Options we sent. */ }; +/* Relay agent server list. */ +struct server_list { + struct server_list *next; + struct sockaddr_in to; +} *servers; + /* Information about each network interface. */ struct interface_info { @@ -787,7 +793,12 @@ struct interface_info { struct shared_network *shared_network; /* Networks connected to this interface. */ struct hardware hw_address; /* Its physical address. */ - struct in_addr primary_address; /* Primary interface address. */ + struct in_addr *addresses; /* Addresses associated with + interface. */ + int address_count; /* Number of addresses associated with + interface. */ + int address_max; /* Max number of addresses we can + store in current buffer. */ u_int8_t *circuit_id; /* Circuit ID associated with this interface. */ @@ -796,6 +807,8 @@ struct interface_info { u_int8_t *remote_id; /* Remote ID associated with this interface (if any). */ unsigned remote_id_len; /* Length of Remote ID. */ + struct server_list *servers; /* List of relay servers for this + interface. */ char name [IFNAMSIZ]; /* Its name... */ int index; /* Its index. */ @@ -808,6 +821,9 @@ struct interface_info { size_t rbuf_len; /* Length of data in buffer. */ struct ifreq *ifp; /* Pointer to ifreq struct. */ + int configured; /* If set to 1, interface has at + * least one valid IP address. + */ u_int32_t flags; /* Control flags... */ #define INTERFACE_REQUESTED 1 #define INTERFACE_AUTOMATIC 2 @@ -2037,6 +2053,7 @@ int parse_ip_addr PROTO ((struct parse *, struct iaddr *)); void parse_reject_statement PROTO ((struct parse *, struct client_config *)); /* dhcrelay.c */ +void new_relay_server (char *, struct server_list **); void relay PROTO ((struct interface_info *, struct dhcp_packet *, unsigned, unsigned int, struct iaddr, struct hardware *)); int strip_relay_agent_options PROTO ((struct interface_info *, diff --git a/relay/dhcrelay.8 b/relay/dhcrelay.8 index 05b6dabc..1e0a9a9c 100644 --- a/relay/dhcrelay.8 +++ b/relay/dhcrelay.8 @@ -27,7 +27,7 @@ .\" see ``http://www.isc.org/isc''. To learn more about Vixie .\" Enterprises, see ``http://www.vix.com''. .\" -.\" $Id: dhcrelay.8,v 1.10 2005/03/17 20:15:24 dhankins Exp $ +.\" $Id: dhcrelay.8,v 1.11 2006/02/27 23:56:13 dhankins Exp $ .\" .TH dhcrelay 8 .SH NAME @@ -48,6 +48,11 @@ dhcrelay - Dynamic Host Configuration Protocol Relay Agent .B -i .I if0 [ +.B -is +.I server +... +] +[ .B ... .B -i .I ifN @@ -114,6 +119,11 @@ server) is attached. However, in some cases it may be necessary to exclude some networks; in this case, you must list all those network interfaces that should \fInot\fR be excluded using the \fB-i\fR flag. .PP +The +.B -is +flag can be used to indicate that for the previous interface specified with +-i, packets should be forwarded to the specified server. +.PP In some cases it .I is helpful for the relay agent to forward requests from networks on which diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c index 452724b1..4abc5250 100644 --- a/relay/dhcrelay.c +++ b/relay/dhcrelay.c @@ -34,7 +34,7 @@ #ifndef lint static char ocopyright[] = -"$Id: dhcrelay.c,v 1.54 2006/02/24 23:16:30 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n"; +"$Id: dhcrelay.c,v 1.55 2006/02/27 23:56:13 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -92,11 +92,6 @@ enum { forward_and_append, /* Forward and append our own relay option. */ u_int16_t local_port; u_int16_t remote_port; -struct server_list { - struct server_list *next; - struct sockaddr_in to; -} *servers; - static char copyright [] = "Copyright 2004-2005 Internet Systems Consortium."; static char arr [] = "All rights reserved."; static char message [] = "Internet Systems Consortium DHCP Relay Agent"; @@ -113,6 +108,7 @@ int main (argc, argv, envp) int quiet = 0; isc_result_t status; char *s; + struct interface_info *tmp = (struct interface_info *)0; /* Make sure we have stdin, stdout and stderr. */ i = open ("/dev/null", O_RDWR); @@ -154,8 +150,8 @@ int main (argc, argv, envp) } else if (!strcmp (argv [i], "-d")) { no_daemon = 1; } else if (!strcmp (argv [i], "-i")) { - struct interface_info *tmp = - (struct interface_info *)0; + if (tmp) + interface_dereference (&tmp, MDL); status = interface_allocate (&tmp, MDL); if (status != ISC_R_SUCCESS) log_fatal ("%s: interface_allocate: %s", @@ -166,7 +162,14 @@ int main (argc, argv, envp) } strcpy (tmp -> name, argv [i]); interface_snorf (tmp, INTERFACE_REQUESTED); - interface_dereference (&tmp, MDL); + } else if (!strcmp (argv [i], "-is")) { + if (++i == argc) + usage (); + if (!tmp) { + log_error ("-is must follow -i."); + usage (); + } + new_relay_server (argv [i], &tmp -> servers); } else if (!strcmp (argv [i], "-q")) { quiet = 1; quiet_interface_discovery = 1; @@ -206,33 +209,15 @@ int main (argc, argv, envp) log_info ("isc-dhcrelay-%s", DHCP_VERSION); exit (0); } else { - struct hostent *he; - struct in_addr ia, *iap = (struct in_addr *)0; - if (inet_aton (argv [i], &ia)) { - iap = &ia; - } else { - he = gethostbyname (argv [i]); - if (!he) { - log_error ("%s: host unknown", - argv [i]); - } else { - iap = ((struct in_addr *) - he -> h_addr_list [0]); - } - } - if (iap) { - sp = ((struct server_list *) - dmalloc (sizeof *sp, MDL)); - if (!sp) - log_fatal ("no memory for server.\n"); - sp -> next = servers; - servers = sp; - memcpy (&sp -> to.sin_addr, - iap, sizeof *iap); - } + new_relay_server (argv [i], &servers); } } + limited_broadcast.s_addr = INADDR_BROADCAST; + + if (tmp) + interface_dereference (&tmp, MDL); + if ((s = getenv ("PATH_DHCRELAY_PID"))) { path_dhcrelay_pid = s; } @@ -259,7 +244,7 @@ int main (argc, argv, envp) remote_port = htons (ntohs (local_port) + 1); /* We need at least one server. */ - if (!sp) { + if (!servers) { usage (); } @@ -272,6 +257,29 @@ int main (argc, argv, envp) #endif } + if (interfaces) { + interface_reference (&tmp, interfaces, MDL); + do { + struct interface_info *next = NULL; + if (tmp -> next) + interface_reference (&next, tmp -> next, MDL); + + for (sp = tmp -> servers; sp; sp = sp -> next) { + sp -> to.sin_port = local_port; + sp -> to.sin_family = AF_INET; +#ifdef HAVE_SA_LEN + sp -> to.sin_len = sizeof sp -> to; +#endif + } + + interface_dereference (&tmp, MDL); + if (next) { + interface_reference (&tmp, next, MDL); + interface_dereference (&next, MDL); + } + } while (tmp); + } + /* Get the current time... */ GET_TIME (&cur_time); @@ -323,6 +331,36 @@ int main (argc, argv, envp) return 0; } +void new_relay_server (char *arg, struct server_list **servers) +{ + struct hostent *he; + struct in_addr ia, *iap = (struct in_addr *)0; + struct server_list *sp; + + if (inet_aton (arg, &ia)) { + iap = &ia; + } else { + he = gethostbyname (arg); + if (!he) { + log_error ("%s: host unknown", arg); + } else { + iap = ((struct in_addr *) + he -> h_addr_list [0]); + } + } + if (iap) { + sp = ((struct server_list *) + dmalloc (sizeof *sp, MDL)); + if (!sp) + log_fatal ("no memory for server.\n"); + memset(sp, 0, sizeof *sp); + sp -> next = *servers; + *servers = sp; + memcpy (&sp -> to.sin_addr, + iap, sizeof *iap); + } +} + void relay (ip, packet, length, from_port, from, hfrom) struct interface_info *ip; struct dhcp_packet *packet; @@ -335,6 +373,7 @@ void relay (ip, packet, length, from_port, from, hfrom) struct sockaddr_in to; struct interface_info *out; struct hardware hto, *htop; + int i; if (packet -> hlen > sizeof packet -> chaddr) { log_info ("Discarding packet with invalid hlen."); @@ -345,14 +384,16 @@ void relay (ip, packet, length, from_port, from, hfrom) in the packet. */ if (packet -> giaddr.s_addr) { for (out = interfaces; out; out = out -> next) { - if (!memcmp (&out -> primary_address, - &packet -> giaddr, - sizeof packet -> giaddr)) - break; + for (i = 0; i < out -> address_count; i++) { + if (out -> addresses [i].s_addr == + packet -> giaddr.s_addr) + goto matched; + } } } else { out = (struct interface_info *)0; } + matched: /* If it's a bootreply, forward it to the client. */ if (packet -> op == BOOTREPLY) { @@ -388,15 +429,18 @@ void relay (ip, packet, length, from_port, from, hfrom) return; if (!out) { - log_error ("packet to bogus giaddr %s.\n", + log_error ("packet to bogus giaddr %s.", inet_ntoa (packet -> giaddr)); ++bogus_giaddr_drops; return; } + if (out -> address_count < 1) + log_fatal ("no IP address on interface %s!", + out -> name); if (send_packet (out, (struct packet *)0, - packet, length, out -> primary_address, + packet, length, out -> addresses [0], &to, htop) < 0) { ++server_packet_errors; } else { @@ -415,10 +459,13 @@ void relay (ip, packet, length, from_port, from, hfrom) if (out) return; + if (ip -> address_count < 1) + log_fatal ("no IP address on interface %s", ip -> name); + /* Add relay agent options if indicated. If something goes wrong, drop the packet. */ if (!(length = add_relay_agent_options (ip, packet, length, - ip -> primary_address))) + ip -> addresses [0]))) return; /* If giaddr is not already set, Set it so the server can @@ -427,7 +474,7 @@ void relay (ip, packet, length, from_port, from, hfrom) set, the response will be sent directly to the relay agent that set giaddr, so we won't see it. */ if (!packet -> giaddr.s_addr) - packet -> giaddr = ip -> primary_address; + packet -> giaddr = ip -> addresses [0]; if (packet -> hops < max_hop_count) packet -> hops = packet -> hops + 1; else @@ -435,11 +482,12 @@ void relay (ip, packet, length, from_port, from, hfrom) /* Otherwise, it's a BOOTREQUEST, so forward it to all the servers. */ - for (sp = servers; sp; sp = sp -> next) { + for (sp = (ip -> servers + ? ip -> servers : servers); sp; sp = sp -> next) { if (send_packet ((fallback_interface ? fallback_interface : interfaces), (struct packet *)0, - packet, length, ip -> primary_address, + packet, length, ip -> addresses [0], &sp -> to, (struct hardware *)0) < 0) { ++client_packet_errors; } else { @@ -450,13 +498,12 @@ void relay (ip, packet, length, from_port, from, hfrom) ++client_packets_relayed; } } - } static void usage () { log_fatal ("Usage: dhcrelay [-p ] [-d] [-D] [-i %s%s%s%s", - "interface] [-q] [-a]\n ", + "interface [-is server ... ]]\n ", "[-c count] [-A length] ", "[-m append|replace|forward|discard]\n", " [server1 [... serverN]]"); diff --git a/server/bootp.c b/server/bootp.c index c5b2ae0b..6600fc40 100644 --- a/server/bootp.c +++ b/server/bootp.c @@ -34,7 +34,7 @@ #ifndef lint static char copyright[] = -"$Id: bootp.c,v 1.73 2005/07/07 16:39:07 dhankins Exp $ Copyright (c) 2004-2005 Internet Systems Consortium. All rights reserved.\n"; +"$Id: bootp.c,v 1.74 2006/02/27 23:56:13 dhankins Exp $ Copyright (c) 2004-2005 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -271,11 +271,13 @@ void bootp (packet) memcpy (&raw.siaddr, d1.data, 4); data_string_forget (&d1, MDL); } else { - if (lease -> subnet -> shared_network -> interface) + if (lease -> subnet -> shared_network -> interface && + lease -> subnet -> + shared_network -> interface -> address_count) raw.siaddr = (lease -> subnet -> shared_network -> - interface -> primary_address); - else - raw.siaddr = packet -> interface -> primary_address; + interface -> addresses [0]); + else if (packet -> interface -> address_count) + raw.siaddr = packet -> interface -> addresses [0]; } raw.giaddr = packet -> raw -> giaddr; @@ -325,7 +327,8 @@ void bootp (packet) hto.hlen = packet -> raw -> hlen + 1; memcpy (&hto.hbuf [1], packet -> raw -> chaddr, packet -> raw -> hlen); - from = packet -> interface -> primary_address; + if (packet -> interface -> address_count) + from = packet -> interface -> addresses [0]; /* Report what we're doing... */ log_info ("%s", msgbuf); diff --git a/server/dhcp.c b/server/dhcp.c index 8eb7524b..fada817a 100644 --- a/server/dhcp.c +++ b/server/dhcp.c @@ -34,7 +34,7 @@ #ifndef lint static char copyright[] = -"$Id: dhcp.c,v 1.200 2006/02/24 23:16:30 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n"; +"$Id: dhcp.c,v 1.201 2006/02/27 23:56:13 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -1092,21 +1092,21 @@ void dhcpinform (packet, ms_nulltp) if (!(oc = lookup_option (&dhcp_universe, options, i))) { use_primary: oc = (struct option_cache *)0; + if (packet -> interface -> address_count > 0) { if (option_cache_allocate (&oc, MDL)) { if (make_const_data (&oc -> expression, ((unsigned char *) - &packet -> interface -> primary_address), - sizeof packet -> interface -> primary_address, + &packet -> interface -> addresses [0]), + sizeof packet -> interface -> addresses [0], 0, 0, MDL)) { - oc -> option = - dhcp_universe.options [i]; - save_option (&dhcp_universe, - options, oc); + oc -> option = dhcp_universe.options [i]; + save_option (&dhcp_universe, options, oc); } option_cache_dereference (&oc, MDL); } - from = packet -> interface -> primary_address; + from = packet -> interface -> addresses [0]; + } } else { if (evaluate_option_cache (&d1, packet, (struct lease *)0, (struct client_state *)0, @@ -1358,15 +1358,16 @@ void nak_lease (packet, cip) option_cache_dereference (&oc, MDL); i = DHO_DHCP_SERVER_IDENTIFIER; - if (!(oc = lookup_option (&dhcp_universe, options, i))) { + if (packet -> interface -> address_count > 0) { + if (!(oc = lookup_option (&dhcp_universe, options, i))) { use_primary: oc = (struct option_cache *)0; if (option_cache_allocate (&oc, MDL)) { if (make_const_data (&oc -> expression, ((unsigned char *) - &packet -> interface -> primary_address), - sizeof packet -> interface -> primary_address, + &packet -> interface -> addresses [0]), + sizeof packet -> interface -> addresses [0], 0, 0, MDL)) { oc -> option = dhcp_universe.options [i]; @@ -1374,9 +1375,10 @@ void nak_lease (packet, cip) } option_cache_dereference (&oc, MDL); } - myfrom.len = sizeof packet -> interface -> primary_address; + myfrom.len = sizeof packet -> interface -> addresses [0]; memcpy (myfrom.iabuf, - &packet -> interface -> primary_address, myfrom.len); + &packet -> interface -> addresses [0], myfrom.len); + } } else { memset (&data, 0, sizeof data); if (evaluate_option_cache (&data, packet, (struct lease *)0, @@ -1421,7 +1423,8 @@ void nak_lease (packet, cip) option_state_dereference (&options, MDL); /* memset (&raw.ciaddr, 0, sizeof raw.ciaddr);*/ - raw.siaddr = packet -> interface -> primary_address; + if (packet -> interface -> address_count) + raw.siaddr = packet -> interface -> addresses [0]; raw.giaddr = packet -> raw -> giaddr; memcpy (raw.chaddr, packet -> raw -> chaddr, sizeof raw.chaddr); raw.hlen = packet -> raw -> hlen; @@ -2401,13 +2404,14 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp) if (!(oc = lookup_option (&dhcp_universe, state -> options, i))) { use_primary: + if (state -> ip -> address_count > 0) { oc = (struct option_cache *)0; if (option_cache_allocate (&oc, MDL)) { if (make_const_data (&oc -> expression, ((unsigned char *) - &state -> ip -> primary_address), - sizeof state -> ip -> primary_address, + &state -> ip -> addresses [0]), + sizeof state -> ip -> addresses [0], 0, 0, MDL)) { oc -> option = dhcp_universe.options [i]; @@ -2417,10 +2421,11 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp) option_cache_dereference (&oc, MDL); } state -> from.len = - sizeof state -> ip -> primary_address; + sizeof state -> ip -> addresses [0]; memcpy (state -> from.iabuf, - &state -> ip -> primary_address, + &state -> ip -> addresses [0], state -> from.len); + } } else { if (evaluate_option_cache (&d1, packet, lease, (struct client_state *)0, @@ -2505,11 +2510,13 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp) option_cache_dereference (&oc, MDL); } } else { - state -> from.len = - sizeof state -> ip -> primary_address; - memcpy (state -> from.iabuf, - &state -> ip -> primary_address, - state -> from.len); + if (state -> ip -> address_count) { + state -> from.len = + sizeof state -> ip -> addresses [0]; + memcpy (state -> from.iabuf, + &state -> ip -> addresses [0], + state -> from.len); + } } /* Figure out the address of the boot file server. */