typedef void (*interface_receiver_t)(void *, interface_info_t *);
+extern volatile int disable_dynamic_updates;
+
extern void interface_enumerate P((interface_receiver_t, void *));
extern struct interface *findinterface P((struct sockaddr_storage *));
extern struct interface *findbcastinter P((struct sockaddr_storage *));
extern void timer P((void));
extern void timer_clr_stats P((void));
extern void timer_interfacetimeout P((u_long));
+extern volatile int interface_interval;
#ifdef OPENSSL
extern char *sys_hostname;
int ninterfaces; /* Total number of interfaces */
+volatile int disable_dynamic_updates; /* when set to != 0 dynamic updates won't happen */
+
#ifdef REFCLOCK
/*
* Refclock stuff. We keep a chain of structures with data concerning
void
interface_update(interface_receiver_t receiver, void *data)
{
- BLOCKIO();
- update_interfaces(htons(NTP_PORT), receiver, data);
- UNBLOCKIO();
+ if (!disable_dynamic_updates) {
+ BLOCKIO();
+ update_interfaces(htons(NTP_PORT), receiver, data);
+ UNBLOCKIO();
+ }
}
/*
return 0;
}
+#ifdef OS_NEEDS_REUSEADDR_FOR_IFADDRBIND
/*
* enable/disable re-use of wildcard address socket
*/
&any_interface->sin : &any6_interface->sin)));
}
}
+#endif /* OS_NEEDS_REUSEADDR_FOR_IFADDRBIND */
/*
* update_interface strategy
* attempt to create a new interface entry
*
* Phase 2:
- * forall currently known interfaces
+ * forall currently known non MCAST and WILDCARD interfaces
* if interface does not match configuration phase (not seen in phase 1):
* remove interface from known interface list
* forall peers associated with this interface
htonl(~(u_int32)0);
DPRINT_INTERFACE(2, (interface, "multicast add ", "\n"));
add_interface(interface);
+ list_if_listening(interface, NTP_PORT);
}
else
{
int cnt;
+ if (disable_dynamic_updates) {
+ /*
+ * discard ourselves if we are not need any more
+ * usually happens when running unprivileged
+ */
+ remove_asyncio_reader(reader);
+ delete_asyncio_reader(reader);
+ return;
+ }
+
cnt = read(reader->fd, buffer, sizeof(buffer));
if (cnt < 0) {
reader->fd = fd;
reader->receiver = process_routing_msgs;
- add_asyncio_reader(reader, FD_TYPE_FILE);
+ add_asyncio_reader(reader, FD_TYPE_SOCKET);
msyslog(LOG_INFO, "Listening on routing socket on fd #%d for interface updates", fd);
} else {
msyslog(LOG_ERR, "unable to open routing socket (%m) - using polled interface update");
exit (-1);
}
+ /*
+ * for now assume that the privilege to bind to privileged ports
+ * is associated with running with uid 0 - should be refined on
+ * ports that allow binding to NTP_PORT with uid != 0
+ */
+ disable_dynamic_updates |= (sw_uid != 0); /* also notifies routing message listener */
+
+ if (disable_dynamic_updates && interface_interval) {
+ interface_interval = 0;
+ msyslog(LOG_INFO, "running in unprivileged mode disables dynamic interface tracking");
+ }
+
#ifdef HAVE_LINUX_CAPABILITIES
do {
/* We may be running under non-root uid now, but we still hold full root privileges!