if (scan_ipv6 == ISC_FALSE && family == AF_INET6)
continue;
- /*
- * Check to see if we are going to use the interface
- * If we don't use it we mark it to drop any packet
- * received but we still must create the socket and
- * bind to it. This prevents other apps binding to it
- * and potentially causing problems with more than one
- * process fiddling with the clock
+ /*
+ * create prototype
*/
- if (address_okay(&isc_if) == ISC_TRUE) {
- inter_list[idx].ignore_packets = ISC_FALSE;
- }
- else {
- inter_list[idx].ignore_packets = ISC_TRUE;
+ init_interface(&interface);
+
+ DPRINT_INTERFACE(1, (&interface, "examining", "\n"));
+
+ convert_isc_if(&isc_if, &interface, port);
+
+ if (!(interface.flags & INT_UP)) { /* interfaces must be UP to be usable */
+ DPRINTF(1, ("skipping interface %s (%s) - DOWN\n", interface.name, stoa(&interface.sin)));
+ continue;
}
-
- convert_isc_if(&isc_if, &inter_list[idx], port);
+
+ /*
+ * skip any interfaces UP and bound to a wildcard
+ * address - some dhcp clients produce that in the
+ * wild
+ */
+ if (family == AF_INET &&
+ ((struct sockaddr_in*)&inter_list[idx].sin)->sin_addr.s_addr == htonl(INADDR_ANY))
+ continue;
+
+ if (family == AF_INET6 &&
+ memcmp(&((struct sockaddr_in6*)&inter_list[idx].sin)->sin6_addr, &in6addr_any,
+ sizeof(in6addr_any) == 0))
+ continue;
- inter_list[idx].fd = INVALID_SOCKET;
- inter_list[idx].bfd = INVALID_SOCKET;
- inter_list[idx].num_mcast = 0;
- inter_list[idx].received = 0;
- inter_list[idx].sent = 0;
- inter_list[idx].notsent = 0;
- idx++;
+ /*
+ * map to local *address* in order
+ * to map all duplicate interfaces to an interface structure
+ * with the appropriate socket (our name space is
+ * (ip-address) - NOT (interface name, ip-address))
+ */
+ iface = findlocalinterface(&interface.sin);
+
+ if (iface && refresh_interface(iface))
+ {
+ /*
+ * found existing and up to date interface - mark present
+ */
+
+ iface->phase = sys_interphase;
+ DPRINT_INTERFACE(2, (iface, "updating ", " present\n"));
+ ifi.action = IFS_EXISTS;
+ ifi.interface = iface;
+ if (receiver)
+ receiver(data, &ifi);
+ }
+ else
+ {
+ /*
+ * this is new or refreshing failed - add to our interface list
+ * if refreshing failed we will delete the interface structure in
+ * phase 2 as the interface was not marked current. We can bind to
+ * the address as the refresh code already closed the offending socket
+ */
+
+ iface = create_interface(port, &interface);
+
+ if (iface)
+ {
+ ifi.action = IFS_CREATED;
+ ifi.interface = iface;
+ if (receiver && iface)
+ receiver(data, &ifi);
+ DPRINT_INTERFACE(2, (iface ? iface : &interface, "updating ", iface ? " new - created\n" : " new - creation FAILED"));
+ }
+ else
+ {
+ msyslog(LOG_INFO, "failed to initialize interface for address %s", stoa(&interface.sin));
+ }
+ }
+ /*
+ * Check to see if we are going to use the interface
+ * If we don't use it we mark it to drop any packet
+ * received but we still must create the socket and
+ * bind to it. This prevents other apps binding to it
+ * and potentially causing problems with more than one
+ * process fiddling with the clock
+ */
+ if (address_okay(&isc_if) == ISC_TRUE) {
+ iface->ignore_packets = ISC_FALSE;
+ }
+ else {
+ iface->ignore_packets = ISC_TRUE;
+ }
}
+
isc_interfaceiter_destroy(&iter);
- ninterfaces = idx;
/*
- * Create the sockets
+ * phase 2 - delete gone interfaces - reassigning peers to other interfaces
*/
- for (i = 0; i < ninterfaces; i++) {
- inter_list[i].fd = open_socket(&inter_list[i].sin,
- inter_list[i].flags, 0, &inter_list[i], i);
- if (inter_list[i].fd != INVALID_SOCKET)
- msyslog(LOG_INFO, "Listening on interface %s, %s#%d %s",
- inter_list[i].name,
- stoa((&inter_list[i].sin)),
- NTP_PORT,
- (inter_list[i].ignore_packets == ISC_FALSE) ?
- "Enabled": "Disabled");
+ {
+ struct interface *interf = ISC_LIST_HEAD(inter_list);
+
+ while (interf != NULL)
+ {
+ struct interface *next = ISC_LIST_NEXT(interf, link);
+
+ if (!(interf->flags & (INT_WILDCARD|INT_MCASTIF))) {
+ /*
+ * if phase does not match sys_phase this interface was not
+ * enumerated during interface scan - so it is gone and
+ * will be deleted here unless it is solely an MCAST interface
+ */
+ if (interf->phase != sys_interphase) {
+ struct peer *peer;
+ DPRINT_INTERFACE(2, (interf, "updating ", "GONE - deleting\n"));
+ remove_interface(interf);
+
+ ifi.action = IFS_DELETED;
+ ifi.interface = interf;
+ if (receiver)
+ receiver(data, &ifi);
+
+ peer = ISC_LIST_HEAD(interf->peers);
+ /*
+ * disconnect peer from deleted interface
+ */
+ while (peer != NULL) {
+ struct peer *npeer = ISC_LIST_NEXT(peer, ilink);
+
+ /*
+ * this one just lost it's interface
+ */
+ set_peerdstadr(peer, NULL);
+
+ peer = npeer;
+ }
+ delete_interface(interf);
+ }
+ }
+ interf = next;
+ }
+ }
+
/*
- * Calculate the address hash for each interface address.
+ * phase3 - re-configure as the world has changed if necessary
*/
- inter_list[i].addr_refid = addr2refid(&inter_list[i].sin);
- }
+ refresh_all_peerinterfaces();
+}
+
+
+/*
+ * create_sockets - create a socket for each interface plus a default
+ * socket for when we don't know where to send
+ */
+static int
+create_sockets(
+ u_short port
+ )
+{
+#ifndef HAVE_IO_COMPLETION_PORT
+ /*
+ * I/O Completion Ports don't care about the select and FD_SET
+ */
+ maxactivefd = 0;
+ FD_ZERO(&activefds);
+#endif
+
+ DPRINTF(2, ("create_sockets(%d)\n", ntohs( (u_short) port)));
+ create_wildcards(port);
+
+ update_interfaces(port, NULL, NULL);
+
/*
* Now that we have opened all the sockets, turn off the reuse
* flag for security.