switch (addr->type) {
case SCK_ADDR_IP:
- sock_fd = SCK_OpenUdpSocket(&addr->addr.ip, NULL, 0);
+ sock_fd = SCK_OpenUdpSocket(&addr->addr.ip, NULL, NULL, 0);
break;
case SCK_ADDR_UNIX:
/* Construct path of our socket. Use the same directory as the server
SCK_GetLoopbackIPAddress(family, &local_addr.ip_addr);
local_addr.port = port;
- sock_fd = SCK_OpenUdpSocket(NULL, &local_addr, SCK_FLAG_RX_DEST_ADDR);
+ sock_fd = SCK_OpenUdpSocket(NULL, &local_addr, NULL, SCK_FLAG_RX_DEST_ADDR);
if (sock_fd < 0) {
LOG(LOGS_ERR, "Could not open command socket on %s",
UTI_IPSockAddrToString(&local_addr));
if (!client_only)
sock_flags |= SCK_FLAG_BROADCAST;
- sock_fd = SCK_OpenUdpSocket(remote_addr, &local_addr, sock_flags);
+ sock_fd = SCK_OpenUdpSocket(remote_addr, &local_addr, NULL, sock_flags);
if (sock_fd < 0) {
if (!client_only)
LOG(LOGS_ERR, "Could not open NTP socket on %s", UTI_IPSockAddrToString(&local_addr));
return 1;
}
- sock_fd = SCK_OpenUdpSocket(NULL, NULL, 0);
+ sock_fd = SCK_OpenUdpSocket(NULL, NULL, NULL, 0);
if (sock_fd < 0)
return 0;
struct ifreq req;
int sock_fd, link_speed;
- sock_fd = SCK_OpenUdpSocket(NULL, NULL, 0);
+ sock_fd = SCK_OpenUdpSocket(NULL, NULL, NULL, 0);
if (sock_fd < 0)
return;
{
int sock_fd;
- sock_fd = SCK_OpenUdpSocket(NULL, NULL, 0);
+ sock_fd = SCK_OpenUdpSocket(NULL, NULL, NULL, 0);
if (sock_fd < 0)
return 0;
{
int sock_fd, events = 0;
- sock_fd = SCK_OpenUdpSocket(NULL, NULL, 0);
+ sock_fd = SCK_OpenUdpSocket(NULL, NULL, NULL, 0);
if (sock_fd < 0)
return INVALID_SOCK_FD;
local_addr.port = 0;
- sock_fd = SCK_OpenTcpSocket(&inst->address, &local_addr, 0);
+ sock_fd = SCK_OpenTcpSocket(&inst->address, &local_addr, NULL, 0);
if (sock_fd < 0)
return 0;
local_addr.port = port;
- sock_fd = SCK_OpenTcpSocket(NULL, &local_addr, 0);
+ sock_fd = SCK_OpenTcpSocket(NULL, &local_addr, NULL, 0);
if (sock_fd < 0) {
LOG(LOGS_ERR, "Could not open NTS-KE socket on %s", UTI_IPSockAddrToString(&local_addr));
return INVALID_SOCK_FD;
/* ================================================== */
+static int
+bind_device(int sock_fd, const char *iface)
+{
+#ifdef SO_BINDTODEVICE
+ if (setsockopt(sock_fd, SOL_SOCKET, SO_BINDTODEVICE, iface, strlen(iface) + 1) < 0) {
+ DEBUG_LOG("Could not bind socket to %s : %s", iface, strerror(errno));
+ return 0;
+ }
+ return 1;
+#else
+ DEBUG_LOG("Could not bind socket to %s : %s", "Not supported");
+ return 0;
+#endif
+}
+
+/* ================================================== */
+
static int
bind_ip_address(int sock_fd, IPSockAddr *addr, int flags)
{
/* ================================================== */
static int
-open_ip_socket(IPSockAddr *remote_addr, IPSockAddr *local_addr, int type, int flags)
+open_ip_socket(IPSockAddr *remote_addr, IPSockAddr *local_addr, const char *iface,
+ int type, int flags)
{
int domain, family, sock_fd;
if (!set_ip_options(sock_fd, family, flags))
goto error;
+ if (iface && !bind_device(sock_fd, iface))
+ goto error;
+
/* Bind the socket if a non-any local address/port was specified */
if (local_addr && local_addr->ip_addr.family != IPADDR_UNSPEC &&
(local_addr->port != 0 || !is_any_address(&local_addr->ip_addr)) &&
/* ================================================== */
int
-SCK_OpenUdpSocket(IPSockAddr *remote_addr, IPSockAddr *local_addr, int flags)
+SCK_OpenUdpSocket(IPSockAddr *remote_addr, IPSockAddr *local_addr, const char *iface, int flags)
{
- return open_ip_socket(remote_addr, local_addr, SOCK_DGRAM, flags);
+ return open_ip_socket(remote_addr, local_addr, iface, SOCK_DGRAM, flags);
}
/* ================================================== */
int
-SCK_OpenTcpSocket(IPSockAddr *remote_addr, IPSockAddr *local_addr, int flags)
+SCK_OpenTcpSocket(IPSockAddr *remote_addr, IPSockAddr *local_addr, const char *iface, int flags)
{
- return open_ip_socket(remote_addr, local_addr, SOCK_STREAM, flags);
+ return open_ip_socket(remote_addr, local_addr, iface, SOCK_STREAM, flags);
}
/* ================================================== */
extern void SCK_SetPrivBind(int (*function)(int sock_fd, struct sockaddr *address,
socklen_t address_len));
-/* Open socket */
-extern int SCK_OpenUdpSocket(IPSockAddr *remote_addr, IPSockAddr *local_addr, int flags);
-extern int SCK_OpenTcpSocket(IPSockAddr *remote_addr, IPSockAddr *local_addr, int flags);
+/* Open a socket (addresses and iface may be NULL) */
+extern int SCK_OpenUdpSocket(IPSockAddr *remote_addr, IPSockAddr *local_addr,
+ const char *iface, int flags);
+extern int SCK_OpenTcpSocket(IPSockAddr *remote_addr, IPSockAddr *local_addr,
+ const char *iface, int flags);
extern int SCK_OpenUnixDatagramSocket(const char *remote_addr, const char *local_addr,
int flags);
extern int SCK_OpenUnixStreamSocket(const char *remote_addr, const char *local_addr,
UTI_DropRoot(uid, gid);
- /* Keep CAP_NET_BIND_SERVICE only if a server NTP port can be opened
- and keep CAP_SYS_TIME only if the clock control is enabled */
- if (snprintf(cap_text, sizeof (cap_text), "%s %s",
+ /* Keep CAP_NET_BIND_SERVICE if the NTP server sockets may need to be bound.
+ Keep CAP_NET_RAW if an NTP socket may need to be bound to a device.
+ Keep CAP_SYS_TIME if the clock control is enabled. */
+ if (snprintf(cap_text, sizeof (cap_text), "%s %s %s",
CNF_GetNTPPort() ? "cap_net_bind_service=ep" : "",
+ 0 ? "cap_net_raw=ep" : "",
clock_control ? "cap_sys_time=ep" : "") >= sizeof (cap_text))
assert(0);