From: Ted Lemon Date: Wed, 19 Feb 1997 10:51:44 +0000 (+0000) Subject: Restructure to allow interface reinitialization X-Git-Tag: DHCP_970222~54 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=c3585217153b07518ecb2e0d03bce2703bfaedf0;p=thirdparty%2Fdhcp.git Restructure to allow interface reinitialization --- diff --git a/bpf.c b/bpf.c index f59806d00..8584f009f 100644 --- 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) diff --git a/common/bpf.c b/common/bpf.c index f59806d00..8584f009f 100644 --- a/common/bpf.c +++ b/common/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) diff --git a/common/dispatch.c b/common/dispatch.c index 90c59aa2e..b9239aada 100644 --- a/common/dispatch.c +++ b/common/dispatch.c @@ -42,15 +42,16 @@ #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 -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/common/nit.c b/common/nit.c index 9b1dc06f4..77c2ea155 100644 --- a/common/nit.c +++ b/common/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/common/raw.c b/common/raw.c index 148408e02..6d7641695 100644 --- a/common/raw.c +++ b/common/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 /* 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; diff --git a/common/socket.c b/common/socket.c index 3e3121b5e..952f190c4 100644 --- a/common/socket.c +++ b/common/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 ? diff --git a/dispatch.c b/dispatch.c index 90c59aa2e..b9239aada 100644 --- a/dispatch.c +++ b/dispatch.c @@ -42,15 +42,16 @@ #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 -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 9b1dc06f4..77c2ea155 100644 --- 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 148408e02..6d7641695 100644 --- 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 /* 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; diff --git a/socket.c b/socket.c index 3e3121b5e..952f190c4 100644 --- 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 ?