]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
Restructure to allow interface reinitialization
authorTed Lemon <source@isc.org>
Wed, 19 Feb 1997 10:51:44 +0000 (10:51 +0000)
committerTed Lemon <source@isc.org>
Wed, 19 Feb 1997 10:51:44 +0000 (10:51 +0000)
bpf.c
common/bpf.c
common/dispatch.c
common/nit.c
common/raw.c
common/socket.c
dispatch.c
nit.c
raw.c
socket.c

diff --git a/bpf.c b/bpf.c
index f59806d00d773dc5bd10fd44a6f53caa92a7b395..8584f009f908cebb1a2e7d77efa7ce3795da7bbe 100644 (file)
--- a/bpf.c
+++ b/bpf.c
@@ -42,7 +42,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: bpf.c,v 1.15 1997/02/18 14:30:12 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: bpf.c,v 1.16 1997/02/19 10:49:20 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -59,13 +59,29 @@ static char copyright[] =
 #include "includes/netinet/udp.h"
 #include "includes/netinet/if_ether.h"
 
+/* Reinitializes the specified interface after an address change.   This
+   is not required for packet-filter APIs. */
+
+#ifdef USE_BPF_SEND
+void if_reinitialize_send (info)
+       struct interface_info *info;
+{
+}
+#endif
+
+#ifdef USE_BPF_RECEIVE
+void if_reinitialize_receive (info)
+       struct interface_info *info;
+{
+}
+#endif
+
 /* Called by get_interface_list for each interface that's discovered.
    Opens a packet filter for each interface and adds it to the select
    mask. */
 
-int if_register_bpf (info, ifp)
+int if_register_bpf (info)
        struct interface_info *info;
-       struct ifreq *ifp;
 {
        int sock;
        char filename[50];
@@ -91,7 +107,7 @@ int if_register_bpf (info, ifp)
        }
 
        /* Set the BPF device to point at this interface. */
-       if (ioctl (sock, BIOCSETIF, ifp) < 0)
+       if (ioctl (sock, BIOCSETIF, info -> ifp) < 0)
                error ("Can't attach interface %s to bpf device %s: %m",
                       info -> name, filename);
 
@@ -100,9 +116,8 @@ int if_register_bpf (info, ifp)
 #endif /* USE_BPF_SEND || USE_BPF_RECEIVE */
 
 #ifdef USE_BPF_SEND
-void if_register_send (info, interface)
+void if_register_send (info)
        struct interface_info *info;
-       struct ifreq *interface;
 {
        /* If we're using the bpf API for sending and receiving,
           we don't need to register this interface twice. */
@@ -153,9 +168,8 @@ struct bpf_insn filter [] = {
        BPF_STMT(BPF_RET+BPF_K, 0),
 };
 
-void if_register_receive (info, interface)
+void if_register_receive (info)
        struct interface_info *info;
-       struct ifreq *interface;
 {
        int flag = 1;
        struct bpf_version v;
@@ -164,7 +178,7 @@ void if_register_receive (info, interface)
        u_int32_t bits;
 
        /* Open a BPF device and hang it on this interface... */
-       info -> rfdesc = if_register_bpf (info, interface);
+       info -> rfdesc = if_register_bpf (info);
 
        /* Make sure the BPF version is in range... */
        if (ioctl (info -> rfdesc, BIOCVERSION, &v) < 0)
index f59806d00d773dc5bd10fd44a6f53caa92a7b395..8584f009f908cebb1a2e7d77efa7ce3795da7bbe 100644 (file)
@@ -42,7 +42,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: bpf.c,v 1.15 1997/02/18 14:30:12 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: bpf.c,v 1.16 1997/02/19 10:49:20 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -59,13 +59,29 @@ static char copyright[] =
 #include "includes/netinet/udp.h"
 #include "includes/netinet/if_ether.h"
 
+/* Reinitializes the specified interface after an address change.   This
+   is not required for packet-filter APIs. */
+
+#ifdef USE_BPF_SEND
+void if_reinitialize_send (info)
+       struct interface_info *info;
+{
+}
+#endif
+
+#ifdef USE_BPF_RECEIVE
+void if_reinitialize_receive (info)
+       struct interface_info *info;
+{
+}
+#endif
+
 /* Called by get_interface_list for each interface that's discovered.
    Opens a packet filter for each interface and adds it to the select
    mask. */
 
-int if_register_bpf (info, ifp)
+int if_register_bpf (info)
        struct interface_info *info;
-       struct ifreq *ifp;
 {
        int sock;
        char filename[50];
@@ -91,7 +107,7 @@ int if_register_bpf (info, ifp)
        }
 
        /* Set the BPF device to point at this interface. */
-       if (ioctl (sock, BIOCSETIF, ifp) < 0)
+       if (ioctl (sock, BIOCSETIF, info -> ifp) < 0)
                error ("Can't attach interface %s to bpf device %s: %m",
                       info -> name, filename);
 
@@ -100,9 +116,8 @@ int if_register_bpf (info, ifp)
 #endif /* USE_BPF_SEND || USE_BPF_RECEIVE */
 
 #ifdef USE_BPF_SEND
-void if_register_send (info, interface)
+void if_register_send (info)
        struct interface_info *info;
-       struct ifreq *interface;
 {
        /* If we're using the bpf API for sending and receiving,
           we don't need to register this interface twice. */
@@ -153,9 +168,8 @@ struct bpf_insn filter [] = {
        BPF_STMT(BPF_RET+BPF_K, 0),
 };
 
-void if_register_receive (info, interface)
+void if_register_receive (info)
        struct interface_info *info;
-       struct ifreq *interface;
 {
        int flag = 1;
        struct bpf_version v;
@@ -164,7 +178,7 @@ void if_register_receive (info, interface)
        u_int32_t bits;
 
        /* Open a BPF device and hang it on this interface... */
-       info -> rfdesc = if_register_bpf (info, interface);
+       info -> rfdesc = if_register_bpf (info);
 
        /* Make sure the BPF version is in range... */
        if (ioctl (info -> rfdesc, BIOCVERSION, &v) < 0)
index 90c59aa2e0ab171261184a36ebe7f77d2147e847..b9239aadab76574d6734256726c9a42e2b927ac1 100644 (file)
 
 #ifndef lint
 static char copyright[] =
-"$Id: dispatch.c,v 1.29 1997/02/18 14:33:43 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: dispatch.c,v 1.30 1997/02/19 10:49:19 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
 #include <sys/ioctl.h>
 
-struct interface_info *interfaces;
+struct interface_info *interfaces, *dummy_interfaces;
 struct timeout *timeouts;
 static struct timeout *free_timeouts;
+static int interfaces_invalidated;
 
 static void got_one PROTO ((struct interface_info *));
 
@@ -219,8 +220,20 @@ void discover_interfaces (state)
                        /* If this is the first real IP address we've
                           found, keep a pointer to ifreq structure in
                           which we found it. */
-                       if (!tmp -> tif)
-                               tmp -> tif = ifp;
+                       if (!tmp -> ifp) {
+                               struct ifreq *tif;
+#ifdef HAVE_SA_LEN
+                               int len = ((sizeof ifp -> ifr_name) +
+                                          ifp -> ifr_addr.sa_len);
+#else
+                               int len = sizeof *ifp;
+#endif
+                               tif = (struct ifreq *)malloc (len);
+                               if (!tif)
+                                       error ("no space to remember ifp.");
+                               memcpy (tif, ifp, len);
+                               tmp -> ifp = ifp;
+                       }
 
                        /* Grab the address... */
                        addr.len = 4;
@@ -274,19 +287,24 @@ void discover_interfaces (state)
        /* Weed out the interfaces that did not have IP addresses. */
        last = (struct interface_info *)0;
        for (tmp = interfaces; tmp; tmp = tmp -> next) {
-               if (!tmp -> tif || !(tmp -> flags & INTERFACE_REQUESTED)) {
+               if (!tmp -> ifp || !(tmp -> flags & INTERFACE_REQUESTED)) {
                        if ((tmp -> flags & INTERFACE_REQUESTED) != ir)
                                error ("%s: not found", tmp -> name);
                        if (!last)
                                interfaces = interfaces -> next;
                        else
                                last -> next = tmp -> next;
+
+                       /* Remember the interface in case we need to know
+                          about it later. */
+                       tmp -> next = dummy_interfaces;
+                       dummy_interfaces = tmp;
                        continue;
                }
                last = tmp;
 
-               memcpy (&foo, &tmp -> tif -> ifr_addr,
-                       sizeof tmp -> tif -> ifr_addr);
+               memcpy (&foo, &tmp -> ifp -> ifr_addr,
+                       sizeof tmp -> ifp -> ifr_addr);
 
                /* We must have a subnet declaration for each interface. */
                if (!tmp -> shared_network && (state == DISCOVER_SERVER))
@@ -309,10 +327,8 @@ void discover_interfaces (state)
                }
 
                /* Register the interface... */
-               if_register_receive (tmp, tmp -> tif);
-               if_register_send (tmp, tmp -> tif);
-
-               tmp -> tif = (struct ifreq *)0; /* Can't keep this. */
+               if_register_receive (tmp);
+               if_register_send (tmp);
        }
 
        close (sock);
@@ -321,8 +337,24 @@ void discover_interfaces (state)
        strcpy (fallback_interface.name, "fallback");   
        fallback_interface.shared_network = &fallback_network;
        fallback_network.name = "fallback-net";
-       if_register_fallback (&fallback_interface, (struct ifreq *)0);
+       if_register_fallback (&fallback_interface);
+#endif
+}
+
+void reinitialize_interfaces ()
+{
+       struct interface_info *ip;
+
+       for (ip = interfaces; ip; ip = ip -> next) {
+               if_reinitialize_receive (ip);
+               if_reinitialize_send (ip);
+       }
+
+#ifdef USE_FALLBACK
+       if_reinitialize_fallback (&fallback_interface);
 #endif
+
+       interfaces_invalidated = 1;
 }
 
 #ifdef USE_POLL
@@ -357,23 +389,7 @@ void dispatch ()
        if (!fds)
                error ("Can't allocate poll structures.");
 
-       i = 0;
-       for (l = interfaces; l; l = l -> next) {
-               fds [i].fd = l -> rfdesc;
-               fds [i].events = POLLIN;
-               fds [i].revents = 0;
-               ++i;
-       }
-
-#ifdef USE_FALLBACK
-       fds [i].fd = fallback_interface.wfdesc;
-       fds [i].events = POLLIN;
-       fds [i].revents = 0;
-       ++i;
-#endif
-
        do {
-
                /* Call any expired timeouts, and then if there's
                   still a timeout registered, time out the select
                   call then. */
@@ -402,6 +418,22 @@ void dispatch ()
                } else
                        to_msec = -1;
 
+               /* Set up the descriptors to be polled. */
+               i = 0;
+               for (l = interfaces; l; l = l -> next) {
+                       fds [i].fd = l -> rfdesc;
+                       fds [i].events = POLLIN;
+                       fds [i].revents = 0;
+                       ++i;
+               }
+
+#ifdef USE_FALLBACK
+               fds [i].fd = fallback_interface.wfdesc;
+               fds [i].events = POLLIN;
+               fds [i].revents = 0;
+               ++i;
+#endif
+
                /* Wait for a packet or a timeout... XXX */
                count = poll (fds, nfds, to_msec);
 
@@ -417,13 +449,16 @@ void dispatch ()
                        if ((fds [i].revents & POLLIN)) {
                                fds [i].revents = 0;
                                got_one (l);
+                               if (interfaces_invalidated)
+                                       break;
                        }
                        ++i;
                }
 #ifdef USE_FALLBACK
-               if (fds [i].revents & POLLIN)
+               if ((fds [i].revents & POLLIN) && !interfaces_invalidated)
                        fallback_discard (&fallback_interface);
 #endif
+               interfaces_invalidated = 0;
        } while (1);
 }
 #else
@@ -440,24 +475,10 @@ void dispatch ()
        int count;
        struct timeval tv, *tvp;
 
-       FD_ZERO (&r);
        FD_ZERO (&w);
        FD_ZERO (&x);
 
        do {
-               /* Set up the read mask. */
-               for (l = interfaces; l; l = l -> next) {
-                       FD_SET (l -> rfdesc, &r);
-                       FD_SET (l -> rfdesc, &x);
-                       if (l -> rfdesc > max)
-                               max = l -> rfdesc;
-               }
-#ifdef USE_FALLBACK
-               FD_SET (fallback_interface.wfdesc, &r);
-               if (fallback_interface.wfdesc > max)
-                               max = fallback_interface.wfdesc;
-#endif
-
                /* Call any expired timeouts, and then if there's
                   still a timeout registered, time out the select
                   call then. */
@@ -478,6 +499,21 @@ void dispatch ()
                } else
                        tvp = (struct timeval *)0;
 
+               /* Set up the read mask. */
+               FD_ZERO (&r);
+
+               for (l = interfaces; l; l = l -> next) {
+                       FD_SET (l -> rfdesc, &r);
+                       FD_SET (l -> rfdesc, &x);
+                       if (l -> rfdesc > max)
+                               max = l -> rfdesc;
+               }
+#ifdef USE_FALLBACK
+               FD_SET (fallback_interface.wfdesc, &r);
+               if (fallback_interface.wfdesc > max)
+                               max = fallback_interface.wfdesc;
+#endif
+
                /* Wait for a packet or a timeout... XXX */
                count = select (max + 1, &r, &w, &x, tvp);
 
@@ -492,11 +528,15 @@ void dispatch ()
                        if (!FD_ISSET (l -> rfdesc, &r))
                                continue;
                        got_one (l);
+                       if (interfaces_invalidated)
+                               break;
                }
 #ifdef USE_FALLBACK
-               if (FD_ISSET (fallback_interface.wfdesc, &r))
+               if (FD_ISSET (fallback_interface.wfdesc, &r) &&
+                   !interfaces_invalidated)
                        fallback_discard (&fallback_interface);
 #endif
+               interfaces_invalidated = 1;
        } while (1);
 }
 #endif /* USE_POLL */
index 9b1dc06f43ffbde77afa93701db0c7cb226c80c7..77c2ea155fb1d43206f4f949aab8d5a45de503d5 100644 (file)
@@ -42,7 +42,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: nit.c,v 1.11 1997/02/18 14:30:12 mellon Exp $ Copyright (c) 1996 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: nit.c,v 1.12 1997/02/19 10:49:20 mellon Exp $ Copyright (c) 1996 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -63,13 +63,29 @@ static char copyright[] =
 #include "includes/netinet/udp.h"
 #include "includes/netinet/if_ether.h"
 
+/* Reinitializes the specified interface after an address change.   This
+   is not required for packet-filter APIs. */
+
+#ifdef USE_NIT_SEND
+void if_reinitialize_send (info)
+       struct interface_info *info;
+{
+}
+#endif
+
+#ifdef USE_NIT_RECEIVE
+void if_reinitialize_receive (info)
+       struct interface_info *info;
+{
+}
+#endif
+
 /* Called by get_interface_list for each interface that's discovered.
    Opens a packet filter for each interface and adds it to the select
    mask. */
 
-int if_register_nit (info, ifp)
+int if_register_nit (info)
        struct interface_info *info;
-       struct ifreq *ifp;
 {
        int sock;
        char filename[50];
@@ -83,8 +99,8 @@ int if_register_nit (info, ifp)
 
        /* Set the NIT device to point at this interface. */
        sio.ic_cmd = NIOCBIND;
-       sio.ic_len = sizeof *ifp;
-       sio.ic_dp = (char *)ifp;
+       sio.ic_len = sizeof *(info -> ifp);
+       sio.ic_dp = (char *)(info -> ifp);
        sio.ic_timout = INFTIM;
        if (ioctl (sock, I_STR, &sio) < 0)
                error ("Can't attach interface %s to nit device: %m",
@@ -113,9 +129,8 @@ int if_register_nit (info, ifp)
 #endif /* USE_NIT_SEND || USE_NIT_RECEIVE */
 
 #ifdef USE_NIT_SEND
-void if_register_send (info, interface)
+void if_register_send (info)
        struct interface_info *info;
-       struct ifreq *interface;
 {
        /* If we're using the nit API for sending and receiving,
           we don't need to register this interface twice. */
@@ -123,7 +138,7 @@ void if_register_send (info, interface)
        struct packetfilt pf;
        struct strioctl sio;
 
-       info -> wfdesc = if_register_nit (info, interface);
+       info -> wfdesc = if_register_nit (info);
 
        pf.Pf_Priority = 0;
        pf.Pf_FilterLen = 1;
@@ -153,9 +168,8 @@ void if_register_send (info, interface)
    XXX Changes to the filter program may require changes to the constant
    offsets used in if_register_send to patch the NIT program! XXX */
 
-void if_register_receive (info, interface)
+void if_register_receive (info)
        struct interface_info *info;
-       struct ifreq *interface;
 {
        int flag = 1;
        u_int32_t x;
@@ -165,7 +179,7 @@ void if_register_receive (info, interface)
        struct timeval t;
 
        /* Open a NIT device and hang it on this interface... */
-       info -> rfdesc = if_register_nit (info, interface);
+       info -> rfdesc = if_register_nit (info);
 
        /* Set the snap length to 0, which means always take the whole
           packet. */
index 148408e0217f637e80ad9caa2adc6d81a0f9fc57..6d76416954034e55ecd9d7e4ad63366a01f7e665 100644 (file)
@@ -54,7 +54,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: raw.c,v 1.9 1997/02/18 14:32:51 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: raw.c,v 1.10 1997/02/19 10:51:44 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -63,9 +63,8 @@ static char copyright[] =
 #include <sys/uio.h>
 
 /* Generic interface registration routine... */
-void if_register_send (info, interface)
+void if_register_send (info)
        struct interface_info *info;
-       struct ifreq *interface;
 {
        struct sockaddr_in name;
        int sock;
index 3e3121b5eddabf77dcc72b44e115826e10724cd8..952f190c44d30a3e174b1d5e3d09d2c986a0c86f 100644 (file)
@@ -50,7 +50,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: socket.c,v 1.18 1997/02/18 14:30:13 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: socket.c,v 1.19 1997/02/19 10:49:19 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -59,21 +59,50 @@ static char copyright[] =
 #  define USE_SOCKET_SEND
 #  define if_register_send if_register_fallback
 #  define send_packet send_fallback
+#  define if_reinitialize_send if_reinitialize_fallback
+#endif
+
+static int once = 0;
+
+/* Reinitializes the specified interface after an address change.   This
+   is not required for packet-filter APIs. */
+
+#ifdef USE_SOCKET_SEND
+void if_reinitialize_send (info)
+       struct interface_info *info;
+{
+#if 0
+#ifndef USE_SOCKET_RECEIVE
+       once = 0;
+       close (info -> wfdesc);
+#endif
+       if_register_send (info);
+#endif
+}
+#endif
+
+#ifdef USE_SOCKET_RECEIVE
+void if_reinitialize_receive (info)
+       struct interface_info *info;
+{
+#if 0
+       once = 0;
+       close (info -> rfdesc);
+       if_register_receive (info);
+#endif
+}
 #endif
 
 #if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_RECEIVE)
 /* Generic interface registration routine... */
-int if_register_socket (info, interface)
+int if_register_socket (info)
        struct interface_info *info;
-       struct ifreq *interface;
 {
        struct sockaddr_in name;
        int sock;
        int flag;
 
 #ifndef SO_BINDTODEVICE
-       static int once = 0;
-
        /* Make sure only one interface is registered. */
        if (once)
                error ("The standard socket API can only support %s%s%s%s%s",
@@ -121,8 +150,8 @@ int if_register_socket (info, interface)
 
 #ifdef SO_BINDTODEVICE
        /* Bind this socket to this interface. */
-       if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE,
-                      (char *)interface, sizeof(*interface)) < 0) {
+       if (setsockopt (sock, SOL_SOCKET, SO_BINDTODEVICE,
+                       (char *)(info -> ifp), sizeof *(info -> ifp)) < 0) {
                error("setting SO_BINDTODEVICE");
        }
 #endif
@@ -132,13 +161,11 @@ int if_register_socket (info, interface)
 #endif /* USE_SOCKET_SEND || USE_SOCKET_RECEIVE */
 
 #ifdef USE_SOCKET_SEND
-void if_register_send (info, interface)
+void if_register_send (info)
        struct interface_info *info;
-       struct ifreq *interface;
-
 {
 #ifndef USE_SOCKET_RECEIVE
-       info -> wfdesc = if_register_socket (info, interface);
+       info -> wfdesc = if_register_socket (info);
 #else
        info -> wfdesc = info -> rfdesc;
 #endif
@@ -151,13 +178,12 @@ void if_register_send (info, interface)
 #endif /* USE_SOCKET_SEND */
 
 #ifdef USE_SOCKET_RECEIVE
-void if_register_receive (info, interface)
+void if_register_receive (info)
        struct interface_info *info;
-       struct ifreq *interface;
 {
        /* If we're using the socket API for sending and receiving,
           we don't need to register this interface twice. */
-       info -> rfdesc = if_register_socket (info, interface);
+       info -> rfdesc = if_register_socket (info);
        note ("Listening on Socket/%s/%s",
              info -> name,
              (info -> shared_network ?
index 90c59aa2e0ab171261184a36ebe7f77d2147e847..b9239aadab76574d6734256726c9a42e2b927ac1 100644 (file)
 
 #ifndef lint
 static char copyright[] =
-"$Id: dispatch.c,v 1.29 1997/02/18 14:33:43 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: dispatch.c,v 1.30 1997/02/19 10:49:19 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
 #include <sys/ioctl.h>
 
-struct interface_info *interfaces;
+struct interface_info *interfaces, *dummy_interfaces;
 struct timeout *timeouts;
 static struct timeout *free_timeouts;
+static int interfaces_invalidated;
 
 static void got_one PROTO ((struct interface_info *));
 
@@ -219,8 +220,20 @@ void discover_interfaces (state)
                        /* If this is the first real IP address we've
                           found, keep a pointer to ifreq structure in
                           which we found it. */
-                       if (!tmp -> tif)
-                               tmp -> tif = ifp;
+                       if (!tmp -> ifp) {
+                               struct ifreq *tif;
+#ifdef HAVE_SA_LEN
+                               int len = ((sizeof ifp -> ifr_name) +
+                                          ifp -> ifr_addr.sa_len);
+#else
+                               int len = sizeof *ifp;
+#endif
+                               tif = (struct ifreq *)malloc (len);
+                               if (!tif)
+                                       error ("no space to remember ifp.");
+                               memcpy (tif, ifp, len);
+                               tmp -> ifp = ifp;
+                       }
 
                        /* Grab the address... */
                        addr.len = 4;
@@ -274,19 +287,24 @@ void discover_interfaces (state)
        /* Weed out the interfaces that did not have IP addresses. */
        last = (struct interface_info *)0;
        for (tmp = interfaces; tmp; tmp = tmp -> next) {
-               if (!tmp -> tif || !(tmp -> flags & INTERFACE_REQUESTED)) {
+               if (!tmp -> ifp || !(tmp -> flags & INTERFACE_REQUESTED)) {
                        if ((tmp -> flags & INTERFACE_REQUESTED) != ir)
                                error ("%s: not found", tmp -> name);
                        if (!last)
                                interfaces = interfaces -> next;
                        else
                                last -> next = tmp -> next;
+
+                       /* Remember the interface in case we need to know
+                          about it later. */
+                       tmp -> next = dummy_interfaces;
+                       dummy_interfaces = tmp;
                        continue;
                }
                last = tmp;
 
-               memcpy (&foo, &tmp -> tif -> ifr_addr,
-                       sizeof tmp -> tif -> ifr_addr);
+               memcpy (&foo, &tmp -> ifp -> ifr_addr,
+                       sizeof tmp -> ifp -> ifr_addr);
 
                /* We must have a subnet declaration for each interface. */
                if (!tmp -> shared_network && (state == DISCOVER_SERVER))
@@ -309,10 +327,8 @@ void discover_interfaces (state)
                }
 
                /* Register the interface... */
-               if_register_receive (tmp, tmp -> tif);
-               if_register_send (tmp, tmp -> tif);
-
-               tmp -> tif = (struct ifreq *)0; /* Can't keep this. */
+               if_register_receive (tmp);
+               if_register_send (tmp);
        }
 
        close (sock);
@@ -321,8 +337,24 @@ void discover_interfaces (state)
        strcpy (fallback_interface.name, "fallback");   
        fallback_interface.shared_network = &fallback_network;
        fallback_network.name = "fallback-net";
-       if_register_fallback (&fallback_interface, (struct ifreq *)0);
+       if_register_fallback (&fallback_interface);
+#endif
+}
+
+void reinitialize_interfaces ()
+{
+       struct interface_info *ip;
+
+       for (ip = interfaces; ip; ip = ip -> next) {
+               if_reinitialize_receive (ip);
+               if_reinitialize_send (ip);
+       }
+
+#ifdef USE_FALLBACK
+       if_reinitialize_fallback (&fallback_interface);
 #endif
+
+       interfaces_invalidated = 1;
 }
 
 #ifdef USE_POLL
@@ -357,23 +389,7 @@ void dispatch ()
        if (!fds)
                error ("Can't allocate poll structures.");
 
-       i = 0;
-       for (l = interfaces; l; l = l -> next) {
-               fds [i].fd = l -> rfdesc;
-               fds [i].events = POLLIN;
-               fds [i].revents = 0;
-               ++i;
-       }
-
-#ifdef USE_FALLBACK
-       fds [i].fd = fallback_interface.wfdesc;
-       fds [i].events = POLLIN;
-       fds [i].revents = 0;
-       ++i;
-#endif
-
        do {
-
                /* Call any expired timeouts, and then if there's
                   still a timeout registered, time out the select
                   call then. */
@@ -402,6 +418,22 @@ void dispatch ()
                } else
                        to_msec = -1;
 
+               /* Set up the descriptors to be polled. */
+               i = 0;
+               for (l = interfaces; l; l = l -> next) {
+                       fds [i].fd = l -> rfdesc;
+                       fds [i].events = POLLIN;
+                       fds [i].revents = 0;
+                       ++i;
+               }
+
+#ifdef USE_FALLBACK
+               fds [i].fd = fallback_interface.wfdesc;
+               fds [i].events = POLLIN;
+               fds [i].revents = 0;
+               ++i;
+#endif
+
                /* Wait for a packet or a timeout... XXX */
                count = poll (fds, nfds, to_msec);
 
@@ -417,13 +449,16 @@ void dispatch ()
                        if ((fds [i].revents & POLLIN)) {
                                fds [i].revents = 0;
                                got_one (l);
+                               if (interfaces_invalidated)
+                                       break;
                        }
                        ++i;
                }
 #ifdef USE_FALLBACK
-               if (fds [i].revents & POLLIN)
+               if ((fds [i].revents & POLLIN) && !interfaces_invalidated)
                        fallback_discard (&fallback_interface);
 #endif
+               interfaces_invalidated = 0;
        } while (1);
 }
 #else
@@ -440,24 +475,10 @@ void dispatch ()
        int count;
        struct timeval tv, *tvp;
 
-       FD_ZERO (&r);
        FD_ZERO (&w);
        FD_ZERO (&x);
 
        do {
-               /* Set up the read mask. */
-               for (l = interfaces; l; l = l -> next) {
-                       FD_SET (l -> rfdesc, &r);
-                       FD_SET (l -> rfdesc, &x);
-                       if (l -> rfdesc > max)
-                               max = l -> rfdesc;
-               }
-#ifdef USE_FALLBACK
-               FD_SET (fallback_interface.wfdesc, &r);
-               if (fallback_interface.wfdesc > max)
-                               max = fallback_interface.wfdesc;
-#endif
-
                /* Call any expired timeouts, and then if there's
                   still a timeout registered, time out the select
                   call then. */
@@ -478,6 +499,21 @@ void dispatch ()
                } else
                        tvp = (struct timeval *)0;
 
+               /* Set up the read mask. */
+               FD_ZERO (&r);
+
+               for (l = interfaces; l; l = l -> next) {
+                       FD_SET (l -> rfdesc, &r);
+                       FD_SET (l -> rfdesc, &x);
+                       if (l -> rfdesc > max)
+                               max = l -> rfdesc;
+               }
+#ifdef USE_FALLBACK
+               FD_SET (fallback_interface.wfdesc, &r);
+               if (fallback_interface.wfdesc > max)
+                               max = fallback_interface.wfdesc;
+#endif
+
                /* Wait for a packet or a timeout... XXX */
                count = select (max + 1, &r, &w, &x, tvp);
 
@@ -492,11 +528,15 @@ void dispatch ()
                        if (!FD_ISSET (l -> rfdesc, &r))
                                continue;
                        got_one (l);
+                       if (interfaces_invalidated)
+                               break;
                }
 #ifdef USE_FALLBACK
-               if (FD_ISSET (fallback_interface.wfdesc, &r))
+               if (FD_ISSET (fallback_interface.wfdesc, &r) &&
+                   !interfaces_invalidated)
                        fallback_discard (&fallback_interface);
 #endif
+               interfaces_invalidated = 1;
        } while (1);
 }
 #endif /* USE_POLL */
diff --git a/nit.c b/nit.c
index 9b1dc06f43ffbde77afa93701db0c7cb226c80c7..77c2ea155fb1d43206f4f949aab8d5a45de503d5 100644 (file)
--- a/nit.c
+++ b/nit.c
@@ -42,7 +42,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: nit.c,v 1.11 1997/02/18 14:30:12 mellon Exp $ Copyright (c) 1996 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: nit.c,v 1.12 1997/02/19 10:49:20 mellon Exp $ Copyright (c) 1996 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -63,13 +63,29 @@ static char copyright[] =
 #include "includes/netinet/udp.h"
 #include "includes/netinet/if_ether.h"
 
+/* Reinitializes the specified interface after an address change.   This
+   is not required for packet-filter APIs. */
+
+#ifdef USE_NIT_SEND
+void if_reinitialize_send (info)
+       struct interface_info *info;
+{
+}
+#endif
+
+#ifdef USE_NIT_RECEIVE
+void if_reinitialize_receive (info)
+       struct interface_info *info;
+{
+}
+#endif
+
 /* Called by get_interface_list for each interface that's discovered.
    Opens a packet filter for each interface and adds it to the select
    mask. */
 
-int if_register_nit (info, ifp)
+int if_register_nit (info)
        struct interface_info *info;
-       struct ifreq *ifp;
 {
        int sock;
        char filename[50];
@@ -83,8 +99,8 @@ int if_register_nit (info, ifp)
 
        /* Set the NIT device to point at this interface. */
        sio.ic_cmd = NIOCBIND;
-       sio.ic_len = sizeof *ifp;
-       sio.ic_dp = (char *)ifp;
+       sio.ic_len = sizeof *(info -> ifp);
+       sio.ic_dp = (char *)(info -> ifp);
        sio.ic_timout = INFTIM;
        if (ioctl (sock, I_STR, &sio) < 0)
                error ("Can't attach interface %s to nit device: %m",
@@ -113,9 +129,8 @@ int if_register_nit (info, ifp)
 #endif /* USE_NIT_SEND || USE_NIT_RECEIVE */
 
 #ifdef USE_NIT_SEND
-void if_register_send (info, interface)
+void if_register_send (info)
        struct interface_info *info;
-       struct ifreq *interface;
 {
        /* If we're using the nit API for sending and receiving,
           we don't need to register this interface twice. */
@@ -123,7 +138,7 @@ void if_register_send (info, interface)
        struct packetfilt pf;
        struct strioctl sio;
 
-       info -> wfdesc = if_register_nit (info, interface);
+       info -> wfdesc = if_register_nit (info);
 
        pf.Pf_Priority = 0;
        pf.Pf_FilterLen = 1;
@@ -153,9 +168,8 @@ void if_register_send (info, interface)
    XXX Changes to the filter program may require changes to the constant
    offsets used in if_register_send to patch the NIT program! XXX */
 
-void if_register_receive (info, interface)
+void if_register_receive (info)
        struct interface_info *info;
-       struct ifreq *interface;
 {
        int flag = 1;
        u_int32_t x;
@@ -165,7 +179,7 @@ void if_register_receive (info, interface)
        struct timeval t;
 
        /* Open a NIT device and hang it on this interface... */
-       info -> rfdesc = if_register_nit (info, interface);
+       info -> rfdesc = if_register_nit (info);
 
        /* Set the snap length to 0, which means always take the whole
           packet. */
diff --git a/raw.c b/raw.c
index 148408e0217f637e80ad9caa2adc6d81a0f9fc57..6d76416954034e55ecd9d7e4ad63366a01f7e665 100644 (file)
--- a/raw.c
+++ b/raw.c
@@ -54,7 +54,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: raw.c,v 1.9 1997/02/18 14:32:51 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: raw.c,v 1.10 1997/02/19 10:51:44 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -63,9 +63,8 @@ static char copyright[] =
 #include <sys/uio.h>
 
 /* Generic interface registration routine... */
-void if_register_send (info, interface)
+void if_register_send (info)
        struct interface_info *info;
-       struct ifreq *interface;
 {
        struct sockaddr_in name;
        int sock;
index 3e3121b5eddabf77dcc72b44e115826e10724cd8..952f190c44d30a3e174b1d5e3d09d2c986a0c86f 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -50,7 +50,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: socket.c,v 1.18 1997/02/18 14:30:13 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: socket.c,v 1.19 1997/02/19 10:49:19 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -59,21 +59,50 @@ static char copyright[] =
 #  define USE_SOCKET_SEND
 #  define if_register_send if_register_fallback
 #  define send_packet send_fallback
+#  define if_reinitialize_send if_reinitialize_fallback
+#endif
+
+static int once = 0;
+
+/* Reinitializes the specified interface after an address change.   This
+   is not required for packet-filter APIs. */
+
+#ifdef USE_SOCKET_SEND
+void if_reinitialize_send (info)
+       struct interface_info *info;
+{
+#if 0
+#ifndef USE_SOCKET_RECEIVE
+       once = 0;
+       close (info -> wfdesc);
+#endif
+       if_register_send (info);
+#endif
+}
+#endif
+
+#ifdef USE_SOCKET_RECEIVE
+void if_reinitialize_receive (info)
+       struct interface_info *info;
+{
+#if 0
+       once = 0;
+       close (info -> rfdesc);
+       if_register_receive (info);
+#endif
+}
 #endif
 
 #if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_RECEIVE)
 /* Generic interface registration routine... */
-int if_register_socket (info, interface)
+int if_register_socket (info)
        struct interface_info *info;
-       struct ifreq *interface;
 {
        struct sockaddr_in name;
        int sock;
        int flag;
 
 #ifndef SO_BINDTODEVICE
-       static int once = 0;
-
        /* Make sure only one interface is registered. */
        if (once)
                error ("The standard socket API can only support %s%s%s%s%s",
@@ -121,8 +150,8 @@ int if_register_socket (info, interface)
 
 #ifdef SO_BINDTODEVICE
        /* Bind this socket to this interface. */
-       if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE,
-                      (char *)interface, sizeof(*interface)) < 0) {
+       if (setsockopt (sock, SOL_SOCKET, SO_BINDTODEVICE,
+                       (char *)(info -> ifp), sizeof *(info -> ifp)) < 0) {
                error("setting SO_BINDTODEVICE");
        }
 #endif
@@ -132,13 +161,11 @@ int if_register_socket (info, interface)
 #endif /* USE_SOCKET_SEND || USE_SOCKET_RECEIVE */
 
 #ifdef USE_SOCKET_SEND
-void if_register_send (info, interface)
+void if_register_send (info)
        struct interface_info *info;
-       struct ifreq *interface;
-
 {
 #ifndef USE_SOCKET_RECEIVE
-       info -> wfdesc = if_register_socket (info, interface);
+       info -> wfdesc = if_register_socket (info);
 #else
        info -> wfdesc = info -> rfdesc;
 #endif
@@ -151,13 +178,12 @@ void if_register_send (info, interface)
 #endif /* USE_SOCKET_SEND */
 
 #ifdef USE_SOCKET_RECEIVE
-void if_register_receive (info, interface)
+void if_register_receive (info)
        struct interface_info *info;
-       struct ifreq *interface;
 {
        /* If we're using the socket API for sending and receiving,
           we don't need to register this interface twice. */
-       info -> rfdesc = if_register_socket (info, interface);
+       info -> rfdesc = if_register_socket (info);
        note ("Listening on Socket/%s/%s",
              info -> name,
              (info -> shared_network ?