]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
- The IO system now tracks all local IP addresses, so that the DHCP
authorDavid Hankins <dhankins@isc.org>
Mon, 27 Feb 2006 23:56:13 +0000 (23:56 +0000)
committerDavid Hankins <dhankins@isc.org>
Mon, 27 Feb 2006 23:56:13 +0000 (23:56 +0000)
  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. [ISC-Bugs #15573]

RELNOTES
client/dhclient.c
common/ctrace.c
common/discover.c
common/packet.c
includes/dhcpd.h
relay/dhcrelay.8
relay/dhcrelay.c
server/bootp.c
server/dhcp.c

index 692af08e879ee54d09a10ebec56f0c487ccb7c56..727e0b66295210fe8e1e8f3af66dd739a75bc1bc 100644 (file)
--- 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
 
index 762d6d76c5d6995efe0755c34f6cbf8a34b8204b..29d600e9cdaf58a7461cc0705047f5fc085ecd91 100644 (file)
@@ -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;
        }
index e5042ec6d364dce94d3f6c6d82e02c0e510a7d1f..5e8bcc09f1ef58850e47fda3d1ad01640f06e5d6 100644 (file)
@@ -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);
index 16796d783de42da1f2ad413e281d01a48f267ee5..4d22d149ed5c598364efa3bfa7a8abeccf2643c2 100644 (file)
@@ -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;
index 830c276a53d8c1a65f073ce828126a5f87844078..57702fcbc389415e5d89b1c553bce2ac43060b23 100644 (file)
@@ -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) {
index d9c911fcec0e6ca54a2d81b89032e0c48a2f19be..36b74c81c63a60b9df5056592f7461112218cf9d 100644 (file)
@@ -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 *,
index 05b6dabc473a0a6eaf52c79d83a5b84fd7f064e3..1e0a9a9c2b609d4b258bc4df8759279398ff58df 100644 (file)
@@ -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
index 452724b10b6553a72dd86ee676517c68aea4d953..4abc52502e03777678889053cd393d6da1f7afb3 100644 (file)
@@ -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 <port>] [-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]]");
index c5b2ae0b6413869176c001d1cc877102f26c5030..6600fc40839a9fdc89ceb7347bee6d43cb2d9e4c 100644 (file)
@@ -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);
index 8eb7524bbc746c013dbad5c264f994a3e50f5b95..fada817a7f367a0a46a0009bb1cc8af78a8351c3 100644 (file)
@@ -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. */