socket: add support for binding sockets to device
As a Linux-specific feature, allow sockets to be bound to a device using the SO_BINDTODEVICE socket option. The CAP_NET_RAW capability is required for setting the option.
This commit is contained in:
parent
0f04baeb97
commit
4ef944b734
9 changed files with 45 additions and 20 deletions
2
client.c
2
client.c
|
@ -222,7 +222,7 @@ open_socket(struct Address *addr)
|
|||
|
||||
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
|
||||
|
|
2
cmdmon.c
2
cmdmon.c
|
@ -173,7 +173,7 @@ open_socket(int family)
|
|||
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));
|
||||
|
|
2
ntp_io.c
2
ntp_io.c
|
@ -103,7 +103,7 @@ open_socket(int family, int local_port, int client_only, IPSockAddr *remote_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));
|
||||
|
|
|
@ -125,7 +125,7 @@ add_interface(CNF_HwTsInterface *conf_iface)
|
|||
return 1;
|
||||
}
|
||||
|
||||
sock_fd = SCK_OpenUdpSocket(NULL, NULL, 0);
|
||||
sock_fd = SCK_OpenUdpSocket(NULL, NULL, NULL, 0);
|
||||
if (sock_fd < 0)
|
||||
return 0;
|
||||
|
||||
|
@ -285,7 +285,7 @@ update_interface_speed(struct Interface *iface)
|
|||
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;
|
||||
|
||||
|
@ -320,7 +320,7 @@ check_timestamping_option(int option)
|
|||
{
|
||||
int sock_fd;
|
||||
|
||||
sock_fd = SCK_OpenUdpSocket(NULL, NULL, 0);
|
||||
sock_fd = SCK_OpenUdpSocket(NULL, NULL, NULL, 0);
|
||||
if (sock_fd < 0)
|
||||
return 0;
|
||||
|
||||
|
@ -341,7 +341,7 @@ open_dummy_socket(void)
|
|||
{
|
||||
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;
|
||||
|
||||
|
|
|
@ -325,7 +325,7 @@ NKC_Start(NKC_Instance inst)
|
|||
|
||||
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;
|
||||
|
||||
|
|
|
@ -268,7 +268,7 @@ open_socket(int family, int port)
|
|||
|
||||
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;
|
||||
|
|
31
socket.c
31
socket.c
|
@ -336,6 +336,23 @@ is_any_address(IPAddr *addr)
|
|||
|
||||
/* ================================================== */
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -403,7 +420,8 @@ connect_ip_address(int sock_fd, IPSockAddr *addr)
|
|||
/* ================================================== */
|
||||
|
||||
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;
|
||||
|
||||
|
@ -442,6 +460,9 @@ open_ip_socket(IPSockAddr *remote_addr, IPSockAddr *local_addr, int type, int fl
|
|||
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)) &&
|
||||
|
@ -1213,17 +1234,17 @@ SCK_SetPrivBind(int (*function)(int sock_fd, struct sockaddr *address,
|
|||
/* ================================================== */
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
|
8
socket.h
8
socket.h
|
@ -92,9 +92,11 @@ extern void SCK_GetLoopbackIPAddress(int family, IPAddr *local_addr);
|
|||
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,
|
||||
|
|
|
@ -437,10 +437,12 @@ SYS_Linux_DropRoot(uid_t uid, gid_t gid, int clock_control)
|
|||
|
||||
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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue