Add IPv6 support

This commit is contained in:
Miroslav Lichvar 2009-10-09 15:00:59 +02:00
parent 183d56fd40
commit 8265ff2890
32 changed files with 1709 additions and 770 deletions

163
acquire.c
View file

@ -65,7 +65,8 @@
#define RETRANSMISSION_TIMEOUT (1.0) #define RETRANSMISSION_TIMEOUT (1.0)
typedef struct { unsigned long ip_addr; typedef struct {
IPAddr ip_addr; /* Address of the server */
int sanity; /* Flag indicating whether source int sanity; /* Flag indicating whether source
looks sane or not */ looks sane or not */
int n_dead_probes; /* Number of probes sent to the server int n_dead_probes; /* Number of probes sent to the server
@ -93,7 +94,18 @@ static int n_completed_sources;
static int init_slew_threshold = -1; static int init_slew_threshold = -1;
static int sock_fd = -1; union sockaddr_in46 {
struct sockaddr_in in4;
#ifdef HAVE_IPV6
struct sockaddr_in6 in6;
#endif
struct sockaddr u;
};
static int sock_fd4 = -1;
#ifdef HAVE_IPV6
static int sock_fd6 = -1;
#endif
/* ================================================== */ /* ================================================== */
@ -143,12 +155,13 @@ ACQ_Finalise(void)
/* ================================================== */ /* ================================================== */
static void static int
initialise_io(void) prepare_socket(int family)
{ {
unsigned short port_number = CNF_GetAcquisitionPort(); unsigned short port_number = CNF_GetAcquisitionPort();
int sock_fd;
sock_fd = socket(AF_INET, SOCK_DGRAM, 0); sock_fd = socket(family, SOCK_DGRAM, 0);
if (sock_fd < 0) { if (sock_fd < 0) {
LOG_FATAL(LOGF_Acquire, "Could not open socket : %s", strerror(errno)); LOG_FATAL(LOGF_Acquire, "Could not open socket : %s", strerror(errno));
@ -158,18 +171,48 @@ initialise_io(void)
/* Don't bother binding this socket - we're not fussed what port /* Don't bother binding this socket - we're not fussed what port
number it gets */ number it gets */
} else { } else {
struct sockaddr_in my_addr; union sockaddr_in46 my_addr;
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(port_number); memset(&my_addr, 0, sizeof (my_addr));
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sock_fd, (struct sockaddr *) &my_addr, sizeof(my_addr)) < 0) { switch (family) {
case AF_INET:
my_addr.in4.sin_family = family;
my_addr.in4.sin_port = htons(port_number);
my_addr.in4.sin_addr.s_addr = htonl(INADDR_ANY);
break;
#ifdef HAVE_IPV6
case AF_INET6:
my_addr.in6.sin6_family = family;
my_addr.in6.sin6_port = htons(port_number);
my_addr.in6.sin6_addr = in6addr_any;
break;
#endif
default:
assert(0);
}
if (bind(sock_fd, &my_addr.u, sizeof(my_addr)) < 0) {
LOG(LOGS_ERR, LOGF_Acquire, "Could not bind socket : %s\n", strerror(errno)); LOG(LOGS_ERR, LOGF_Acquire, "Could not bind socket : %s\n", strerror(errno));
/* but keep running */ /* but keep running */
} }
} }
SCH_AddInputFileHandler(sock_fd, read_from_socket, NULL); SCH_AddInputFileHandler(sock_fd, read_from_socket, (void *)(long)sock_fd);
return sock_fd;
}
/* ================================================== */
static void
initialise_io(int family)
{
if (family == IPADDR_INET4 || family == IPADDR_UNSPEC)
sock_fd4 = prepare_socket(AF_INET);
#ifdef HAVE_IPV6
if (family == IPADDR_INET6 || family == IPADDR_UNSPEC)
sock_fd6 = prepare_socket(AF_INET6);
#endif
} }
/* ================================================== */ /* ================================================== */
@ -177,10 +220,18 @@ initialise_io(void)
static void static void
finalise_io(void) finalise_io(void)
{ {
if (sock_fd >= 0) { if (sock_fd4 >= 0) {
SCH_RemoveInputFileHandler(sock_fd); SCH_RemoveInputFileHandler(sock_fd4);
close(sock_fd); close(sock_fd4);
} }
sock_fd4 = -1;
#ifdef HAVE_IPV6
if (sock_fd6 >= 0) {
SCH_RemoveInputFileHandler(sock_fd6);
close(sock_fd6);
}
sock_fd6 = -1;
#endif
return; return;
} }
@ -195,10 +246,11 @@ probe_source(SourceRecord *src)
NTP_Mode my_mode = MODE_CLIENT; NTP_Mode my_mode = MODE_CLIENT;
struct timeval cooked; struct timeval cooked;
double local_time_err; double local_time_err;
struct sockaddr_in his_addr; union sockaddr_in46 his_addr;
int sock_fd;
#if 0 #if 0
printf("Sending probe to %08lx sent=%d samples=%d\n", src->ip_addr, src->n_probes_sent, src->n_samples); printf("Sending probe to %s sent=%d samples=%d\n", UTI_IPToString(&src->ip_addr), src->n_probes_sent, src->n_samples);
#endif #endif
pkt.lvm = (((LEAP_Unsynchronised << 6) & 0xc0) | pkt.lvm = (((LEAP_Unsynchronised << 6) & 0xc0) |
@ -219,18 +271,37 @@ probe_source(SourceRecord *src)
pkt.receive_ts.lo = 0; /* Set to 0 */ pkt.receive_ts.lo = 0; /* Set to 0 */
/* And do transmission */ /* And do transmission */
his_addr.sin_addr.s_addr = htonl(src->ip_addr);
his_addr.sin_port = htons(123); /* Fixed for now */ memset(&his_addr, 0, sizeof (his_addr));
his_addr.sin_family = AF_INET; switch (src->ip_addr.family) {
case IPADDR_INET4:
his_addr.in4.sin_addr.s_addr = htonl(src->ip_addr.addr.in4);
his_addr.in4.sin_port = htons(123); /* Fixed for now */
his_addr.in4.sin_family = AF_INET;
sock_fd = sock_fd4;
break;
#ifdef HAVE_IPV6
case IPADDR_INET6:
memcpy(&his_addr.in6.sin6_addr.s6_addr, &src->ip_addr.addr.in6,
sizeof (his_addr.in6.sin6_addr.s6_addr));
his_addr.in6.sin6_port = htons(123); /* Fixed for now */
his_addr.in6.sin6_family = AF_INET6;
sock_fd = sock_fd6;
break;
#endif
default:
assert(0);
}
LCL_ReadCookedTime(&cooked, &local_time_err); LCL_ReadCookedTime(&cooked, &local_time_err);
UTI_TimevalToInt64(&cooked, &pkt.transmit_ts); UTI_TimevalToInt64(&cooked, &pkt.transmit_ts);
if (sendto(sock_fd, (void *) &pkt, NTP_NORMAL_PACKET_SIZE, if (sendto(sock_fd, (void *) &pkt, NTP_NORMAL_PACKET_SIZE,
0, 0,
(struct sockaddr *) &his_addr, sizeof(his_addr)) < 0) { &his_addr.u, sizeof(his_addr)) < 0) {
LOG(LOGS_WARN, LOGF_Acquire, "Could not send to %s : %s", LOG(LOGS_WARN, LOGF_Acquire, "Could not send to %s : %s",
UTI_IPToDottedQuad(src->ip_addr), UTI_IPToString(&src->ip_addr),
strerror(errno)); strerror(errno));
} }
@ -253,7 +324,7 @@ transmit_timeout(void *x)
src->timer_running = 0; src->timer_running = 0;
#if 0 #if 0
printf("Timeout expired for server %08lx\n", src->ip_addr); printf("Timeout expired for server %s\n", UTI_IPToString(&src->ip_addr));
#endif #endif
if (src->n_dead_probes < MAX_DEAD_PROBES) { if (src->n_dead_probes < MAX_DEAD_PROBES) {
@ -357,11 +428,12 @@ read_from_socket(void *anything)
{ {
int status; int status;
ReceiveBuffer msg; ReceiveBuffer msg;
struct sockaddr_in his_addr; union sockaddr_in46 his_addr;
int sock_fd;
socklen_t his_addr_len; socklen_t his_addr_len;
int flags; int flags;
int message_length; int message_length;
unsigned long remote_ip; IPAddr remote_ip;
int i, ok; int i, ok;
struct timeval now; struct timeval now;
double local_time_err; double local_time_err;
@ -374,24 +446,39 @@ read_from_socket(void *anything)
/* Get timestamp */ /* Get timestamp */
LCL_ReadCookedTime(&now, &local_time_err); LCL_ReadCookedTime(&now, &local_time_err);
sock_fd = (long)anything;
status = recvfrom (sock_fd, (char *)&msg, message_length, flags, status = recvfrom (sock_fd, (char *)&msg, message_length, flags,
(struct sockaddr *) &his_addr, &his_addr_len); &his_addr.u, &his_addr_len);
if (status < 0) { if (status < 0) {
LOG(LOGS_WARN, LOGF_Acquire, "Error reading from socket, %s", strerror(errno)); LOG(LOGS_WARN, LOGF_Acquire, "Error reading from socket, %s", strerror(errno));
return; return;
} }
remote_ip = ntohl(his_addr.sin_addr.s_addr); switch (his_addr.u.sa_family) {
case AF_INET:
remote_ip.family = IPADDR_INET4;
remote_ip.addr.in4 = ntohl(his_addr.in4.sin_addr.s_addr);
break;
#ifdef HAVE_IPV6
case AF_INET6:
remote_ip.family = IPADDR_INET6;
memcpy(&remote_ip.addr.in6, his_addr.in6.sin6_addr.s6_addr,
sizeof (remote_ip.addr.in6));
break;
#endif
default:
assert(0);
}
#if 0 #if 0
printf("Got message from %08lx\n", remote_ip); printf("Got message from %s\n", UTI_IPToString(&remote_ip));
#endif #endif
/* Find matching host */ /* Find matching host */
ok = 0; ok = 0;
for (i=0; i<n_sources; i++) { for (i=0; i<n_sources; i++) {
if (remote_ip == sources[i].ip_addr) { if (UTI_CompareIPs(&remote_ip, &sources[i].ip_addr, NULL) == 0) {
ok = 1; ok = 1;
break; break;
} }
@ -418,7 +505,7 @@ read_from_socket(void *anything)
(src->n_total_samples >= MAX_SAMPLES)) { (src->n_total_samples >= MAX_SAMPLES)) {
++n_completed_sources; ++n_completed_sources;
#if 0 #if 0
printf("Source %08lx completed\n", src->ip_addr); printf("Source %s completed\n", UTI_IPToString(&src->ip_addr));
#endif #endif
if (n_completed_sources == n_sources) { if (n_completed_sources == n_sources) {
wind_up_acquisition(); wind_up_acquisition();
@ -440,7 +527,7 @@ start_next_source(void)
{ {
probe_source(sources + n_started_sources); probe_source(sources + n_started_sources);
#if 0 #if 0
printf("Trying to start source %08lx\n", sources[n_started_sources].ip_addr); printf("Trying to start source %s\n", UTI_IPToString(&sources[n_started_sources].ip_addr));
#endif #endif
n_started_sources++; n_started_sources++;
@ -552,10 +639,10 @@ process_measurements(void)
for (i=0; i<2*n_sane_sources; i++) { for (i=0; i<2*n_sane_sources; i++) {
#if 0 #if 0
fprintf(stderr, "Endpoint type %s source index %d [ip=%08lx] offset=%.6f\n", fprintf(stderr, "Endpoint type %s source index %d [ip=%s] offset=%.6f\n",
(eps[i].type == LO) ? "LO" : "HIGH", (eps[i].type == LO) ? "LO" : "HIGH",
eps[i].index, eps[i].index,
sources[eps[i].index].ip_addr, UTI_IPToString(&sources[eps[i].index].ip_addr),
eps[i].offset); eps[i].offset);
#endif #endif
@ -655,10 +742,10 @@ start_source_timeout_handler(void *not_used)
/* ================================================== */ /* ================================================== */
void void
ACQ_StartAcquisition(int n, unsigned long *ip_addrs, int threshold, void (*after_hook)(void *), void *anything) ACQ_StartAcquisition(int n, IPAddr *ip_addrs, int threshold, void (*after_hook)(void *), void *anything)
{ {
int i; int i, ip4, ip6;
saved_after_hook = after_hook; saved_after_hook = after_hook;
saved_after_hook_anything = anything; saved_after_hook_anything = anything;
@ -670,14 +757,18 @@ ACQ_StartAcquisition(int n, unsigned long *ip_addrs, int threshold, void (*after
n_sources = n; n_sources = n;
sources = MallocArray(SourceRecord, n); sources = MallocArray(SourceRecord, n);
for (i=0; i<n; i++) { for (i = ip4 = ip6 = 0; i < n; i++) {
sources[i].ip_addr = ip_addrs[i]; sources[i].ip_addr = ip_addrs[i];
sources[i].n_samples = 0; sources[i].n_samples = 0;
sources[i].n_total_samples = 0; sources[i].n_total_samples = 0;
sources[i].n_dead_probes = 0; sources[i].n_dead_probes = 0;
if (ip_addrs[i].family == IPADDR_INET4)
ip4++;
else if (ip_addrs[i].family == IPADDR_INET6)
ip6++;
} }
initialise_io(); initialise_io((ip4 && ip6) ? IPADDR_UNSPEC : (ip4 ? IPADDR_INET4 : IPADDR_INET6));
/* Start sampling first source */ /* Start sampling first source */
start_next_source(); start_next_source();

View file

@ -31,13 +31,15 @@
#ifndef GOT_ACQUIRE_H #ifndef GOT_ACQUIRE_H
#define GOT_ACQUIRE_H #define GOT_ACQUIRE_H
#include "addressing.h"
typedef struct ACQ_SourceRecord *ACQ_Source; typedef struct ACQ_SourceRecord *ACQ_Source;
extern void ACQ_Initialise(void); extern void ACQ_Initialise(void);
extern void ACQ_Finalise(void); extern void ACQ_Finalise(void);
extern void ACQ_StartAcquisition(int n, unsigned long *ip_addrs, int init_slew_threshold, extern void ACQ_StartAcquisition(int n, IPAddr *ip_addrs, int init_slew_threshold,
void (*after_hook)(void *), void *anything); void (*after_hook)(void *), void *anything);
extern void ACQ_AccumulateSample(ACQ_Source acq_source, double offset, double root_distance); extern void ACQ_AccumulateSample(ACQ_Source acq_source, double offset, double root_distance);

View file

@ -31,17 +31,28 @@
#ifndef GOT_ADDRESSING_H #ifndef GOT_ADDRESSING_H
#define GOT_ADDRESSING_H #define GOT_ADDRESSING_H
/* This type is used to represent an IPv4 address and port #include "sysincl.h"
number. Both parts are in HOST order, NOT network order. */
/* This type is used to represent an IPv4 address or IPv6 address.
All parts are in HOST order, NOT network order. */
#define IPADDR_UNSPEC 0
#define IPADDR_INET4 1
#define IPADDR_INET6 2
typedef struct { typedef struct {
unsigned long ip_addr; union {
unsigned long local_ip_addr; uint32_t in4;
uint8_t in6[16];
} addr;
uint16_t family;
} IPAddr;
typedef struct {
IPAddr ip_addr;
IPAddr local_ip_addr;
unsigned short port; unsigned short port;
} NTP_Remote_Address; } NTP_Remote_Address;
#if 0
unsigned long NTP_IP_Address;
#endif
#endif /* GOT_ADDRESSING_H */ #endif /* GOT_ADDRESSING_H */

View file

@ -51,23 +51,35 @@ typedef struct _TableNode {
} TableNode; } TableNode;
struct ADF_AuthTableInst { struct ADF_AuthTableInst {
TableNode base; TableNode base4; /* IPv4 node */
TableNode base6; /* IPv6 node */
}; };
/* ================================================== */ /* ================================================== */
inline static unsigned long static void
get_subnet(unsigned long addr) split_ip6(IPAddr *ip, uint32_t *dst)
{ {
return (addr >> (32-NBITS)) & ((1UL<<NBITS) - 1); int i;
for (i = 0; i < 4; i++)
dst[i] = ip->addr.in6[i * 4 + 0] << 24 |
ip->addr.in6[i * 4 + 1] << 16 |
ip->addr.in6[i * 4 + 2] << 8 |
ip->addr.in6[i * 4 + 3];
} }
/* ================================================== */ /* ================================================== */
inline static unsigned long inline static uint32_t
get_residual(unsigned long addr) get_subnet(uint32_t *addr, unsigned int where)
{ {
return (addr << NBITS); int off;
off = where / 32;
where %= 32;
return (addr[off] >> (32 - NBITS - where)) & ((1UL << NBITS) - 1);
} }
/* ================================================== */ /* ================================================== */
@ -79,8 +91,10 @@ ADF_CreateTable(void)
result = MallocNew(struct ADF_AuthTableInst); result = MallocNew(struct ADF_AuthTableInst);
/* Default is that nothing is allowed */ /* Default is that nothing is allowed */
result->base.state = DENY; result->base4.state = DENY;
result->base.extended = NULL; result->base4.extended = NULL;
result->base6.state = DENY;
result->base6.extended = NULL;
return result; return result;
} }
@ -135,22 +149,22 @@ open_node(TableNode *node)
static ADF_Status static ADF_Status
set_subnet(TableNode *start_node, set_subnet(TableNode *start_node,
unsigned long ip, uint32_t *ip,
int ip_len,
int subnet_bits, int subnet_bits,
State new_state, State new_state,
int delete_children) int delete_children)
{ {
int bits_to_go; int bits_to_go, bits_consumed;
unsigned long residual; uint32_t subnet;
unsigned long subnet;
TableNode *node; TableNode *node;
bits_consumed = 0;
bits_to_go = subnet_bits; bits_to_go = subnet_bits;
residual = ip;
node = start_node; node = start_node;
if ((subnet_bits < 0) || if ((subnet_bits < 0) ||
(subnet_bits > 32)) { (subnet_bits > 32 * ip_len)) {
return ADF_BADSUBNET; return ADF_BADSUBNET;
@ -159,13 +173,13 @@ set_subnet(TableNode *start_node,
if ((bits_to_go & (NBITS-1)) == 0) { if ((bits_to_go & (NBITS-1)) == 0) {
while (bits_to_go > 0) { while (bits_to_go > 0) {
subnet = get_subnet(residual); subnet = get_subnet(ip, bits_consumed);
residual = get_residual(residual);
if (!(node->extended)) { if (!(node->extended)) {
open_node(node); open_node(node);
} }
node = &(node->extended[subnet]); node = &(node->extended[subnet]);
bits_to_go -= NBITS; bits_to_go -= NBITS;
bits_consumed += NBITS;
} }
if (delete_children) { if (delete_children) {
@ -178,18 +192,18 @@ set_subnet(TableNode *start_node,
TableNode *this_node; TableNode *this_node;
while (bits_to_go >= NBITS) { while (bits_to_go >= NBITS) {
subnet = get_subnet(residual); subnet = get_subnet(ip, bits_consumed);
residual = get_residual(residual);
if (!(node->extended)) { if (!(node->extended)) {
open_node(node); open_node(node);
} }
node = &(node->extended[subnet]); node = &(node->extended[subnet]);
bits_to_go -= NBITS; bits_to_go -= NBITS;
bits_consumed += NBITS;
} }
/* How many subnet entries to set : 1->8, 2->4, 3->2 */ /* How many subnet entries to set : 1->8, 2->4, 3->2 */
N = 1 << (NBITS-bits_to_go); N = 1 << (NBITS-bits_to_go);
subnet = get_subnet(residual); subnet = get_subnet(ip, bits_consumed);
if (!(node->extended)) { if (!(node->extended)) {
open_node(node); open_node(node);
} }
@ -210,12 +224,41 @@ set_subnet(TableNode *start_node,
/* ================================================== */ /* ================================================== */
static ADF_Status
set_subnet_(ADF_AuthTable table,
IPAddr *ip_addr,
int subnet_bits,
State new_state,
int delete_children)
{
uint32_t ip6[4];
switch (ip_addr->family) {
case IPADDR_INET4:
return set_subnet(&table->base4, &ip_addr->addr.in4, 1, subnet_bits, new_state, delete_children);
case IPADDR_INET6:
split_ip6(ip_addr, ip6);
return set_subnet(&table->base6, ip6, 4, subnet_bits, new_state, delete_children);
case IPADDR_UNSPEC:
/* Apply to both, subnet_bits has to be 0 */
if (subnet_bits != 0)
return ADF_BADSUBNET;
memset(ip6, 0, sizeof (ip6));
if (set_subnet(&table->base4, ip6, 1, 0, new_state, delete_children) == ADF_SUCCESS &&
set_subnet(&table->base6, ip6, 4, 0, new_state, delete_children) == ADF_SUCCESS)
return ADF_SUCCESS;
break;
}
return ADF_BADSUBNET;
}
ADF_Status ADF_Status
ADF_Allow(ADF_AuthTable table, ADF_Allow(ADF_AuthTable table,
unsigned long ip, IPAddr *ip,
int subnet_bits) int subnet_bits)
{ {
return set_subnet(&(table->base), ip, subnet_bits, ALLOW, 0); return set_subnet_(table, ip, subnet_bits, ALLOW, 0);
} }
/* ================================================== */ /* ================================================== */
@ -223,30 +266,30 @@ ADF_Allow(ADF_AuthTable table,
ADF_Status ADF_Status
ADF_AllowAll(ADF_AuthTable table, ADF_AllowAll(ADF_AuthTable table,
unsigned long ip, IPAddr *ip,
int subnet_bits) int subnet_bits)
{ {
return set_subnet(&(table->base), ip, subnet_bits, ALLOW, 1); return set_subnet_(table, ip, subnet_bits, ALLOW, 1);
} }
/* ================================================== */ /* ================================================== */
ADF_Status ADF_Status
ADF_Deny(ADF_AuthTable table, ADF_Deny(ADF_AuthTable table,
unsigned long ip, IPAddr *ip,
int subnet_bits) int subnet_bits)
{ {
return set_subnet(&(table->base), ip, subnet_bits, DENY, 0); return set_subnet_(table, ip, subnet_bits, DENY, 0);
} }
/* ================================================== */ /* ================================================== */
ADF_Status ADF_Status
ADF_DenyAll(ADF_AuthTable table, ADF_DenyAll(ADF_AuthTable table,
unsigned long ip, IPAddr *ip,
int subnet_bits) int subnet_bits)
{ {
return set_subnet(&(table->base), ip, subnet_bits, DENY, 1); return set_subnet_(table, ip, subnet_bits, DENY, 1);
} }
/* ================================================== */ /* ================================================== */
@ -254,32 +297,33 @@ ADF_DenyAll(ADF_AuthTable table,
void void
ADF_DestroyTable(ADF_AuthTable table) ADF_DestroyTable(ADF_AuthTable table)
{ {
close_node(&(table->base)); close_node(&table->base4);
close_node(&table->base6);
Free(table); Free(table);
} }
/* ================================================== */ /* ================================================== */
static int static int
check_ip_in_node(TableNode *start_node, unsigned long ip) check_ip_in_node(TableNode *start_node, uint32_t *ip)
{ {
unsigned long residual, subnet; uint32_t subnet;
int bits_consumed = 0;
int result = 0; int result = 0;
int finished = 0; int finished = 0;
TableNode *node; TableNode *node;
State state=DENY; State state=DENY;
node = start_node; node = start_node;
residual = ip;
do { do {
if (node->state != AS_PARENT) { if (node->state != AS_PARENT) {
state = node->state; state = node->state;
} }
if (node->extended) { if (node->extended) {
subnet = get_subnet(residual); subnet = get_subnet(ip, bits_consumed);
residual = get_residual(residual);
node = &(node->extended[subnet]); node = &(node->extended[subnet]);
bits_consumed += NBITS;
} else { } else {
/* Make decision on this node */ /* Make decision on this node */
finished = 1; finished = 1;
@ -306,38 +350,63 @@ check_ip_in_node(TableNode *start_node, unsigned long ip)
int int
ADF_IsAllowed(ADF_AuthTable table, ADF_IsAllowed(ADF_AuthTable table,
unsigned long ip) IPAddr *ip_addr)
{ {
uint32_t ip6[4];
return check_ip_in_node(&(table->base), ip); switch (ip_addr->family) {
case IPADDR_INET4:
return check_ip_in_node(&table->base4, &ip_addr->addr.in4);
case IPADDR_INET6:
split_ip6(ip_addr, ip6);
return check_ip_in_node(&table->base6, ip6);
}
return 0;
} }
/* ================================================== */ /* ================================================== */
#if defined TEST #if defined TEST
static void print_node(TableNode *node, unsigned long addr, int shift, int subnet_bits) static void print_node(TableNode *node, uint32_t *addr, int ip_len, int shift, int subnet_bits)
{ {
unsigned long new_addr; uint32_t new_addr[4];
int i; int i;
TableNode *sub_node; TableNode *sub_node;
for (i=0; i<subnet_bits; i++) putchar(' '); for (i=0; i<subnet_bits; i++) putchar(' ');
printf("%d.%d.%d.%d/%d : %s\n", if (ip_len == 1)
((addr >> 24) & 255), printf("%d.%d.%d.%d",
((addr >> 16) & 255), ((addr[0] >> 24) & 255),
((addr >> 8) & 255), ((addr[0] >> 16) & 255),
((addr ) & 255), ((addr[0] >> 8) & 255),
((addr[0] ) & 255));
else {
for (i=0; i<4; i++) {
if (addr[i])
printf("%d.%d.%d.%d",
((addr[i] >> 24) & 255),
((addr[i] >> 16) & 255),
((addr[i] >> 8) & 255),
((addr[i] ) & 255));
putchar(i < 3 ? ':' : '\0');
}
}
printf("/%d : %s\n",
subnet_bits, subnet_bits,
(node->state == ALLOW) ? "allow" : (node->state == ALLOW) ? "allow" :
(node->state == DENY) ? "deny" : "as parent"); (node->state == DENY) ? "deny" : "as parent");
if (node->extended) { if (node->extended) {
for (i=0; i<16; i++) { for (i=0; i<16; i++) {
sub_node = &((*(node->extended))[i]); sub_node = &(node->extended[i]);
new_addr = addr | ((unsigned long) i << shift); new_addr[0] = addr[0];
print_node(sub_node, new_addr, shift - 4, subnet_bits + 4); new_addr[1] = addr[1];
new_addr[2] = addr[2];
new_addr[3] = addr[3];
new_addr[ip_len - 1 - shift / 32] |= ((uint32_t)i << (shift % 32));
print_node(sub_node, new_addr, ip_len, shift - 4, subnet_bits + 4);
} }
} }
return; return;
@ -346,11 +415,15 @@ static void print_node(TableNode *node, unsigned long addr, int shift, int subne
static void print_table(ADF_AuthTable table) static void print_table(ADF_AuthTable table)
{ {
unsigned long addr = 0; uint32_t addr[4];
int shift = 28;
int subnet_bits = 0;
print_node(&table->base, addr, shift, subnet_bits); memset(addr, 0, sizeof (addr));
printf("IPv4 table:\n");
print_node(&table->base4, addr, 1, 28, 0);
memset(addr, 0, sizeof (addr));
printf("IPv6 table:\n");
print_node(&table->base6, addr, 4, 124, 0);
return; return;
} }
@ -358,13 +431,41 @@ static void print_table(ADF_AuthTable table)
int main (int argc, char **argv) int main (int argc, char **argv)
{ {
IPAddr ip;
ADF_AuthTable table; ADF_AuthTable table;
table = ADF_CreateTable(); table = ADF_CreateTable();
ADF_Allow(table, 0x7e800000, 9); ip.family = IPADDR_INET4;
ADF_Deny(table, 0x7ecc0000, 14);
/* ADF_Deny(table, 0x7f000001, 32); */ ip.addr.in4 = 0x7e800000;
/* ADF_Allow(table, 0x7f000000, 8); */ ADF_Allow(table, &ip, 9);
ip.addr.in4 = 0x7ecc0000;
ADF_Deny(table, &ip, 14);
#if 0
ip.addr.in4 = 0x7f000001;
ADF_Deny(table, &ip, 32);
ip.addr.in4 = 0x7f000000;
ADF_Allow(table, &ip, 8);
#endif
printf("allowed: %d\n", ADF_IsAllowed(table, &ip));
ip.addr.in4 ^= 1;
printf("allowed: %d\n", ADF_IsAllowed(table, &ip));
ip.family = IPADDR_INET6;
memcpy(ip.addr.in6, "abcdefghijklmnop", 16);
ADF_Deny(table, &ip, 66);
ADF_Allow(table, &ip, 59);
memcpy(ip.addr.in6, "xbcdefghijklmnop", 16);
ADF_Deny(table, &ip, 128);
ip.addr.in6[15] ^= 3;
ADF_Allow(table, &ip, 127);
printf("allowed: %d\n", ADF_IsAllowed(table, &ip));
ip.addr.in4 ^= 1;
printf("allowed: %d\n", ADF_IsAllowed(table, &ip));
print_table(table); print_table(table);

View file

@ -31,6 +31,8 @@
#ifndef GOT_ADDRFILT_H #ifndef GOT_ADDRFILT_H
#define GOT_ADDRFILT_H #define GOT_ADDRFILT_H
#include "addressing.h"
typedef struct ADF_AuthTableInst *ADF_AuthTable; typedef struct ADF_AuthTableInst *ADF_AuthTable;
typedef enum { typedef enum {
@ -45,25 +47,25 @@ extern ADF_AuthTable ADF_CreateTable(void);
/* Allow anything in the supplied subnet, EXCEPT for any more specific /* Allow anything in the supplied subnet, EXCEPT for any more specific
subnets that are already defined */ subnets that are already defined */
extern ADF_Status ADF_Allow(ADF_AuthTable table, extern ADF_Status ADF_Allow(ADF_AuthTable table,
unsigned long ip, IPAddr *ip,
int subnet_bits); int subnet_bits);
/* Allow anything in the supplied subnet, overwriting existing /* Allow anything in the supplied subnet, overwriting existing
definitions for any more specific subnets */ definitions for any more specific subnets */
extern ADF_Status ADF_AllowAll(ADF_AuthTable table, extern ADF_Status ADF_AllowAll(ADF_AuthTable table,
unsigned long ip, IPAddr *ip,
int subnet_bits); int subnet_bits);
/* Deny anything in the supplied subnet, EXCEPT for any more specific /* Deny anything in the supplied subnet, EXCEPT for any more specific
subnets that are already defined */ subnets that are already defined */
extern ADF_Status ADF_Deny(ADF_AuthTable table, extern ADF_Status ADF_Deny(ADF_AuthTable table,
unsigned long ip, IPAddr *ip,
int subnet_bits); int subnet_bits);
/* Deny anything in the supplied subnet, overwriting existing /* Deny anything in the supplied subnet, overwriting existing
definitions for any more specific subnets */ definitions for any more specific subnets */
extern ADF_Status ADF_DenyAll(ADF_AuthTable table, extern ADF_Status ADF_DenyAll(ADF_AuthTable table,
unsigned long ip, IPAddr *ip,
int subnet_bits); int subnet_bits);
/* Clear up the table */ /* Clear up the table */
@ -72,6 +74,6 @@ extern void ADF_DestroyTable(ADF_AuthTable table);
/* Check whether a given IP address is allowed by the rules in /* Check whether a given IP address is allowed by the rules in
the table */ the table */
extern int ADF_IsAllowed(ADF_AuthTable table, extern int ADF_IsAllowed(ADF_AuthTable table,
unsigned long ip); IPAddr *ip);
#endif /* GOT_ADDRFILT_H */ #endif /* GOT_ADDRFILT_H */

View file

@ -132,7 +132,7 @@ timeout_handler(void *arbitrary)
/* ================================================== */ /* ================================================== */
void void
BRD_AddDestination(unsigned long addr, unsigned short port, int interval) BRD_AddDestination(IPAddr *addr, unsigned short port, int interval)
{ {
if (max_destinations == n_destinations) { if (max_destinations == n_destinations) {
/* Expand array */ /* Expand array */
@ -144,8 +144,8 @@ BRD_AddDestination(unsigned long addr, unsigned short port, int interval)
} }
} }
destinations[n_destinations].addr.ip_addr = addr; destinations[n_destinations].addr.ip_addr = *addr;
destinations[n_destinations].addr.local_ip_addr = 0; destinations[n_destinations].addr.local_ip_addr.family = IPADDR_UNSPEC;
destinations[n_destinations].addr.port = port; destinations[n_destinations].addr.port = port;
destinations[n_destinations].interval = interval; destinations[n_destinations].interval = interval;

View file

@ -31,9 +31,11 @@
#ifndef GOT_BROADCAST_H #ifndef GOT_BROADCAST_H
#define GOT_BROADCAST_H #define GOT_BROADCAST_H
#include "addressing.h"
extern void BRD_Initialise(void); extern void BRD_Initialise(void);
extern void BRD_Finalise(void); extern void BRD_Finalise(void);
extern void BRD_AddDestination(unsigned long addr, unsigned short port, int interval); extern void BRD_AddDestination(IPAddr *addr, unsigned short port, int interval);
#endif /* GOT_BROADCAST_H */ #endif /* GOT_BROADCAST_H */

48
candm.h
View file

@ -34,6 +34,7 @@
#define GOT_CANDM_H #define GOT_CANDM_H
#include "sysincl.h" #include "sysincl.h"
#include "addressing.h"
/* This is the default port to use for CANDM, if no alternative is /* This is the default port to use for CANDM, if no alternative is
defined */ defined */
@ -96,33 +97,33 @@
transmitted for each packet type. */ transmitted for each packet type. */
typedef struct { typedef struct {
uint32_t mask; IPAddr mask;
uint32_t address; IPAddr address;
int32_t EOR; int32_t EOR;
} REQ_Online; } REQ_Online;
typedef struct { typedef struct {
uint32_t mask; IPAddr mask;
uint32_t address; IPAddr address;
int32_t EOR; int32_t EOR;
} REQ_Offline; } REQ_Offline;
typedef struct { typedef struct {
uint32_t mask; IPAddr mask;
uint32_t address; IPAddr address;
int32_t n_good_samples; int32_t n_good_samples;
int32_t n_total_samples; int32_t n_total_samples;
int32_t EOR; int32_t EOR;
} REQ_Burst; } REQ_Burst;
typedef struct { typedef struct {
uint32_t address; IPAddr address;
int32_t new_minpoll; int32_t new_minpoll;
int32_t EOR; int32_t EOR;
} REQ_Modify_Minpoll; } REQ_Modify_Minpoll;
typedef struct { typedef struct {
uint32_t address; IPAddr address;
int32_t new_maxpoll; int32_t new_maxpoll;
int32_t EOR; int32_t EOR;
} REQ_Modify_Maxpoll; } REQ_Modify_Maxpoll;
@ -133,13 +134,13 @@ typedef struct {
} REQ_Dump; } REQ_Dump;
typedef struct { typedef struct {
uint32_t address; IPAddr address;
int32_t new_max_delay; int32_t new_max_delay;
int32_t EOR; int32_t EOR;
} REQ_Modify_Maxdelay; } REQ_Modify_Maxdelay;
typedef struct { typedef struct {
uint32_t address; IPAddr address;
int32_t new_max_delay_ratio; int32_t new_max_delay_ratio;
int32_t EOR; int32_t EOR;
} REQ_Modify_Maxdelayratio; } REQ_Modify_Maxdelayratio;
@ -184,18 +185,18 @@ typedef struct {
} REQ_Rekey; } REQ_Rekey;
typedef struct { typedef struct {
uint32_t ip; IPAddr ip;
int32_t subnet_bits; int32_t subnet_bits;
int32_t EOR; int32_t EOR;
} REQ_Allow_Deny; } REQ_Allow_Deny;
typedef struct { typedef struct {
uint32_t ip; IPAddr ip;
int32_t EOR; int32_t EOR;
} REQ_Ac_Check; } REQ_Ac_Check;
typedef struct { typedef struct {
uint32_t ip_addr; IPAddr ip_addr;
uint32_t port; uint32_t port;
int32_t minpoll; int32_t minpoll;
int32_t maxpoll; int32_t maxpoll;
@ -209,7 +210,7 @@ typedef struct {
} REQ_NTP_Source; } REQ_NTP_Source;
typedef struct { typedef struct {
uint32_t ip_addr; IPAddr ip_addr;
int32_t EOR; int32_t EOR;
} REQ_Del_Source; } REQ_Del_Source;
@ -250,7 +251,7 @@ typedef struct {
} REQ_CycleLogs; } REQ_CycleLogs;
typedef struct { typedef struct {
uint32_t ip; IPAddr ip;
uint32_t bits_specd; uint32_t bits_specd;
} REQ_SubnetsAccessed_Subnet; } REQ_SubnetsAccessed_Subnet;
@ -263,11 +264,11 @@ typedef struct {
/* This is based on the response size rather than the /* This is based on the response size rather than the
request size */ request size */
#define MAX_CLIENT_ACCESSES 16 #define MAX_CLIENT_ACCESSES 8
typedef struct { typedef struct {
uint32_t n_clients; uint32_t n_clients;
uint32_t client_ips[MAX_CLIENT_ACCESSES]; IPAddr client_ips[MAX_CLIENT_ACCESSES];
} REQ_ClientAccesses; } REQ_ClientAccesses;
typedef struct { typedef struct {
@ -310,9 +311,11 @@ typedef struct {
Version 3 : NTP_Source message lengthened (auto_offline) Version 3 : NTP_Source message lengthened (auto_offline)
Version 4 : IPv6 addressing added
*/ */
#define PROTO_VERSION_NUMBER 3 #define PROTO_VERSION_NUMBER 4
/* ================================================== */ /* ================================================== */
@ -419,6 +422,7 @@ typedef struct {
#define STT_BADRTCFILE 14 #define STT_BADRTCFILE 14
#define STT_INACTIVE 15 #define STT_INACTIVE 15
#define STT_BADSAMPLE 16 #define STT_BADSAMPLE 16
#define STT_INVALIDAF 17
typedef struct { typedef struct {
int32_t EOR; int32_t EOR;
@ -440,7 +444,7 @@ typedef struct {
#define RPY_SD_ST_OTHER 4 #define RPY_SD_ST_OTHER 4
typedef struct { typedef struct {
uint32_t ip_addr; IPAddr ip_addr;
uint16_t poll; uint16_t poll;
uint16_t stratum; uint16_t stratum;
uint16_t state; uint16_t state;
@ -472,7 +476,7 @@ typedef struct {
} RPY_Tracking; } RPY_Tracking;
typedef struct { typedef struct {
uint32_t ip_addr; IPAddr ip_addr;
uint32_t n_samples; uint32_t n_samples;
uint32_t n_runs; uint32_t n_runs;
uint32_t span_seconds; uint32_t span_seconds;
@ -500,7 +504,7 @@ typedef struct {
} RPY_ManualTimestamp; } RPY_ManualTimestamp;
typedef struct { typedef struct {
uint32_t ip; IPAddr ip;
uint32_t bits_specd; uint32_t bits_specd;
uint32_t bitmap[8]; uint32_t bitmap[8];
} RPY_SubnetsAccessed_Subnet; } RPY_SubnetsAccessed_Subnet;
@ -511,7 +515,7 @@ typedef struct {
} RPY_SubnetsAccessed; } RPY_SubnetsAccessed;
typedef struct { typedef struct {
uint32_t ip; IPAddr ip;
uint32_t client_hits; uint32_t client_hits;
uint32_t peer_hits; uint32_t peer_hits;
uint32_t cmd_hits_auth; uint32_t cmd_hits_auth;

416
client.c
View file

@ -58,8 +58,16 @@
/* ================================================== */ /* ================================================== */
union sockaddr_in46 {
struct sockaddr_in in4;
#ifdef HAVE_IPV6
struct sockaddr_in6 in6;
#endif
struct sockaddr u;
};
static int sock_fd; static int sock_fd;
struct sockaddr_in his_addr; union sockaddr_in46 his_addr;
static int on_terminal = 0; static int on_terminal = 0;
@ -137,62 +145,64 @@ read_line(void)
} }
/* ================================================== */
static unsigned long
get_address(const char *hostname)
{
char *address0;
struct hostent *host;
unsigned long result;
/* Note, this call could block for a while */
host = gethostbyname(hostname);
if (host == NULL) {
fprintf(stderr, "Could not get IP address for %s\n", hostname);
exit(1);
} else {
address0 = host->h_addr_list[0];
result = ((((unsigned long) address0[0] & 0xff) << 24) |
(((unsigned long) address0[1] & 0xff) << 16) |
(((unsigned long) address0[2] & 0xff) << 8) |
(((unsigned long) address0[3] & 0xff)));
}
return result;
}
/* ================================================== */ /* ================================================== */
/* Initialise the socket used to talk to the daemon */ /* Initialise the socket used to talk to the daemon */
static void static void
open_io(const char *hostname, int port) open_io(const char *hostname, int port)
{ {
struct sockaddr_in my_addr; union sockaddr_in46 my_addr;
IPAddr ip;
/* Note, this call could block for a while */
if (!DNS_Name2IPAddress(hostname, &ip, 0)) {
fprintf(stderr, "Could not get IP address for %s\n", hostname);
exit(1);
}
memset(&my_addr, 0, sizeof (my_addr));
memset(&his_addr, 0, sizeof (his_addr));
switch (ip.family) {
case IPADDR_INET4:
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
my_addr.in4.sin_family = AF_INET;
my_addr.in4.sin_port = htons(INADDR_ANY);
my_addr.in4.sin_addr.s_addr = htonl(INADDR_ANY);
his_addr.in4.sin_family = AF_INET;
his_addr.in4.sin_addr.s_addr = htonl(ip.addr.in4);
his_addr.in4.sin_port = htons(port);
break;
#ifdef HAVE_IPV6
case IPADDR_INET6:
sock_fd = socket(AF_INET6, SOCK_DGRAM, 0);
my_addr.in6.sin6_family = AF_INET6;
my_addr.in6.sin6_port = htons(INADDR_ANY);
my_addr.in6.sin6_addr = in6addr_any;
his_addr.in6.sin6_family = AF_INET6;
memcpy(his_addr.in6.sin6_addr.s6_addr, ip.addr.in6,
sizeof (his_addr.in6.sin6_addr.s6_addr));
his_addr.in6.sin6_port = htons(port);
break;
#endif
default:
assert(0);
}
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (sock_fd < 0) { if (sock_fd < 0) {
perror("Can't create socket"); perror("Can't create socket");
exit(1); exit(1);
} }
my_addr.sin_family = AF_INET; if(bind(sock_fd, &my_addr.u, sizeof(my_addr)) < 0) {
my_addr.sin_port = htons(INADDR_ANY);
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(sock_fd, (struct sockaddr *) &my_addr, sizeof(my_addr)) < 0) {
perror("Can't bind socket"); perror("Can't bind socket");
exit(1); exit(1);
} }
/* Build the socket address structure for sending packets */
his_addr.sin_family = AF_INET;
his_addr.sin_addr.s_addr = htonl(get_address(hostname));
/* Eventually the port number needs to be a command line param */
his_addr.sin_port = htons(port);
return; return;
} }
@ -208,34 +218,78 @@ close_io(void)
/* ================================================== */ /* ================================================== */
static int static void
read_mask_address(char *line, unsigned long *mask, unsigned long *address) bits_to_mask(int bits, int family, IPAddr *mask)
{ {
unsigned int ma, mb, mc, md, aa, ab, ac, ad; int i;
int ok = 0;
char *p; mask->family = family;
switch (family) {
case IPADDR_INET4:
if (bits < 0)
bits = 32;
if (bits > 0) {
mask->addr.in4 = -1;
mask->addr.in4 <<= 32 - bits;
} else {
mask->addr.in4 = 0;
}
break;
case IPADDR_INET6:
if (bits > 128 || bits < 0)
bits = 128;
for (i = 0; i < bits / 8; i++)
mask->addr.in6[i] = 0xff;
if (i < 16)
mask->addr.in6[i++] = (0xff << (8 - bits % 8)) & 0xff;
for (; i < 16; i++)
mask->addr.in6[i] = 0x0;
break;
default:
assert(0);
}
}
/* ================================================== */
static int
read_mask_address(char *line, IPAddr *mask, IPAddr *address)
{
unsigned int bits;
char *p, *q;
p = line; p = line;
while (*p && isspace((unsigned char)*p)) p++; while (*p && isspace((unsigned char)*p)) p++;
if (!*p) { if (!*p) {
*mask = *address = 0; mask->family = address->family = IPADDR_UNSPEC;
ok = 1; return 1;
} else { } else {
q = strchr(p, '/');
if (sscanf(line, "%u.%u.%u.%u/%u.%u.%u.%u", if (q) {
&ma, &mb, &mc, &md, *q++ = 0;
&aa, &ab, &ac, &ad) != 8) { if (UTI_StringToIP(p, mask)) {
fprintf(stderr, "Invalid syntax for mask/address\n"); p = q;
ok = 0; while (*q && !isspace((unsigned char)*q)) q++;
*q = 0;
if (UTI_StringToIP(p, address)) {
if (address->family == mask->family)
return 1;
} else if (sscanf(p, "%u", &bits) == 1) {
*address = *mask;
bits_to_mask(bits, address->family, mask);
return 1;
}
}
} else { } else {
*mask = (ma << 24) | (mb << 16) | (mc << 8) | md; if (UTI_StringToIP(p, address)) {
*address = (aa << 24) | (ab << 16) | (ac << 8) | ad; bits_to_mask(-1, address->family, mask);
ok = 1; return 1;
}
} }
} }
return ok; fprintf(stderr, "Invalid syntax for mask/address\n");
return 0;
} }
/* ================================================== */ /* ================================================== */
@ -243,12 +297,12 @@ read_mask_address(char *line, unsigned long *mask, unsigned long *address)
static int static int
process_cmd_offline(CMD_Request *msg, char *line) process_cmd_offline(CMD_Request *msg, char *line)
{ {
unsigned long mask, address; IPAddr mask, address;
int ok; int ok;
if (read_mask_address(line, &mask, &address)) { if (read_mask_address(line, &mask, &address)) {
msg->data.offline.mask = htonl(mask); UTI_IPHostToNetwork(&mask, &msg->data.offline.mask);
msg->data.offline.address = htonl(address); UTI_IPHostToNetwork(&address, &msg->data.offline.address);
msg->command = htons(REQ_OFFLINE); msg->command = htons(REQ_OFFLINE);
ok = 1; ok = 1;
} else { } else {
@ -265,12 +319,12 @@ process_cmd_offline(CMD_Request *msg, char *line)
static int static int
process_cmd_online(CMD_Request *msg, char *line) process_cmd_online(CMD_Request *msg, char *line)
{ {
unsigned long mask, address; IPAddr mask, address;
int ok; int ok;
if (read_mask_address(line, &mask, &address)) { if (read_mask_address(line, &mask, &address)) {
msg->data.online.mask = htonl(mask); UTI_IPHostToNetwork(&mask, &msg->data.online.mask);
msg->data.online.address = htonl(address); UTI_IPHostToNetwork(&address, &msg->data.online.address);
msg->command = htons(REQ_ONLINE); msg->command = htons(REQ_ONLINE);
ok = 1; ok = 1;
} else { } else {
@ -284,7 +338,7 @@ process_cmd_online(CMD_Request *msg, char *line)
/* ================================================== */ /* ================================================== */
static int static int
read_address_integer(char *line, unsigned long *address, int *value) read_address_integer(char *line, IPAddr *address, int *value)
{ {
char hostname[2048]; char hostname[2048];
int ok = 0; int ok = 0;
@ -293,8 +347,7 @@ read_address_integer(char *line, unsigned long *address, int *value)
fprintf(stderr, "Invalid syntax for address value\n"); fprintf(stderr, "Invalid syntax for address value\n");
ok = 0; ok = 0;
} else { } else {
*address = DNS_Name2IPAddress(hostname); if (!DNS_Name2IPAddress(hostname, address, 0)) {
if (*address == DNS_Failed_Address) {
fprintf(stderr, "Could not get address for hostname\n"); fprintf(stderr, "Could not get address for hostname\n");
ok = 0; ok = 0;
} else { } else {
@ -310,7 +363,7 @@ read_address_integer(char *line, unsigned long *address, int *value)
/* ================================================== */ /* ================================================== */
static int static int
read_address_double(char *line, unsigned long *address, double *value) read_address_double(char *line, IPAddr *address, double *value)
{ {
char hostname[2048]; char hostname[2048];
int ok = 0; int ok = 0;
@ -319,8 +372,7 @@ read_address_double(char *line, unsigned long *address, double *value)
fprintf(stderr, "Invalid syntax for address value\n"); fprintf(stderr, "Invalid syntax for address value\n");
ok = 0; ok = 0;
} else { } else {
*address = DNS_Name2IPAddress(hostname); if (!DNS_Name2IPAddress(hostname, address, 0)) {
if (*address == DNS_Failed_Address) {
fprintf(stderr, "Could not get address for hostname\n"); fprintf(stderr, "Could not get address for hostname\n");
ok = 0; ok = 0;
} else { } else {
@ -338,12 +390,12 @@ read_address_double(char *line, unsigned long *address, double *value)
static int static int
process_cmd_minpoll(CMD_Request *msg, char *line) process_cmd_minpoll(CMD_Request *msg, char *line)
{ {
unsigned long address; IPAddr address;
int minpoll; int minpoll;
int ok; int ok;
if (read_address_integer(line, &address, &minpoll)) { if (read_address_integer(line, &address, &minpoll)) {
msg->data.modify_minpoll.address = htonl(address); UTI_IPHostToNetwork(&address, &msg->data.modify_minpoll.address);
msg->data.modify_minpoll.new_minpoll = htonl(minpoll); msg->data.modify_minpoll.new_minpoll = htonl(minpoll);
msg->command = htons(REQ_MODIFY_MINPOLL); msg->command = htons(REQ_MODIFY_MINPOLL);
ok = 1; ok = 1;
@ -360,12 +412,12 @@ process_cmd_minpoll(CMD_Request *msg, char *line)
static int static int
process_cmd_maxpoll(CMD_Request *msg, char *line) process_cmd_maxpoll(CMD_Request *msg, char *line)
{ {
unsigned long address; IPAddr address;
int maxpoll; int maxpoll;
int ok; int ok;
if (read_address_integer(line, &address, &maxpoll)) { if (read_address_integer(line, &address, &maxpoll)) {
msg->data.modify_maxpoll.address = htonl(address); UTI_IPHostToNetwork(&address, &msg->data.modify_maxpoll.address);
msg->data.modify_maxpoll.new_maxpoll = htonl(maxpoll); msg->data.modify_maxpoll.new_maxpoll = htonl(maxpoll);
msg->command = htons(REQ_MODIFY_MAXPOLL); msg->command = htons(REQ_MODIFY_MAXPOLL);
ok = 1; ok = 1;
@ -382,12 +434,12 @@ process_cmd_maxpoll(CMD_Request *msg, char *line)
static int static int
process_cmd_maxdelay(CMD_Request *msg, char *line) process_cmd_maxdelay(CMD_Request *msg, char *line)
{ {
unsigned long address; IPAddr address;
double max_delay; double max_delay;
int ok; int ok;
if (read_address_double(line, &address, &max_delay)) { if (read_address_double(line, &address, &max_delay)) {
msg->data.modify_maxdelay.address = htonl(address); UTI_IPHostToNetwork(&address, &msg->data.modify_maxdelay.address);
msg->data.modify_maxdelay.new_max_delay = REAL2WIRE(max_delay); msg->data.modify_maxdelay.new_max_delay = REAL2WIRE(max_delay);
msg->command = htons(REQ_MODIFY_MAXDELAY); msg->command = htons(REQ_MODIFY_MAXDELAY);
ok = 1; ok = 1;
@ -404,12 +456,12 @@ process_cmd_maxdelay(CMD_Request *msg, char *line)
static int static int
process_cmd_maxdelayratio(CMD_Request *msg, char *line) process_cmd_maxdelayratio(CMD_Request *msg, char *line)
{ {
unsigned long address; IPAddr address;
double max_delay_ratio; double max_delay_ratio;
int ok; int ok;
if (read_address_double(line, &address, &max_delay_ratio)) { if (read_address_double(line, &address, &max_delay_ratio)) {
msg->data.modify_maxdelayratio.address = htonl(address); UTI_IPHostToNetwork(&address, &msg->data.modify_maxdelayratio.address);
msg->data.modify_maxdelayratio.new_max_delay_ratio = REAL2WIRE(max_delay_ratio); msg->data.modify_maxdelayratio.new_max_delay_ratio = REAL2WIRE(max_delay_ratio);
msg->command = htons(REQ_MODIFY_MAXDELAYRATIO); msg->command = htons(REQ_MODIFY_MAXDELAYRATIO);
ok = 1; ok = 1;
@ -478,36 +530,28 @@ process_cmd_cyclelogs(CMD_Request *msg, char *line)
static int static int
process_cmd_burst(CMD_Request *msg, char *line) process_cmd_burst(CMD_Request *msg, char *line)
{ {
int ok;
int n_good_samples, n_total_samples; int n_good_samples, n_total_samples;
unsigned int ma, mb, mc, md, aa, ab, ac, ad;
int n_parsed; int n_parsed;
char s[101];
IPAddr address, mask;
n_parsed = sscanf(line, "%d/%d %u.%u.%u.%u/%u.%u.%u.%u", n_parsed = sscanf(line, "%d/%d %100s", &n_good_samples, &n_total_samples, s);
&n_good_samples,
&n_total_samples,
&ma, &mb, &mc, &md,
&aa, &ab, &ac, &ad);
msg->command = htons(REQ_BURST); msg->command = htons(REQ_BURST);
msg->data.burst.n_good_samples = ntohl(n_good_samples); msg->data.burst.n_good_samples = ntohl(n_good_samples);
msg->data.burst.n_total_samples = ntohl(n_total_samples); msg->data.burst.n_total_samples = ntohl(n_total_samples);
if (n_parsed == 10) { mask.family = address.family = IPADDR_UNSPEC;
msg->data.burst.mask = htonl((ma << 24) | (mb << 16) | (mc << 8) | md);
msg->data.burst.address = htonl((aa << 24) | (ab << 16) | (ac << 8) | ad); if (n_parsed < 2 || (n_parsed == 3 && !read_mask_address(s, &mask, &address))) {
ok = 1;
} else if (n_parsed == 2) {
msg->data.burst.mask = 0;
msg->data.burst.address = 0;
ok = 1;
} else {
ok = 0;
fprintf(stderr, "Invalid syntax for burst command\n"); fprintf(stderr, "Invalid syntax for burst command\n");
return 0;
} }
return ok; UTI_IPHostToNetwork(&mask, &msg->data.burst.mask);
UTI_IPHostToNetwork(&address, &msg->data.burst.address);
return 1;
} }
/* ================================================== */ /* ================================================== */
@ -574,66 +618,81 @@ process_cmd_manual(CMD_Request *msg, const char *line)
static int static int
parse_allow_deny(CMD_Request *msg, char *line) parse_allow_deny(CMD_Request *msg, char *line)
{ {
unsigned long a, b, c, d, n, ip; unsigned long a, b, c, d, n;
IPAddr ip;
char *p, *q; char *p, *q;
p = line; p = line;
while (*p && isspace((unsigned char)*p)) p++; while (*p && isspace((unsigned char)*p)) p++;
if (!*p) { if (!*p) {
/* blank line - applies to all addresses */ /* blank line - applies to all addresses */
msg->data.allow_deny.ip = htonl(0); ip.family = IPADDR_UNSPEC;
UTI_IPHostToNetwork(&ip, &msg->data.allow_deny.ip);
msg->data.allow_deny.subnet_bits = htonl(0); msg->data.allow_deny.subnet_bits = htonl(0);
} else { } else {
char *slashpos; char *slashpos;
slashpos = strchr(p, '/'); slashpos = strchr(p, '/');
if (slashpos) *slashpos = 0; if (slashpos) *slashpos = 0;
n = sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d); n = 0;
if (!UTI_StringToIP(p, &ip) &&
(n = sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d)) == 0) {
if (n == 0) {
/* Try to parse as the name of a machine */ /* Try to parse as the name of a machine */
q = p; q = p;
while (*q) { while (*q) {
if (*q == '\n') *q = 0; if (*q == '\n') *q = 0;
q++; q++;
} }
ip = DNS_Name2IPAddress(p); if (!DNS_Name2IPAddress(p, &ip, 0)) {
if (ip == DNS_Failed_Address) {
fprintf(stderr, "Could not read address\n"); fprintf(stderr, "Could not read address\n");
return 0; return 0;
} else { } else {
msg->data.allow_deny.ip = htonl(ip); UTI_IPHostToNetwork(&ip, &msg->data.allow_deny.ip);
msg->data.allow_deny.subnet_bits = htonl(32); if (ip.family == IPADDR_INET6)
msg->data.allow_deny.subnet_bits = htonl(128);
else
msg->data.allow_deny.subnet_bits = htonl(32);
} }
} else { } else {
a &= 0xff; if (n == 0) {
b &= 0xff; if (ip.family == IPADDR_INET6)
c &= 0xff; msg->data.allow_deny.subnet_bits = htonl(128);
d &= 0xff; else
switch (n) {
case 1:
msg->data.allow_deny.ip = htonl((a<<24));
msg->data.allow_deny.subnet_bits = htonl(8);
break;
case 2:
msg->data.allow_deny.ip = htonl((a<<24) | (b<<16));
msg->data.allow_deny.subnet_bits = htonl(16);
break;
case 3:
msg->data.allow_deny.ip = htonl((a<<24) | (b<<16) | (c<<8));
msg->data.allow_deny.subnet_bits = htonl(24);
break;
case 4:
msg->data.allow_deny.ip = htonl((a<<24) | (b<<16) | (c<<8) | d);
msg->data.allow_deny.subnet_bits = htonl(32); msg->data.allow_deny.subnet_bits = htonl(32);
break; } else {
default: ip.family = IPADDR_INET4;
assert(0);
a &= 0xff;
b &= 0xff;
c &= 0xff;
d &= 0xff;
switch (n) {
case 1:
ip.addr.in4 = htonl((a<<24));
msg->data.allow_deny.subnet_bits = htonl(8);
break;
case 2:
ip.addr.in4 = htonl((a<<24) | (b<<16));
msg->data.allow_deny.subnet_bits = htonl(16);
break;
case 3:
ip.addr.in4 = htonl((a<<24) | (b<<16) | (c<<8));
msg->data.allow_deny.subnet_bits = htonl(24);
break;
case 4:
ip.addr.in4 = htonl((a<<24) | (b<<16) | (c<<8) | d);
msg->data.allow_deny.subnet_bits = htonl(32);
break;
default:
assert(0);
}
} }
UTI_IPHostToNetwork(&ip, &msg->data.allow_deny.ip);
if (slashpos) { if (slashpos) {
int specified_subnet_bits, n; int specified_subnet_bits, n;
n = sscanf(slashpos+1, "%d", &specified_subnet_bits); n = sscanf(slashpos+1, "%d", &specified_subnet_bits);
@ -739,9 +798,10 @@ process_cmd_cmddenyall(CMD_Request *msg, char *line)
/* ================================================== */ /* ================================================== */
static int static int
accheck_getaddr(char *line, unsigned long *addr) accheck_getaddr(char *line, IPAddr *addr)
{ {
unsigned long a, b, c, d, ip; unsigned long a, b, c, d;
IPAddr ip;
char *p, *q; char *p, *q;
p = line; p = line;
while (*p && isspace(*p)) p++; while (*p && isspace(*p)) p++;
@ -749,7 +809,8 @@ accheck_getaddr(char *line, unsigned long *addr)
return 0; return 0;
} else { } else {
if (sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d) == 4) { if (sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d) == 4) {
*addr = (a<<24) | (b<<16) | (c<<8) | d; addr->family = IPADDR_INET4;
addr->addr.in4 = (a<<24) | (b<<16) | (c<<8) | d;
return 1; return 1;
} else { } else {
q = p; q = p;
@ -757,8 +818,7 @@ accheck_getaddr(char *line, unsigned long *addr)
if (*q == '\n') *q = 0; if (*q == '\n') *q = 0;
q++; q++;
} }
ip = DNS_Name2IPAddress(p); if (!DNS_Name2IPAddress(p, &ip, 0)) {
if (ip == DNS_Failed_Address) {
return 0; return 0;
} else { } else {
*addr = ip; *addr = ip;
@ -773,10 +833,10 @@ accheck_getaddr(char *line, unsigned long *addr)
static int static int
process_cmd_accheck(CMD_Request *msg, char *line) process_cmd_accheck(CMD_Request *msg, char *line)
{ {
unsigned long ip; IPAddr ip;
msg->command = htons(REQ_ACCHECK); msg->command = htons(REQ_ACCHECK);
if (accheck_getaddr(line, &ip)) { if (accheck_getaddr(line, &ip)) {
msg->data.ac_check.ip = htonl(ip); UTI_IPHostToNetwork(&ip, &msg->data.ac_check.ip);
return 1; return 1;
} else { } else {
fprintf(stderr, "Could not read address\n"); fprintf(stderr, "Could not read address\n");
@ -789,10 +849,10 @@ process_cmd_accheck(CMD_Request *msg, char *line)
static int static int
process_cmd_cmdaccheck(CMD_Request *msg, char *line) process_cmd_cmdaccheck(CMD_Request *msg, char *line)
{ {
unsigned long ip; IPAddr ip;
msg->command = htons(REQ_CMDACCHECK); msg->command = htons(REQ_CMDACCHECK);
if (accheck_getaddr(line, &ip)) { if (accheck_getaddr(line, &ip)) {
msg->data.ac_check.ip = htonl(ip); UTI_IPHostToNetwork(&ip, &msg->data.ac_check.ip);
return 1; return 1;
} else { } else {
fprintf(stderr, "Could not read address\n"); fprintf(stderr, "Could not read address\n");
@ -866,7 +926,7 @@ process_cmd_add_server_or_peer(CMD_Request *msg, char *line)
switch (status) { switch (status) {
case CPS_Success: case CPS_Success:
msg->data.ntp_source.port = htonl((unsigned long) data.port); msg->data.ntp_source.port = htonl((unsigned long) data.port);
msg->data.ntp_source.ip_addr = htonl(data.ip_addr); UTI_IPHostToNetwork(&data.ip_addr, &msg->data.ntp_source.ip_addr);
msg->data.ntp_source.minpoll = htonl(data.params.minpoll); msg->data.ntp_source.minpoll = htonl(data.params.minpoll);
msg->data.ntp_source.maxpoll = htonl(data.params.maxpoll); msg->data.ntp_source.maxpoll = htonl(data.params.maxpoll);
msg->data.ntp_source.presend_minpoll = htonl(data.params.presend_minpoll); msg->data.ntp_source.presend_minpoll = htonl(data.params.presend_minpoll);
@ -935,7 +995,7 @@ process_cmd_delete(CMD_Request *msg, char *line)
{ {
char hostname[2048]; char hostname[2048];
int ok = 0; int ok = 0;
unsigned long address = 0UL; IPAddr address;
msg->command = htons(REQ_DEL_SOURCE); msg->command = htons(REQ_DEL_SOURCE);
@ -943,8 +1003,7 @@ process_cmd_delete(CMD_Request *msg, char *line)
fprintf(stderr, "Invalid syntax for address\n"); fprintf(stderr, "Invalid syntax for address\n");
ok = 0; ok = 0;
} else { } else {
address = DNS_Name2IPAddress(hostname); if (!DNS_Name2IPAddress(hostname, &address, 0)) {
if (address == DNS_Failed_Address) {
fprintf(stderr, "Could not get address for hostname\n"); fprintf(stderr, "Could not get address for hostname\n");
ok = 0; ok = 0;
} else { } else {
@ -952,7 +1011,7 @@ process_cmd_delete(CMD_Request *msg, char *line)
} }
} }
msg->data.del_source.ip_addr = htonl(address); UTI_IPHostToNetwork(&address, &msg->data.del_source.ip_addr);
return ok; return ok;
@ -1121,7 +1180,7 @@ submit_request(CMD_Request *request, CMD_Reply *reply, int *reply_auth_ok)
{ {
unsigned long tx_sequence; unsigned long tx_sequence;
socklen_t where_from_len; socklen_t where_from_len;
struct sockaddr_in where_from; union sockaddr_in46 where_from;
int bad_length, bad_sender, bad_sequence, bad_header; int bad_length, bad_sender, bad_sequence, bad_header;
int select_status; int select_status;
int recvfrom_status; int recvfrom_status;
@ -1168,7 +1227,7 @@ submit_request(CMD_Request *request, CMD_Reply *reply, int *reply_auth_ok)
#endif #endif
if (sendto(sock_fd, (void *) request, command_length, 0, if (sendto(sock_fd, (void *) request, command_length, 0,
(struct sockaddr *) &his_addr, sizeof(his_addr)) < 0) { &his_addr.u, sizeof(his_addr)) < 0) {
#if 0 #if 0
@ -1210,7 +1269,7 @@ submit_request(CMD_Request *request, CMD_Reply *reply, int *reply_auth_ok)
where_from_len = sizeof(where_from); where_from_len = sizeof(where_from);
recvfrom_status = recvfrom(sock_fd, (void *) reply, sizeof(CMD_Reply), 0, recvfrom_status = recvfrom(sock_fd, (void *) reply, sizeof(CMD_Reply), 0,
(struct sockaddr *) &where_from, &where_from_len); &where_from.u, &where_from_len);
#if 0 #if 0
@ -1231,8 +1290,17 @@ submit_request(CMD_Request *request, CMD_Reply *reply, int *reply_auth_ok)
expected_length = PKL_ReplyLength(reply); expected_length = PKL_ReplyLength(reply);
bad_length = (read_length != expected_length); bad_length = (read_length != expected_length);
bad_sender = ((where_from.sin_addr.s_addr != his_addr.sin_addr.s_addr) || bad_sender = (where_from.u.sa_family != his_addr.u.sa_family ||
(where_from.sin_port != his_addr.sin_port)); (where_from.u.sa_family == AF_INET &&
(where_from.in4.sin_addr.s_addr != his_addr.in4.sin_addr.s_addr ||
where_from.in4.sin_port != his_addr.in4.sin_port)) ||
#ifdef HAVE_IPV6
(where_from.u.sa_family == AF_INET6 &&
(memcmp(where_from.in6.sin6_addr.s6_addr, his_addr.in6.sin6_addr.s6_addr,
sizeof (where_from.in6.sin6_addr.s6_addr)) != 0 ||
where_from.in6.sin6_port != his_addr.in6.sin6_port)) ||
#endif
0);
if (!bad_length) { if (!bad_length) {
bad_sequence = (ntohl(reply->sequence) != tx_sequence); bad_sequence = (ntohl(reply->sequence) != tx_sequence);
@ -1382,13 +1450,12 @@ process_cmd_sources(char *line)
int verbose = 0; int verbose = 0;
int32_t orig_latest_meas, latest_meas, est_offset; int32_t orig_latest_meas, latest_meas, est_offset;
uint32_t ip_addr; IPAddr ip_addr;
uint32_t latest_meas_err, est_offset_err; uint32_t latest_meas_err, est_offset_err;
uint32_t latest_meas_ago; uint32_t latest_meas_ago;
uint16_t poll, stratum; uint16_t poll, stratum;
uint16_t state, mode; uint16_t state, mode;
double resid_freq, resid_skew; double resid_freq, resid_skew;
const char *dns_lookup;
char hostname_buf[32]; char hostname_buf[32];
uint16_t status; uint16_t status;
@ -1439,7 +1506,7 @@ process_cmd_sources(char *line)
if (submit_ok) { if (submit_ok) {
if (ntohs(reply.status) == STT_SUCCESS) { if (ntohs(reply.status) == STT_SUCCESS) {
ip_addr = ntohl(reply.data.source_data.ip_addr); UTI_IPNetworkToHost(&reply.data.source_data.ip_addr, &ip_addr);
poll = ntohs(reply.data.source_data.poll); poll = ntohs(reply.data.source_data.poll);
stratum = ntohs(reply.data.source_data.stratum); stratum = ntohs(reply.data.source_data.stratum);
state = ntohs(reply.data.source_data.state); state = ntohs(reply.data.source_data.state);
@ -1453,14 +1520,13 @@ process_cmd_sources(char *line)
resid_freq = (double) ((long) ntohl(reply.data.source_data.resid_freq)) * 1.0e-3; resid_freq = (double) ((long) ntohl(reply.data.source_data.resid_freq)) * 1.0e-3;
resid_skew = (double) (ntohl(reply.data.source_data.resid_skew)) * 1.0e-3; resid_skew = (double) (ntohl(reply.data.source_data.resid_skew)) * 1.0e-3;
hostname_buf[25] = 0;
if (mode == RPY_SD_MD_REF) { if (mode == RPY_SD_MD_REF) {
snprintf(hostname_buf, sizeof(hostname_buf), "%s", UTI_RefidToString(ip_addr)); snprintf(hostname_buf, sizeof(hostname_buf), "%s", UTI_RefidToString(ip_addr.addr.in4));
} else if (no_dns) { } else if (no_dns) {
snprintf(hostname_buf, sizeof(hostname_buf), "%s", UTI_IPToDottedQuad(ip_addr)); snprintf(hostname_buf, sizeof(hostname_buf), "%s", UTI_IPToString(&ip_addr));
} else { } else {
dns_lookup = DNS_IPAddress2Name(ip_addr); DNS_IPAddress2Name(&ip_addr, hostname_buf, sizeof(hostname_buf));
strncpy(hostname_buf, dns_lookup, 25); hostname_buf[25] = 0;
} }
switch (mode) { switch (mode) {
@ -1515,12 +1581,11 @@ process_cmd_sourcestats(char *line)
int n_sources, i; int n_sources, i;
int verbose = 0; int verbose = 0;
const char *dns_lookup;
char hostname_buf[32]; char hostname_buf[32];
unsigned long n_samples, n_runs, span_seconds; unsigned long n_samples, n_runs, span_seconds;
double resid_freq_ppm, skew_ppm; double resid_freq_ppm, skew_ppm;
unsigned long sd_us; unsigned long sd_us;
unsigned long ip_addr; IPAddr ip_addr;
unsigned short status; unsigned short status;
verbose = check_for_verbose_flag(line); verbose = check_for_verbose_flag(line);
@ -1569,7 +1634,7 @@ process_cmd_sourcestats(char *line)
if (submit_ok) { if (submit_ok) {
if (ntohs(reply.status) == STT_SUCCESS) { if (ntohs(reply.status) == STT_SUCCESS) {
ip_addr = ntohl(reply.data.sourcestats.ip_addr); UTI_IPNetworkToHost(&reply.data.sourcestats.ip_addr, &ip_addr);
n_samples = ntohl(reply.data.sourcestats.n_samples); n_samples = ntohl(reply.data.sourcestats.n_samples);
n_runs = ntohl(reply.data.sourcestats.n_runs); n_runs = ntohl(reply.data.sourcestats.n_runs);
span_seconds = ntohl(reply.data.sourcestats.span_seconds); span_seconds = ntohl(reply.data.sourcestats.span_seconds);
@ -1577,12 +1642,11 @@ process_cmd_sourcestats(char *line)
skew_ppm = WIRE2REAL(reply.data.sourcestats.skew_ppm); skew_ppm = WIRE2REAL(reply.data.sourcestats.skew_ppm);
sd_us = ntohl(reply.data.sourcestats.sd_us); sd_us = ntohl(reply.data.sourcestats.sd_us);
hostname_buf[25] = 0;
if (no_dns) { if (no_dns) {
snprintf(hostname_buf, sizeof(hostname_buf), "%s", UTI_IPToDottedQuad(ip_addr)); snprintf(hostname_buf, sizeof(hostname_buf), "%s", UTI_IPToString(&ip_addr));
} else { } else {
dns_lookup = DNS_IPAddress2Name(ip_addr); DNS_IPAddress2Name(&ip_addr, hostname_buf, sizeof(hostname_buf));
strncpy(hostname_buf, dns_lookup, 25); hostname_buf[25] = 0;
} }
printf("%-25s %2lu %2lu ", hostname_buf, n_samples, n_runs); printf("%-25s %2lu %2lu ", hostname_buf, n_samples, n_runs);
@ -1644,9 +1708,10 @@ process_cmd_tracking(char *line)
b = (ref_id >> 16) & 0xff; b = (ref_id >> 16) & 0xff;
c = (ref_id >> 8) & 0xff; c = (ref_id >> 8) & 0xff;
d = (ref_id) & 0xff; d = (ref_id) & 0xff;
printf("Reference ID : %lu.%lu.%lu.%lu (%s)\n", printf("Reference ID : %lu.%lu.%lu.%lu (%s)\n",
a, b, c, d, a, b, c, d, "");
(no_dns) ? UTI_IPToDottedQuad(ref_id) : DNS_IPAddress2Name(ref_id)); //* TODO (no_dns) ? UTI_IPToDottedQuad(ref_id) : DNS_IPAddress2Name(ref_id)); */
printf("Stratum : %lu\n", (unsigned long) ntohl(reply.data.tracking.stratum)); printf("Stratum : %lu\n", (unsigned long) ntohl(reply.data.tracking.stratum));
ref_time.tv_sec = ntohl(reply.data.tracking.ref_time_s); ref_time.tv_sec = ntohl(reply.data.tracking.ref_time_s);
ref_time.tv_usec = ntohl(reply.data.tracking.ref_time_us); ref_time.tv_usec = ntohl(reply.data.tracking.ref_time_us);
@ -1766,7 +1831,6 @@ process_cmd_clients(char *line)
unsigned long last_ntp_hit_ago; unsigned long last_ntp_hit_ago;
unsigned long last_cmd_hit_ago; unsigned long last_cmd_hit_ago;
char hostname_buf[32]; char hostname_buf[32];
const char *dns_lookup;
int n_replies; int n_replies;
@ -1922,9 +1986,8 @@ process_cmd_clients(char *line)
snprintf(hostname_buf, sizeof(hostname_buf), snprintf(hostname_buf, sizeof(hostname_buf),
"%s", UTI_IPToDottedQuad(ip)); "%s", UTI_IPToDottedQuad(ip));
} else { } else {
dns_lookup = DNS_IPAddress2Name(ip); DNS_IPAddress2Name(ip, hostname_buf, sizeof(hostname_buf));
hostname_buf[25] = 0; hostname_buf[25] = 0;
strncpy(hostname_buf, dns_lookup, 25);
} }
printf("%-25s %6d %6d %6d %6d %6d ", printf("%-25s %6d %6d %6d %6d %6d ",
hostname_buf, hostname_buf,
@ -1988,7 +2051,7 @@ process_cmd_clients(char *line)
int status; int status;
unsigned long next_index; unsigned long next_index;
int j; int j;
unsigned long ip; IPAddr ip;
unsigned long client_hits; unsigned long client_hits;
unsigned long peer_hits; unsigned long peer_hits;
unsigned long cmd_hits_auth; unsigned long cmd_hits_auth;
@ -1997,7 +2060,6 @@ process_cmd_clients(char *line)
unsigned long last_ntp_hit_ago; unsigned long last_ntp_hit_ago;
unsigned long last_cmd_hit_ago; unsigned long last_cmd_hit_ago;
char hostname_buf[32]; char hostname_buf[32];
const char *dns_lookup;
int n_replies; int n_replies;
int n_indices_in_table; int n_indices_in_table;
@ -2025,9 +2087,9 @@ process_cmd_clients(char *line)
goto finished; goto finished;
} }
for (j=0; j<n_replies; j++) { for (j=0; j<n_replies; j++) {
ip = ntohl(reply.data.client_accesses_by_index.clients[j].ip); UTI_IPNetworkToHost(&reply.data.client_accesses_by_index.clients[j].ip, &ip);
if (ip != 0UL) { if (ip.family != IPADDR_UNSPEC) {
/* ip == 0 implies that the node could not be found in /* UNSPEC implies that the node could not be found in
the daemon's tables; we shouldn't ever generate this the daemon's tables; we shouldn't ever generate this
case, but ignore it if we do. (In future there might case, but ignore it if we do. (In future there might
be a protocol to reset the client logging; if another be a protocol to reset the client logging; if another
@ -2045,11 +2107,10 @@ process_cmd_clients(char *line)
if (no_dns) { if (no_dns) {
snprintf(hostname_buf, sizeof(hostname_buf), snprintf(hostname_buf, sizeof(hostname_buf),
"%s", UTI_IPToDottedQuad(ip)); "%s", UTI_IPToString(&ip));
} else { } else {
dns_lookup = DNS_IPAddress2Name(ip); DNS_IPAddress2Name(&ip, hostname_buf, sizeof(hostname_buf));
hostname_buf[25] = 0; hostname_buf[25] = 0;
strncpy(hostname_buf, dns_lookup, 25);
} }
printf("%-25s %6ld %6ld %6ld %6ld %6ld ", printf("%-25s %6ld %6ld %6ld %6ld %6ld ",
hostname_buf, hostname_buf,
@ -2475,6 +2536,9 @@ process_line(char *line)
case STT_BADRTCFILE: case STT_BADRTCFILE:
printf("514 Can't write RTC parameters"); printf("514 Can't write RTC parameters");
break; break;
case STT_INVALIDAF:
printf("515 Invalid address family");
break;
} }
if (reply_auth_ok) { if (reply_auth_ok) {

View file

@ -53,7 +53,7 @@
#define TABLE_SIZE (1UL<<NBITS) #define TABLE_SIZE (1UL<<NBITS)
typedef struct _Node { typedef struct _Node {
unsigned long ip_addr; IPAddr ip_addr;
unsigned long client_hits; unsigned long client_hits;
unsigned long peer_hits; unsigned long peer_hits;
unsigned long cmd_hits_bad; unsigned long cmd_hits_bad;
@ -69,8 +69,10 @@ typedef struct _Subnet {
/* ================================================== */ /* ================================================== */
/* Table for the class A subnet */ /* Table for the IPv4 class A subnet */
static Subnet top_subnet; static Subnet top_subnet4;
/* Table for IPv6 */
static Subnet top_subnet6;
/* Table containing pointers directly to all nodes that have been /* Table containing pointers directly to all nodes that have been
allocated. */ allocated. */
@ -89,6 +91,34 @@ static int active = 0;
/* ================================================== */ /* ================================================== */
static void
split_ip6(IPAddr *ip, uint32_t *dst)
{
int i;
for (i = 0; i < 4; i++)
dst[i] = ip->addr.in6[i * 4 + 0] << 24 |
ip->addr.in6[i * 4 + 1] << 16 |
ip->addr.in6[i * 4 + 2] << 8 |
ip->addr.in6[i * 4 + 3];
}
/* ================================================== */
inline static uint32_t
get_subnet(uint32_t *addr, unsigned int where)
{
int off;
off = where / 32;
where %= 32;
return (addr[off] >> (32 - NBITS - where)) & ((1UL << NBITS) - 1);
}
/* ================================================== */
static void static void
clear_subnet(Subnet *subnet) clear_subnet(Subnet *subnet)
{ {
@ -118,7 +148,8 @@ clear_node(Node *node)
void void
CLG_Initialise(void) CLG_Initialise(void)
{ {
clear_subnet(&top_subnet); clear_subnet(&top_subnet4);
clear_subnet(&top_subnet6);
if (CNF_GetNoClientLog()) { if (CNF_GetNoClientLog()) {
active = 0; active = 0;
} else { } else {
@ -178,27 +209,18 @@ create_node(Subnet *parent_subnet, int the_entry)
expanding subnet tables and node entries as we go if necessary. */ expanding subnet tables and node entries as we go if necessary. */
static void * static void *
find_subnet(Subnet *subnet, CLG_IP_Addr addr, int bits_left) find_subnet(Subnet *subnet, uint32_t *addr, int addr_len, int bits_consumed)
{ {
unsigned long this_subnet, new_subnet, mask, shift; uint32_t this_subnet;
unsigned long new_bits_left;
shift = 32 - NBITS;
mask = (1UL<<shift) - 1;
this_subnet = addr >> shift;
new_subnet = (addr & mask) << NBITS;
new_bits_left = bits_left - NBITS;
#if 0 this_subnet = get_subnet(addr, bits_consumed);
fprintf(stderr, "fs addr=%08lx bl=%d ma=%08lx this=%08lx newsn=%08lx nbl=%d\n", bits_consumed += NBITS;
addr, bits_left, mask, this_subnet, new_subnet, new_bits_left);
#endif
if (new_bits_left > 0) { if (bits_consumed < 32 * addr_len) {
if (!subnet->entry[this_subnet]) { if (!subnet->entry[this_subnet]) {
create_subnet(subnet, this_subnet); create_subnet(subnet, this_subnet);
} }
return find_subnet((Subnet *) subnet->entry[this_subnet], new_subnet, new_bits_left); return find_subnet((Subnet *) subnet->entry[this_subnet], addr, addr_len, bits_consumed);
} else { } else {
if (!subnet->entry[this_subnet]) { if (!subnet->entry[this_subnet]) {
create_node(subnet, this_subnet); create_node(subnet, this_subnet);
@ -213,30 +235,21 @@ find_subnet(Subnet *subnet, CLG_IP_Addr addr, int bits_left)
one of the parents does not exist - never open a node out */ one of the parents does not exist - never open a node out */
static void * static void *
find_subnet_dont_open(Subnet *subnet, CLG_IP_Addr addr, int bits_left) find_subnet_dont_open(Subnet *subnet, uint32_t *addr, int addr_len, int bits_consumed)
{ {
unsigned long this_subnet, new_subnet, mask, shift; uint32_t this_subnet;
unsigned long new_bits_left;
if (bits_left == 0) { if (bits_consumed >= 32 * addr_len) {
return subnet; return subnet;
} else { } else {
shift = 32 - NBITS; this_subnet = get_subnet(addr, bits_consumed);
mask = (1UL<<shift) - 1; bits_consumed += NBITS;
this_subnet = addr >> shift;
new_subnet = (addr & mask) << NBITS;
new_bits_left = bits_left - NBITS;
#if 0
fprintf(stderr, "fsdo addr=%08lx bl=%d this=%08lx newsn=%08lx nbl=%d\n",
addr, bits_left, this_subnet, new_subnet, new_bits_left);
#endif
if (!subnet->entry[this_subnet]) { if (!subnet->entry[this_subnet]) {
return NULL; return NULL;
} else { } else {
return find_subnet_dont_open((Subnet *) subnet->entry[this_subnet], new_subnet, new_bits_left); return find_subnet_dont_open((Subnet *) subnet->entry[this_subnet], addr, addr_len, bits_consumed);
} }
} }
} }
@ -244,12 +257,25 @@ find_subnet_dont_open(Subnet *subnet, CLG_IP_Addr addr, int bits_left)
/* ================================================== */ /* ================================================== */
void void
CLG_LogNTPClientAccess (CLG_IP_Addr client, time_t now) CLG_LogNTPClientAccess (IPAddr *client, time_t now)
{ {
uint32_t ip6[4];
Node *node; Node *node;
if (active) { if (active) {
node = (Node *) find_subnet(&top_subnet, client, 32); switch (client->family) {
node->ip_addr = client; case IPADDR_INET4:
node = (Node *) find_subnet(&top_subnet4, &client->addr.in4, 1, 0);
break;
case IPADDR_INET6:
split_ip6(client, ip6);
node = (Node *) find_subnet(&top_subnet6, ip6, 4, 0);
break;
default:
assert(0);
}
node->ip_addr = *client;
++node->client_hits; ++node->client_hits;
node->last_ntp_hit = now; node->last_ntp_hit = now;
} }
@ -258,12 +284,25 @@ CLG_LogNTPClientAccess (CLG_IP_Addr client, time_t now)
/* ================================================== */ /* ================================================== */
void void
CLG_LogNTPPeerAccess(CLG_IP_Addr client, time_t now) CLG_LogNTPPeerAccess(IPAddr *client, time_t now)
{ {
uint32_t ip6[4];
Node *node; Node *node;
if (active) { if (active) {
node = (Node *) find_subnet(&top_subnet, client, 32); switch (client->family) {
node->ip_addr = client; case IPADDR_INET4:
node = (Node *) find_subnet(&top_subnet4, &client->addr.in4, 1, 0);
break;
case IPADDR_INET6:
split_ip6(client, ip6);
node = (Node *) find_subnet(&top_subnet6, ip6, 4, 0);
break;
default:
assert(0);
}
node->ip_addr = *client;
++node->peer_hits; ++node->peer_hits;
node->last_ntp_hit = now; node->last_ntp_hit = now;
} }
@ -272,12 +311,25 @@ CLG_LogNTPPeerAccess(CLG_IP_Addr client, time_t now)
/* ================================================== */ /* ================================================== */
void void
CLG_LogCommandAccess(CLG_IP_Addr client, CLG_Command_Type type, time_t now) CLG_LogCommandAccess(IPAddr *client, CLG_Command_Type type, time_t now)
{ {
uint32_t ip6[4];
Node *node; Node *node;
if (active) { if (active) {
node = (Node *) find_subnet(&top_subnet, client, 32); switch (client->family) {
node->ip_addr = client; case IPADDR_INET4:
node = (Node *) find_subnet(&top_subnet4, &client->addr.in4, 1, 0);
break;
case IPADDR_INET6:
split_ip6(client, ip6);
node = (Node *) find_subnet(&top_subnet6, ip6, 4, 0);
break;
default:
assert(0);
}
node->ip_addr = *client;
node->last_cmd_hit = now; node->last_cmd_hit = now;
switch (type) { switch (type) {
case CLG_CMD_AUTH: case CLG_CMD_AUTH:
@ -299,16 +351,32 @@ CLG_LogCommandAccess(CLG_IP_Addr client, CLG_Command_Type type, time_t now)
/* ================================================== */ /* ================================================== */
CLG_Status CLG_Status
CLG_GetSubnetBitmap(CLG_IP_Addr subnet, int bits, CLG_Bitmap result) CLG_GetSubnetBitmap(IPAddr *subnet, int bits, CLG_Bitmap result)
{ {
Subnet *s; Subnet *s;
uint32_t ip6[4];
unsigned long i; unsigned long i;
unsigned long word, bit, mask; unsigned long word, bit, mask;
if ((bits == 0) || (bits == 8) || (bits == 16) || (bits == 24)) { if (bits >= 0 && bits % 8 == 0) {
memset (result, 0, TABLE_SIZE/8); memset (result, 0, TABLE_SIZE/8);
if (active) { if (active) {
s = find_subnet_dont_open(&top_subnet, subnet, bits); switch (subnet->family) {
case IPADDR_INET4:
if (bits >= 32)
return CLG_BADSUBNET;
s = find_subnet_dont_open(&top_subnet4, &subnet->addr.in4, 1, 32 - bits);
break;
case IPADDR_INET6:
if (bits >= 128)
return CLG_BADSUBNET;
split_ip6(subnet, ip6);
s = find_subnet_dont_open(&top_subnet6, ip6, 4, 128 - bits);
break;
default:
return CLG_BADSUBNET;
}
if (s) { if (s) {
for (i=0; i<256; i++) { for (i=0; i<256; i++) {
if (s->entry[i]) { if (s->entry[i]) {
@ -333,15 +401,26 @@ CLG_GetSubnetBitmap(CLG_IP_Addr subnet, int bits, CLG_Bitmap result)
/* ================================================== */ /* ================================================== */
CLG_Status CLG_Status
CLG_GetClientAccessReportByIP(unsigned long ip, RPT_ClientAccess_Report *report, time_t now) CLG_GetClientAccessReportByIP(IPAddr *ip, RPT_ClientAccess_Report *report, time_t now)
{ {
uint32_t ip6[4];
Node *node; Node *node;
if (!active) { if (!active) {
return CLG_INACTIVE; return CLG_INACTIVE;
} else { } else {
node = (Node *) find_subnet_dont_open(&top_subnet, ip, 32); switch (ip->family) {
case IPADDR_INET4:
node = (Node *) find_subnet_dont_open(&top_subnet4, &ip->addr.in4, 1, 0);
break;
case IPADDR_INET6:
split_ip6(ip, ip6);
node = (Node *) find_subnet_dont_open(&top_subnet6, ip6, 4, 0);
break;
default:
return CLG_EMPTYSUBNET;
}
if (!node) { if (!node) {
return CLG_EMPTYSUBNET; return CLG_EMPTYSUBNET;
} else { } else {

View file

@ -35,15 +35,13 @@
#include "sysincl.h" #include "sysincl.h"
#include "reports.h" #include "reports.h"
typedef unsigned long CLG_IP_Addr;
/* Enough to hold flags for 256 hosts in a class C */ /* Enough to hold flags for 256 hosts in a class C */
typedef uint32_t CLG_Bitmap[8]; typedef uint32_t CLG_Bitmap[8];
extern void CLG_Initialise(void); extern void CLG_Initialise(void);
extern void CLG_Finalise(void); extern void CLG_Finalise(void);
extern void CLG_LogNTPClientAccess(CLG_IP_Addr client, time_t now); extern void CLG_LogNTPClientAccess(IPAddr *client, time_t now);
extern void CLG_LogNTPPeerAccess(CLG_IP_Addr client, time_t now); extern void CLG_LogNTPPeerAccess(IPAddr *client, time_t now);
/* When logging command packets, there are several subtypes */ /* When logging command packets, there are several subtypes */
@ -53,7 +51,7 @@ typedef enum {
CLG_CMD_BAD_PKT /* bad version or packet length */ CLG_CMD_BAD_PKT /* bad version or packet length */
} CLG_Command_Type; } CLG_Command_Type;
extern void CLG_LogCommandAccess(CLG_IP_Addr client, CLG_Command_Type type, time_t now); extern void CLG_LogCommandAccess(IPAddr *client, CLG_Command_Type type, time_t now);
/* And some reporting functions, for use by chronyc. */ /* And some reporting functions, for use by chronyc. */
/* TBD */ /* TBD */
@ -70,10 +68,10 @@ typedef enum {
known. For bits=24, flag which hosts in that subnet are known. known. For bits=24, flag which hosts in that subnet are known.
Other values, return 0 (failed) */ Other values, return 0 (failed) */
extern CLG_Status CLG_GetSubnetBitmap(CLG_IP_Addr subnet, int bits, CLG_Bitmap result); extern CLG_Status CLG_GetSubnetBitmap(IPAddr *subnet, int bits, CLG_Bitmap result);
extern CLG_Status extern CLG_Status
CLG_GetClientAccessReportByIP(unsigned long ip, RPT_ClientAccess_Report *report, time_t now); CLG_GetClientAccessReportByIP(IPAddr *ip, RPT_ClientAccess_Report *report, time_t now);
CLG_Status CLG_Status
CLG_GetClientAccessReportByIndex(int index, RPT_ClientAccessByIndex_Report *report, CLG_GetClientAccessReportByIndex(int index, RPT_ClientAccessByIndex_Report *report,
@ -83,7 +81,7 @@ CLG_GetClientAccessReportByIndex(int index, RPT_ClientAccessByIndex_Report *repo
that has accessed us since 'since'. */ that has accessed us since 'since'. */
extern void CLG_IterateNTPClients extern void CLG_IterateNTPClients
(void (*fn)(CLG_IP_Addr client, void *arb), (void (*fn)(IPAddr *client, void *arb),
void *arb, void *arb,
time_t since); time_t since);

408
cmdmon.c
View file

@ -54,8 +54,19 @@
/* ================================================== */ /* ================================================== */
/* File descriptor for command and monitoring socket */ union sockaddr_in46 {
static int sock_fd; struct sockaddr_in in4;
#ifdef HAVE_IPV6
struct sockaddr_in6 in6;
#endif
struct sockaddr u;
};
/* File descriptors for command and monitoring sockets */
static int sock_fd4;
#ifdef HAVE_IPV6
static int sock_fd6;
#endif
/* Flag indicating whether this module has been initialised or not */ /* Flag indicating whether this module has been initialised or not */
static int initialised = 0; static int initialised = 0;
@ -157,17 +168,93 @@ static ADF_AuthTable access_auth_table;
/* ================================================== */ /* ================================================== */
/* Forward prototypes */ /* Forward prototypes */
static int prepare_socket(int family);
static void read_from_cmd_socket(void *anything); static void read_from_cmd_socket(void *anything);
/* ================================================== */ /* ================================================== */
static int
prepare_socket(int family)
{
int port_number, sock_fd;
union sockaddr_in46 my_addr;
IPAddr bind_address;
int on_off = 1;
port_number = CNF_GetCommandPort();
if (port_number < 0) {
port_number = DEFAULT_CANDM_PORT;
}
sock_fd = socket(family, SOCK_DGRAM, 0);
if (sock_fd < 0) {
LOG(LOGS_ERR, LOGF_CmdMon, "Could not open socket : %s", strerror(errno));
return -1;
}
/* Allow reuse of port number */
if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on_off, sizeof(on_off)) < 0) {
LOG(LOGS_ERR, LOGF_CmdMon, "Could not set socket options");
/* Don't quit - we might survive anyway */
}
#ifdef HAVE_IPV6
if (family == AF_INET6) {
#ifdef IPV6_V6ONLY
/* Receive IPv6 packets only */
if (setsockopt(sock_fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on_off, sizeof(on_off)) < 0) {
LOG(LOGS_ERR, LOGF_NtpIO, "Could not request IPV6_V6ONLY socket option");
}
#endif
}
#endif
memset(&my_addr, 0, sizeof (my_addr));
switch (family) {
case AF_INET:
my_addr.in4.sin_family = family;
my_addr.in4.sin_port = htons((unsigned short)port_number);
CNF_GetBindCommandAddress(IPADDR_INET4, &bind_address);
if (bind_address.family == IPADDR_INET4)
my_addr.in4.sin_addr.s_addr = htonl(bind_address.addr.in4);
else
my_addr.in4.sin_addr.s_addr = htonl(INADDR_ANY);
break;
#ifdef HAVE_IPV6
case AF_INET6:
my_addr.in6.sin6_family = family;
my_addr.in6.sin6_port = htons((unsigned short)port_number);
CNF_GetBindCommandAddress(IPADDR_INET6, &bind_address);
if (bind_address.family == IPADDR_INET6)
memcpy(my_addr.in6.sin6_addr.s6_addr, bind_address.addr.in6,
sizeof (my_addr.in6.sin6_addr.s6_addr));
else
my_addr.in6.sin6_addr = in6addr_any;
break;
#endif
default:
assert(0);
}
if (bind(sock_fd, &my_addr.u, sizeof(my_addr)) < 0) {
LOG_FATAL(LOGF_CmdMon, "Could not bind socket : %s", strerror(errno));
}
/* Register handler for read events on the socket */
SCH_AddInputFileHandler(sock_fd, read_from_cmd_socket, (void *)(long)sock_fd);
return sock_fd;
}
/* ================================================== */
void void
CAM_Initialise(void) CAM_Initialise(void)
{ {
int port_number;
struct sockaddr_in my_addr;
unsigned long bind_address;
int on_off = 1;
if (initialised) { if (initialised) {
CROAK("Shouldn't be initialised"); CROAK("Shouldn't be initialised");
@ -188,40 +275,19 @@ CAM_Initialise(void)
free_replies = NULL; free_replies = NULL;
kept_replies.next = NULL; kept_replies.next = NULL;
port_number = CNF_GetCommandPort(); sock_fd4 = prepare_socket(AF_INET);
if (port_number < 0) { #ifdef HAVE_IPV6
port_number = DEFAULT_CANDM_PORT; sock_fd6 = prepare_socket(AF_INET6);
#endif
if (sock_fd4 < 0
#ifdef HAVE_IPV6
&& sock_fd6 < 0
#endif
) {
LOG_FATAL(LOGF_CmdMon, "Could not open any command socket");
} }
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (sock_fd < 0) {
LOG_FATAL(LOGF_CmdMon, "Could not open socket : %s", strerror(errno));
}
/* Allow reuse of port number */
if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on_off, sizeof(on_off)) < 0) {
LOG(LOGS_ERR, LOGF_CmdMon, "Could not set socket options");
/* Don't quit - we might survive anyway */
}
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons((unsigned short) port_number);
CNF_GetBindCommandAddress(&bind_address);
if (bind_address != 0UL) {
my_addr.sin_addr.s_addr = htonl(bind_address);
} else {
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
}
if (bind(sock_fd, (struct sockaddr *) &my_addr, sizeof(my_addr)) < 0) {
LOG_FATAL(LOGF_CmdMon, "Could not bind socket : %s", strerror(errno));
}
/* Register handler for read events on the socket */
SCH_AddInputFileHandler(sock_fd, read_from_cmd_socket, NULL);
access_auth_table = ADF_CreateTable(); access_auth_table = ADF_CreateTable();
} }
@ -231,9 +297,18 @@ CAM_Initialise(void)
void void
CAM_Finalise(void) CAM_Finalise(void)
{ {
SCH_RemoveInputFileHandler(sock_fd); if (sock_fd4 >= 0) {
close(sock_fd); SCH_RemoveInputFileHandler(sock_fd4);
sock_fd = -1; close(sock_fd4);
}
sock_fd4 = -1;
#ifdef HAVE_IPV6
if (sock_fd6 >= 0) {
SCH_RemoveInputFileHandler(sock_fd6);
close(sock_fd6);
}
sock_fd6 = -1;
#endif
ADF_DestroyTable(access_auth_table); ADF_DestroyTable(access_auth_table);
@ -644,21 +719,51 @@ print_reply_packet(CMD_Reply *pkt)
/* ================================================== */ /* ================================================== */
static void static void
transmit_reply(CMD_Reply *msg, struct sockaddr_in *where_to) transmit_reply(CMD_Reply *msg, union sockaddr_in46 *where_to)
{ {
int status; int status;
int tx_message_length; int tx_message_length;
unsigned long remote_ip; int sock_fd;
unsigned short remote_port;
switch (where_to->u.sa_family) {
case AF_INET:
sock_fd = sock_fd4;
break;
#ifdef HAVE_IPV6
case AF_INET6:
sock_fd = sock_fd6;
break;
#endif
default:
assert(0);
}
tx_message_length = PKL_ReplyLength(msg); tx_message_length = PKL_ReplyLength(msg);
status = sendto(sock_fd, (void *) msg, tx_message_length, 0, status = sendto(sock_fd, (void *) msg, tx_message_length, 0,
(struct sockaddr *) where_to, sizeof(struct sockaddr_in)); &where_to->u, sizeof(union sockaddr_in46));
if (status < 0) { if (status < 0) {
remote_ip = ntohl(where_to->sin_addr.s_addr); unsigned short port;
remote_port = ntohs(where_to->sin_port); IPAddr ip;
LOG(LOGS_WARN, LOGF_CmdMon, "Could not send response to %s:%hu", UTI_IPToDottedQuad(remote_ip), remote_port);
switch (where_to->u.sa_family) {
case AF_INET:
ip.family = IPADDR_INET4;
ip.addr.in4 = ntohl(where_to->in4.sin_addr.s_addr);
port = ntohs(where_to->in4.sin_port);
break;
#ifdef HAVE_IPV6
case AF_INET6:
ip.family = IPADDR_INET6;
memcpy(ip.addr.in6, (where_to->in6.sin6_addr.s6_addr), sizeof(ip.addr.in6));
port = ntohs(where_to->in6.sin6_port);
break;
#endif
default:
assert(0);
}
LOG(LOGS_WARN, LOGF_CmdMon, "Could not send response to %s:%hu", UTI_IPToString(&ip), port);
} }
return; return;
@ -679,7 +784,10 @@ static void
handle_online(CMD_Request *rx_message, CMD_Reply *tx_message) handle_online(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
int status; int status;
status = NSR_TakeSourcesOnline(ntohl(rx_message->data.online.mask), ntohl(rx_message->data.online.address)); IPAddr address, mask;
UTI_IPNetworkToHost(&rx_message->data.online.mask, &mask);
UTI_IPNetworkToHost(&rx_message->data.online.address, &address);
status = NSR_TakeSourcesOnline(&mask, &address);
if (status) { if (status) {
tx_message->status = htons(STT_SUCCESS); tx_message->status = htons(STT_SUCCESS);
} else { } else {
@ -693,7 +801,10 @@ static void
handle_offline(CMD_Request *rx_message, CMD_Reply *tx_message) handle_offline(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
int status; int status;
status = NSR_TakeSourcesOffline(ntohl(rx_message->data.offline.mask), ntohl(rx_message->data.offline.address)); IPAddr address, mask;
UTI_IPNetworkToHost(&rx_message->data.offline.mask, &mask);
UTI_IPNetworkToHost(&rx_message->data.offline.address, &address);
status = NSR_TakeSourcesOffline(&mask, &address);
if (status) { if (status) {
tx_message->status = htons(STT_SUCCESS); tx_message->status = htons(STT_SUCCESS);
} else { } else {
@ -707,10 +818,12 @@ static void
handle_burst(CMD_Request *rx_message, CMD_Reply *tx_message) handle_burst(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
int status; int status;
IPAddr address, mask;
UTI_IPNetworkToHost(&rx_message->data.burst.mask, &mask);
UTI_IPNetworkToHost(&rx_message->data.burst.address, &address);
status = NSR_InitiateSampleBurst(ntohl(rx_message->data.burst.n_good_samples), status = NSR_InitiateSampleBurst(ntohl(rx_message->data.burst.n_good_samples),
ntohl(rx_message->data.burst.n_total_samples), ntohl(rx_message->data.burst.n_total_samples),
ntohl(rx_message->data.burst.mask), &mask, &address);
ntohl(rx_message->data.burst.address));
if (status) { if (status) {
tx_message->status = htons(STT_SUCCESS); tx_message->status = htons(STT_SUCCESS);
@ -725,7 +838,9 @@ static void
handle_modify_minpoll(CMD_Request *rx_message, CMD_Reply *tx_message) handle_modify_minpoll(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
int status; int status;
status = NSR_ModifyMinpoll(ntohl(rx_message->data.modify_minpoll.address), IPAddr address;
UTI_IPNetworkToHost(&rx_message->data.modify_minpoll.address, &address);
status = NSR_ModifyMinpoll(&address,
ntohl(rx_message->data.modify_minpoll.new_minpoll)); ntohl(rx_message->data.modify_minpoll.new_minpoll));
if (status) { if (status) {
@ -741,7 +856,9 @@ static void
handle_modify_maxpoll(CMD_Request *rx_message, CMD_Reply *tx_message) handle_modify_maxpoll(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
int status; int status;
status = NSR_ModifyMaxpoll(ntohl(rx_message->data.modify_minpoll.address), IPAddr address;
UTI_IPNetworkToHost(&rx_message->data.modify_minpoll.address, &address);
status = NSR_ModifyMaxpoll(&address,
ntohl(rx_message->data.modify_minpoll.new_minpoll)); ntohl(rx_message->data.modify_minpoll.new_minpoll));
if (status) { if (status) {
@ -757,7 +874,9 @@ static void
handle_modify_maxdelay(CMD_Request *rx_message, CMD_Reply *tx_message) handle_modify_maxdelay(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
int status; int status;
status = NSR_ModifyMaxdelay(ntohl(rx_message->data.modify_maxdelay.address), IPAddr address;
UTI_IPNetworkToHost(&rx_message->data.modify_maxdelay.address, &address);
status = NSR_ModifyMaxdelay(&address,
WIRE2REAL(rx_message->data.modify_maxdelay.new_max_delay)); WIRE2REAL(rx_message->data.modify_maxdelay.new_max_delay));
if (status) { if (status) {
tx_message->status = htons(STT_SUCCESS); tx_message->status = htons(STT_SUCCESS);
@ -772,7 +891,9 @@ static void
handle_modify_maxdelayratio(CMD_Request *rx_message, CMD_Reply *tx_message) handle_modify_maxdelayratio(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
int status; int status;
status = NSR_ModifyMaxdelayratio(ntohl(rx_message->data.modify_maxdelayratio.address), IPAddr address;
UTI_IPNetworkToHost(&rx_message->data.modify_maxdelayratio.address, &address);
status = NSR_ModifyMaxdelayratio(&address,
WIRE2REAL(rx_message->data.modify_maxdelayratio.new_max_delay_ratio)); WIRE2REAL(rx_message->data.modify_maxdelayratio.new_max_delay_ratio));
if (status) { if (status) {
tx_message->status = htons(STT_SUCCESS); tx_message->status = htons(STT_SUCCESS);
@ -884,7 +1005,7 @@ handle_source_data(CMD_Request *rx_message, CMD_Reply *tx_message)
tx_message->status = htons(STT_SUCCESS); tx_message->status = htons(STT_SUCCESS);
tx_message->reply = htons(RPY_SOURCE_DATA); tx_message->reply = htons(RPY_SOURCE_DATA);
tx_message->data.source_data.ip_addr = htonl(report.ip_addr); UTI_IPHostToNetwork(&report.ip_addr, &tx_message->data.source_data.ip_addr);
tx_message->data.source_data.stratum = htons(report.stratum); tx_message->data.source_data.stratum = htons(report.stratum);
tx_message->data.source_data.poll = htons(report.poll); tx_message->data.source_data.poll = htons(report.poll);
switch (report.state) { switch (report.state) {
@ -943,11 +1064,11 @@ handle_rekey(CMD_Request *rx_message, CMD_Reply *tx_message)
static void static void
handle_allow(CMD_Request *rx_message, CMD_Reply *tx_message) handle_allow(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
unsigned long ip; IPAddr ip;
int subnet_bits; int subnet_bits;
ip = ntohl(rx_message->data.allow_deny.ip); UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits); subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
if (NCR_AddAccessRestriction(ip, subnet_bits, 1, 0)) { if (NCR_AddAccessRestriction(&ip, subnet_bits, 1, 0)) {
tx_message->status = htons(STT_SUCCESS); tx_message->status = htons(STT_SUCCESS);
} else { } else {
tx_message->status = htons(STT_BADSUBNET); tx_message->status = htons(STT_BADSUBNET);
@ -959,11 +1080,11 @@ handle_allow(CMD_Request *rx_message, CMD_Reply *tx_message)
static void static void
handle_allowall(CMD_Request *rx_message, CMD_Reply *tx_message) handle_allowall(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
unsigned long ip; IPAddr ip;
int subnet_bits; int subnet_bits;
ip = ntohl(rx_message->data.allow_deny.ip); UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits); subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
if (NCR_AddAccessRestriction(ip, subnet_bits, 1, 1)) { if (NCR_AddAccessRestriction(&ip, subnet_bits, 1, 1)) {
tx_message->status = htons(STT_SUCCESS); tx_message->status = htons(STT_SUCCESS);
} else { } else {
tx_message->status = htons(STT_BADSUBNET); tx_message->status = htons(STT_BADSUBNET);
@ -975,11 +1096,11 @@ handle_allowall(CMD_Request *rx_message, CMD_Reply *tx_message)
static void static void
handle_deny(CMD_Request *rx_message, CMD_Reply *tx_message) handle_deny(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
unsigned long ip; IPAddr ip;
int subnet_bits; int subnet_bits;
ip = ntohl(rx_message->data.allow_deny.ip); UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits); subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
if (NCR_AddAccessRestriction(ip, subnet_bits, 0, 0)) { if (NCR_AddAccessRestriction(&ip, subnet_bits, 0, 0)) {
tx_message->status = htons(STT_SUCCESS); tx_message->status = htons(STT_SUCCESS);
} else { } else {
tx_message->status = htons(STT_BADSUBNET); tx_message->status = htons(STT_BADSUBNET);
@ -991,11 +1112,11 @@ handle_deny(CMD_Request *rx_message, CMD_Reply *tx_message)
static void static void
handle_denyall(CMD_Request *rx_message, CMD_Reply *tx_message) handle_denyall(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
unsigned long ip; IPAddr ip;
int subnet_bits; int subnet_bits;
ip = ntohl(rx_message->data.allow_deny.ip); UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits); subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
if (NCR_AddAccessRestriction(ip, subnet_bits, 0, 1)) { if (NCR_AddAccessRestriction(&ip, subnet_bits, 0, 1)) {
tx_message->status = htons(STT_SUCCESS); tx_message->status = htons(STT_SUCCESS);
} else { } else {
tx_message->status = htons(STT_BADSUBNET); tx_message->status = htons(STT_BADSUBNET);
@ -1007,11 +1128,11 @@ handle_denyall(CMD_Request *rx_message, CMD_Reply *tx_message)
static void static void
handle_cmdallow(CMD_Request *rx_message, CMD_Reply *tx_message) handle_cmdallow(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
unsigned long ip; IPAddr ip;
int subnet_bits; int subnet_bits;
ip = ntohl(rx_message->data.allow_deny.ip); UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits); subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
if (CAM_AddAccessRestriction(ip, subnet_bits, 1, 0)) { if (CAM_AddAccessRestriction(&ip, subnet_bits, 1, 0)) {
tx_message->status = htons(STT_SUCCESS); tx_message->status = htons(STT_SUCCESS);
} else { } else {
tx_message->status = htons(STT_BADSUBNET); tx_message->status = htons(STT_BADSUBNET);
@ -1023,11 +1144,11 @@ handle_cmdallow(CMD_Request *rx_message, CMD_Reply *tx_message)
static void static void
handle_cmdallowall(CMD_Request *rx_message, CMD_Reply *tx_message) handle_cmdallowall(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
unsigned long ip; IPAddr ip;
int subnet_bits; int subnet_bits;
ip = ntohl(rx_message->data.allow_deny.ip); UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits); subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
if (CAM_AddAccessRestriction(ip, subnet_bits, 1, 1)) { if (CAM_AddAccessRestriction(&ip, subnet_bits, 1, 1)) {
tx_message->status = htons(STT_SUCCESS); tx_message->status = htons(STT_SUCCESS);
} else { } else {
tx_message->status = htons(STT_BADSUBNET); tx_message->status = htons(STT_BADSUBNET);
@ -1039,11 +1160,11 @@ handle_cmdallowall(CMD_Request *rx_message, CMD_Reply *tx_message)
static void static void
handle_cmddeny(CMD_Request *rx_message, CMD_Reply *tx_message) handle_cmddeny(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
unsigned long ip; IPAddr ip;
int subnet_bits; int subnet_bits;
ip = ntohl(rx_message->data.allow_deny.ip); UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits); subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
if (CAM_AddAccessRestriction(ip, subnet_bits, 0, 0)) { if (CAM_AddAccessRestriction(&ip, subnet_bits, 0, 0)) {
tx_message->status = htons(STT_SUCCESS); tx_message->status = htons(STT_SUCCESS);
} else { } else {
tx_message->status = htons(STT_BADSUBNET); tx_message->status = htons(STT_BADSUBNET);
@ -1055,11 +1176,11 @@ handle_cmddeny(CMD_Request *rx_message, CMD_Reply *tx_message)
static void static void
handle_cmddenyall(CMD_Request *rx_message, CMD_Reply *tx_message) handle_cmddenyall(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
unsigned long ip; IPAddr ip;
int subnet_bits; int subnet_bits;
ip = ntohl(rx_message->data.allow_deny.ip); UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits); subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
if (CAM_AddAccessRestriction(ip, subnet_bits, 0, 1)) { if (CAM_AddAccessRestriction(&ip, subnet_bits, 0, 1)) {
tx_message->status = htons(STT_SUCCESS); tx_message->status = htons(STT_SUCCESS);
} else { } else {
tx_message->status = htons(STT_BADSUBNET); tx_message->status = htons(STT_BADSUBNET);
@ -1071,9 +1192,9 @@ handle_cmddenyall(CMD_Request *rx_message, CMD_Reply *tx_message)
static void static void
handle_accheck(CMD_Request *rx_message, CMD_Reply *tx_message) handle_accheck(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
unsigned long ip; IPAddr ip;
ip = ntohl(rx_message->data.ac_check.ip); UTI_IPNetworkToHost(&rx_message->data.ac_check.ip, &ip);
if (NCR_CheckAccessRestriction(ip)) { if (NCR_CheckAccessRestriction(&ip)) {
tx_message->status = htons(STT_ACCESSALLOWED); tx_message->status = htons(STT_ACCESSALLOWED);
} else { } else {
tx_message->status = htons(STT_ACCESSDENIED); tx_message->status = htons(STT_ACCESSDENIED);
@ -1085,9 +1206,9 @@ handle_accheck(CMD_Request *rx_message, CMD_Reply *tx_message)
static void static void
handle_cmdaccheck(CMD_Request *rx_message, CMD_Reply *tx_message) handle_cmdaccheck(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
unsigned long ip; IPAddr ip;
ip = ntohl(rx_message->data.ac_check.ip); UTI_IPNetworkToHost(&rx_message->data.ac_check.ip, &ip);
if (CAM_CheckAccessRestriction(ip)) { if (CAM_CheckAccessRestriction(&ip)) {
tx_message->status = htons(STT_ACCESSALLOWED); tx_message->status = htons(STT_ACCESSALLOWED);
} else { } else {
tx_message->status = htons(STT_ACCESSDENIED); tx_message->status = htons(STT_ACCESSDENIED);
@ -1103,8 +1224,8 @@ handle_add_server(CMD_Request *rx_message, CMD_Reply *tx_message)
SourceParameters params; SourceParameters params;
NSR_Status status; NSR_Status status;
rem_addr.ip_addr = ntohl(rx_message->data.ntp_source.ip_addr); UTI_IPNetworkToHost(&rx_message->data.ntp_source.ip_addr, &rem_addr.ip_addr);
rem_addr.local_ip_addr = 0; rem_addr.local_ip_addr.family = IPADDR_UNSPEC;
rem_addr.port = (unsigned short)(ntohl(rx_message->data.ntp_source.port)); rem_addr.port = (unsigned short)(ntohl(rx_message->data.ntp_source.port));
params.minpoll = ntohl(rx_message->data.ntp_source.minpoll); params.minpoll = ntohl(rx_message->data.ntp_source.minpoll);
params.maxpoll = ntohl(rx_message->data.ntp_source.maxpoll); params.maxpoll = ntohl(rx_message->data.ntp_source.maxpoll);
@ -1125,6 +1246,9 @@ handle_add_server(CMD_Request *rx_message, CMD_Reply *tx_message)
case NSR_TooManySources: case NSR_TooManySources:
tx_message->status = htons(STT_TOOMANYSOURCES); tx_message->status = htons(STT_TOOMANYSOURCES);
break; break;
case NSR_InvalidAF:
tx_message->status = htons(STT_INVALIDAF);
break;
case NSR_NoSuchSource: case NSR_NoSuchSource:
CROAK("Impossible"); CROAK("Impossible");
break; break;
@ -1140,8 +1264,8 @@ handle_add_peer(CMD_Request *rx_message, CMD_Reply *tx_message)
SourceParameters params; SourceParameters params;
NSR_Status status; NSR_Status status;
rem_addr.ip_addr = ntohl(rx_message->data.ntp_source.ip_addr); UTI_IPNetworkToHost(&rx_message->data.ntp_source.ip_addr, &rem_addr.ip_addr);
rem_addr.local_ip_addr = 0; rem_addr.local_ip_addr.family = IPADDR_UNSPEC;
rem_addr.port = (unsigned short)(ntohl(rx_message->data.ntp_source.port)); rem_addr.port = (unsigned short)(ntohl(rx_message->data.ntp_source.port));
params.minpoll = ntohl(rx_message->data.ntp_source.minpoll); params.minpoll = ntohl(rx_message->data.ntp_source.minpoll);
params.maxpoll = ntohl(rx_message->data.ntp_source.maxpoll); params.maxpoll = ntohl(rx_message->data.ntp_source.maxpoll);
@ -1161,6 +1285,9 @@ handle_add_peer(CMD_Request *rx_message, CMD_Reply *tx_message)
case NSR_TooManySources: case NSR_TooManySources:
tx_message->status = htons(STT_TOOMANYSOURCES); tx_message->status = htons(STT_TOOMANYSOURCES);
break; break;
case NSR_InvalidAF:
tx_message->status = htons(STT_INVALIDAF);
break;
case NSR_NoSuchSource: case NSR_NoSuchSource:
CROAK("Impossible"); CROAK("Impossible");
break; break;
@ -1175,8 +1302,8 @@ handle_del_source(CMD_Request *rx_message, CMD_Reply *tx_message)
NTP_Remote_Address rem_addr; NTP_Remote_Address rem_addr;
NSR_Status status; NSR_Status status;
rem_addr.ip_addr = ntohl(rx_message->data.del_source.ip_addr); UTI_IPNetworkToHost(&rx_message->data.del_source.ip_addr, &rem_addr.ip_addr);
rem_addr.local_ip_addr = 0; rem_addr.local_ip_addr.family = IPADDR_UNSPEC;
rem_addr.port = 0; rem_addr.port = 0;
status = NSR_RemoveSource(&rem_addr); status = NSR_RemoveSource(&rem_addr);
@ -1189,6 +1316,7 @@ handle_del_source(CMD_Request *rx_message, CMD_Reply *tx_message)
break; break;
case NSR_TooManySources: case NSR_TooManySources:
case NSR_AlreadyInUse: case NSR_AlreadyInUse:
case NSR_InvalidAF:
CROAK("Impossible"); CROAK("Impossible");
break; break;
} }
@ -1273,7 +1401,7 @@ handle_sourcestats(CMD_Request *rx_message, CMD_Reply *tx_message)
if (status) { if (status) {
tx_message->status = htons(STT_SUCCESS); tx_message->status = htons(STT_SUCCESS);
tx_message->reply = htons(RPY_SOURCESTATS); tx_message->reply = htons(RPY_SOURCESTATS);
tx_message->data.sourcestats.ip_addr = htonl(report.ip_addr); UTI_IPHostToNetwork(&report.ip_addr, &tx_message->data.sourcestats.ip_addr);
tx_message->data.sourcestats.n_samples = htonl(report.n_samples); tx_message->data.sourcestats.n_samples = htonl(report.n_samples);
tx_message->data.sourcestats.n_runs = htonl(report.n_runs); tx_message->data.sourcestats.n_runs = htonl(report.n_runs);
tx_message->data.sourcestats.span_seconds = htonl(report.span_seconds); tx_message->data.sourcestats.span_seconds = htonl(report.span_seconds);
@ -1345,8 +1473,8 @@ static void
handle_subnets_accessed(CMD_Request *rx_message, CMD_Reply *tx_message) handle_subnets_accessed(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
int i, j; int i, j;
unsigned long ns; unsigned long ns, bits_specd;
unsigned long ip, bits_specd; IPAddr ip;
CLG_Status result; CLG_Status result;
ns = ntohl(rx_message->data.subnets_accessed.n_subnets); ns = ntohl(rx_message->data.subnets_accessed.n_subnets);
@ -1355,13 +1483,13 @@ handle_subnets_accessed(CMD_Request *rx_message, CMD_Reply *tx_message)
tx_message->data.subnets_accessed.n_subnets = htonl(ns); tx_message->data.subnets_accessed.n_subnets = htonl(ns);
for (i=0; i<ns; i++) { for (i=0; i<ns; i++) {
ip = ntohl(rx_message->data.subnets_accessed.subnets[i].ip); UTI_IPNetworkToHost(&rx_message->data.subnets_accessed.subnets[i].ip, &ip);
bits_specd = ntohl(rx_message->data.subnets_accessed.subnets[i].bits_specd); bits_specd = ntohl(rx_message->data.subnets_accessed.subnets[i].bits_specd);
tx_message->data.subnets_accessed.subnets[i].ip = htonl(ip); UTI_IPHostToNetwork(&ip, &tx_message->data.subnets_accessed.subnets[i].ip);
tx_message->data.subnets_accessed.subnets[i].bits_specd = htonl(bits_specd); tx_message->data.subnets_accessed.subnets[i].bits_specd = htonl(bits_specd);
result = CLG_GetSubnetBitmap(ip, bits_specd, tx_message->data.subnets_accessed.subnets[i].bitmap); result = CLG_GetSubnetBitmap(&ip, bits_specd, tx_message->data.subnets_accessed.subnets[i].bitmap);
switch (result) { switch (result) {
case CLG_SUCCESS: case CLG_SUCCESS:
case CLG_EMPTYSUBNET: case CLG_EMPTYSUBNET:
@ -1394,7 +1522,7 @@ handle_client_accesses(CMD_Request *rx_message, CMD_Reply *tx_message)
CLG_Status result; CLG_Status result;
RPT_ClientAccess_Report report; RPT_ClientAccess_Report report;
unsigned long nc; unsigned long nc;
unsigned long ip; IPAddr ip;
int i; int i;
struct timeval now; struct timeval now;
double local_time_error; double local_time_error;
@ -1409,10 +1537,10 @@ handle_client_accesses(CMD_Request *rx_message, CMD_Reply *tx_message)
printf("%d %d\n", (int)sizeof(RPY_ClientAccesses_Client), (int)offsetof(CMD_Reply, data.client_accesses.clients)); printf("%d %d\n", (int)sizeof(RPY_ClientAccesses_Client), (int)offsetof(CMD_Reply, data.client_accesses.clients));
for (i=0; i<nc; i++) { for (i=0; i<nc; i++) {
ip = ntohl(rx_message->data.client_accesses.client_ips[i]); UTI_IPNetworkToHost(&rx_message->data.client_accesses.client_ips[i], &ip);
tx_message->data.client_accesses.clients[i].ip = htonl(ip); UTI_IPHostToNetwork(&ip, &tx_message->data.client_accesses.clients[i].ip);
result = CLG_GetClientAccessReportByIP(ip, &report, now.tv_sec); result = CLG_GetClientAccessReportByIP(&ip, &report, now.tv_sec);
switch (result) { switch (result) {
case CLG_SUCCESS: case CLG_SUCCESS:
tx_message->data.client_accesses.clients[i].client_hits = htonl(report.client_hits); tx_message->data.client_accesses.clients[i].client_hits = htonl(report.client_hits);
@ -1422,13 +1550,13 @@ handle_client_accesses(CMD_Request *rx_message, CMD_Reply *tx_message)
tx_message->data.client_accesses.clients[i].cmd_hits_bad = htonl(report.cmd_hits_bad); tx_message->data.client_accesses.clients[i].cmd_hits_bad = htonl(report.cmd_hits_bad);
tx_message->data.client_accesses.clients[i].last_ntp_hit_ago = htonl(report.last_ntp_hit_ago); tx_message->data.client_accesses.clients[i].last_ntp_hit_ago = htonl(report.last_ntp_hit_ago);
tx_message->data.client_accesses.clients[i].last_cmd_hit_ago = htonl(report.last_cmd_hit_ago); tx_message->data.client_accesses.clients[i].last_cmd_hit_ago = htonl(report.last_cmd_hit_ago);
printf("%08lx %lu %lu %lu %lu %lu %lu %lu\n", ip, report.client_hits, report.peer_hits, report.cmd_hits_auth, report.cmd_hits_normal, report.cmd_hits_bad, report.last_ntp_hit_ago, report.last_cmd_hit_ago); printf("%s %lu %lu %lu %lu %lu %lu %lu\n", UTI_IPToString(&ip), report.client_hits, report.peer_hits, report.cmd_hits_auth, report.cmd_hits_normal, report.cmd_hits_bad, report.last_ntp_hit_ago, report.last_cmd_hit_ago);
break; break;
case CLG_EMPTYSUBNET: case CLG_EMPTYSUBNET:
/* Signal back to the client that this single client address /* Signal back to the client that this single client address
was unknown, by specifying the zero ip address, which will was unknown */
always be invalid (hopefully) */ ip.family = IPADDR_UNSPEC;
tx_message->data.client_accesses.clients[i].ip = htonl(0); UTI_IPHostToNetwork(&ip, &tx_message->data.client_accesses.clients[i].ip);
break; break;
case CLG_INACTIVE: case CLG_INACTIVE:
tx_message->status = htons(STT_INACTIVE); tx_message->status = htons(STT_INACTIVE);
@ -1471,7 +1599,7 @@ handle_client_accesses_by_index(CMD_Request *rx_message, CMD_Reply *tx_message)
switch (result) { switch (result) {
case CLG_SUCCESS: case CLG_SUCCESS:
tx_message->data.client_accesses_by_index.clients[j].ip = htonl(report.ip_addr); UTI_IPHostToNetwork(&report.ip_addr, &tx_message->data.client_accesses_by_index.clients[j].ip);
tx_message->data.client_accesses_by_index.clients[j].client_hits = htonl(report.client_hits); tx_message->data.client_accesses_by_index.clients[j].client_hits = htonl(report.client_hits);
tx_message->data.client_accesses_by_index.clients[j].peer_hits = htonl(report.peer_hits); tx_message->data.client_accesses_by_index.clients[j].peer_hits = htonl(report.peer_hits);
tx_message->data.client_accesses_by_index.clients[j].cmd_hits_auth = htonl(report.cmd_hits_auth); tx_message->data.client_accesses_by_index.clients[j].cmd_hits_auth = htonl(report.cmd_hits_auth);
@ -1594,9 +1722,10 @@ read_from_cmd_socket(void *anything)
CMD_Request rx_message; CMD_Request rx_message;
CMD_Reply tx_message, *prev_tx_message; CMD_Reply tx_message, *prev_tx_message;
int rx_message_length, tx_message_length; int rx_message_length, tx_message_length;
struct sockaddr_in where_from; int sock_fd;
union sockaddr_in46 where_from;
socklen_t from_length; socklen_t from_length;
unsigned long remote_ip; IPAddr remote_ip;
unsigned short remote_port; unsigned short remote_port;
int md5_ok; int md5_ok;
int utoken_ok, token_ok; int utoken_ok, token_ok;
@ -1617,14 +1746,14 @@ read_from_cmd_socket(void *anything)
rx_message_length = sizeof(rx_message); rx_message_length = sizeof(rx_message);
from_length = sizeof(where_from); from_length = sizeof(where_from);
sock_fd = (long)anything;
status = recvfrom(sock_fd, (char *)&rx_message, rx_message_length, flags, status = recvfrom(sock_fd, (char *)&rx_message, rx_message_length, flags,
(struct sockaddr *)&where_from, &from_length); &where_from.u, &from_length);
if (status < 0) { if (status < 0) {
LOG(LOGS_WARN, LOGF_CmdMon, "Error [%s] reading from control socket (IP=%s port=%d)", LOG(LOGS_WARN, LOGF_CmdMon, "Error [%s] reading from control socket %d",
strerror(errno), strerror(errno), sock_fd);
UTI_IPToDottedQuad(ntohl(where_from.sin_addr.s_addr)), return;
ntohs(where_from.sin_port));
} }
read_length = status; read_length = status;
@ -1650,12 +1779,31 @@ read_from_cmd_socket(void *anything)
tx_message.token = htonl(0xffffffffUL); tx_message.token = htonl(0xffffffffUL);
memset(&tx_message.auth, 0, sizeof(tx_message.auth)); memset(&tx_message.auth, 0, sizeof(tx_message.auth));
remote_ip = ntohl(where_from.sin_addr.s_addr); switch (where_from.u.sa_family) {
remote_port = ntohs(where_from.sin_port); case AF_INET:
remote_ip.family = IPADDR_INET4;
remote_ip.addr.in4 = ntohl(where_from.in4.sin_addr.s_addr);
remote_port = ntohs(where_from.in4.sin_port);
localhost = (remote_ip.addr.in4 == 0x7f000001UL);
break;
#ifdef HAVE_IPV6
case AF_INET6:
remote_ip.family = IPADDR_INET6;
memcpy(&remote_ip.addr.in6, where_from.in6.sin6_addr.s6_addr,
sizeof (remote_ip.addr.in6));
remote_port = ntohs(where_from.in6.sin6_port);
/* Check for ::1 */
for (localhost = 0; localhost < 16; localhost++)
if (remote_ip.addr.in6[localhost] != 0)
break;
localhost = (localhost == 15 && remote_ip.addr.in6[localhost] == 1);
break;
#endif
default:
assert(0);
}
localhost = (remote_ip == 0x7f000001UL); if ((!ADF_IsAllowed(access_auth_table, &remote_ip)) &&
if ((!ADF_IsAllowed(access_auth_table, remote_ip)) &&
(!localhost)) { (!localhost)) {
/* The client is not allowed access, so don't waste any more time /* The client is not allowed access, so don't waste any more time
on him. Note that localhost is always allowed access on him. Note that localhost is always allowed access
@ -1667,7 +1815,7 @@ read_from_cmd_socket(void *anything)
hitting us with bad packets until our log file(s) fill up. */ hitting us with bad packets until our log file(s) fill up. */
LOG(LOGS_WARN, LOGF_CmdMon, "Command packet received from unauthorised host %s port %d", LOG(LOGS_WARN, LOGF_CmdMon, "Command packet received from unauthorised host %s port %d",
UTI_IPToDottedQuad(remote_ip), UTI_IPToString(&remote_ip),
remote_port); remote_port);
tx_message.status = htons(STT_NOHOSTACCESS); tx_message.status = htons(STT_NOHOSTACCESS);
@ -1678,8 +1826,8 @@ read_from_cmd_socket(void *anything)
if (read_length != expected_length) { if (read_length != expected_length) {
LOG(LOGS_WARN, LOGF_CmdMon, "Read incorrectly sized packet from %s:%hu", UTI_IPToDottedQuad(remote_ip), remote_port); LOG(LOGS_WARN, LOGF_CmdMon, "Read incorrectly sized packet from %s:%hu", UTI_IPToString(&remote_ip), remote_port);
CLG_LogCommandAccess(remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec); CLG_LogCommandAccess(&remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec);
/* For now, just ignore the packet. We may want to send a reply /* For now, just ignore the packet. We may want to send a reply
back eventually */ back eventually */
return; return;
@ -1691,7 +1839,7 @@ read_from_cmd_socket(void *anything)
(rx_message.res2 != 0)) { (rx_message.res2 != 0)) {
/* We don't know how to process anything like this */ /* We don't know how to process anything like this */
CLG_LogCommandAccess(remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec); CLG_LogCommandAccess(&remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec);
return; return;
} }
@ -1773,7 +1921,7 @@ read_from_cmd_socket(void *anything)
status = sendto(sock_fd, (void *) prev_tx_message, tx_message_length, 0, status = sendto(sock_fd, (void *) prev_tx_message, tx_message_length, 0,
(struct sockaddr *) &where_from, sizeof(where_from)); (struct sockaddr *) &where_from, sizeof(where_from));
if (status < 0) { if (status < 0) {
LOG(LOGS_WARN, LOGF_CmdMon, "Could not send response to %s:%hu", UTI_IPToDottedQuad(remote_ip), remote_port); LOG(LOGS_WARN, LOGF_CmdMon, "Could not send response to %s:%hu", UTI_IPToString(&remote_ip), remote_port);
} }
return; return;
} }
@ -1800,9 +1948,9 @@ read_from_cmd_socket(void *anything)
authenticated = md5_ok & utoken_ok & token_ok; authenticated = md5_ok & utoken_ok & token_ok;
if (authenticated) { if (authenticated) {
CLG_LogCommandAccess(remote_ip, CLG_CMD_AUTH, cooked_now.tv_sec); CLG_LogCommandAccess(&remote_ip, CLG_CMD_AUTH, cooked_now.tv_sec);
} else { } else {
CLG_LogCommandAccess(remote_ip, CLG_CMD_NORMAL, cooked_now.tv_sec); CLG_LogCommandAccess(&remote_ip, CLG_CMD_NORMAL, cooked_now.tv_sec);
} }
if (issue_token) { if (issue_token) {
@ -1895,7 +2043,7 @@ read_from_cmd_socket(void *anything)
if (!issue_token) { if (!issue_token) {
LOG(LOGS_WARN, LOGF_CmdMon, LOG(LOGS_WARN, LOGF_CmdMon,
"Bad command logon from %s port %d (md5_ok=%d valid_ts=%d)\n", "Bad command logon from %s port %d (md5_ok=%d valid_ts=%d)\n",
UTI_IPToDottedQuad(remote_ip), UTI_IPToString(&remote_ip),
remote_port, remote_port,
md5_ok, valid_ts); md5_ok, valid_ts);
} }
@ -2092,7 +2240,7 @@ read_from_cmd_socket(void *anything)
/* ================================================== */ /* ================================================== */
int int
CAM_AddAccessRestriction(unsigned long ip_addr, int subnet_bits, int allow, int all) CAM_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all)
{ {
ADF_Status status; ADF_Status status;
@ -2122,7 +2270,7 @@ CAM_AddAccessRestriction(unsigned long ip_addr, int subnet_bits, int allow, int
/* ================================================== */ /* ================================================== */
int int
CAM_CheckAccessRestriction(unsigned long ip_addr) CAM_CheckAccessRestriction(IPAddr *ip_addr)
{ {
return ADF_IsAllowed(access_auth_table, ip_addr); return ADF_IsAllowed(access_auth_table, ip_addr);
} }

View file

@ -31,11 +31,13 @@
#ifndef GOT_CMDMON_H #ifndef GOT_CMDMON_H
#define GOT_CMDMON_H #define GOT_CMDMON_H
#include "addressing.h"
extern void CAM_Initialise(void); extern void CAM_Initialise(void);
extern void CAM_Finalise(void); extern void CAM_Finalise(void);
extern int CAM_AddAccessRestriction(unsigned long ip_addr, int subnet_bits, int allow, int all); extern int CAM_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all);
extern int CAM_CheckAccessRestriction(unsigned long ip_addr); extern int CAM_CheckAccessRestriction(IPAddr *ip_addr);
#endif /* GOT_CMDMON_H */ #endif /* GOT_CMDMON_H */

View file

@ -61,8 +61,7 @@ CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src)
ok = 0; ok = 0;
if (sscanf(line, "%" SMAXLEN "s%n", hostname, &n) == 1) { if (sscanf(line, "%" SMAXLEN "s%n", hostname, &n) == 1) {
src->ip_addr = DNS_Name2IPAddressRetry(hostname); if (DNS_Name2IPAddress(hostname, &src->ip_addr, 1)) {
if (src->ip_addr != DNS_Failed_Address) {
ok = 1; ok = 1;
} }
} }

View file

@ -32,6 +32,7 @@
#define GOT_CMDPARSE_H #define GOT_CMDPARSE_H
#include "srcparams.h" #include "srcparams.h"
#include "addressing.h"
typedef enum { typedef enum {
CPS_Success, CPS_Success,
@ -47,7 +48,7 @@ typedef enum {
} CPS_Status; } CPS_Status;
typedef struct { typedef struct {
unsigned long ip_addr; IPAddr ip_addr;
unsigned short port; unsigned short port;
SourceParameters params; SourceParameters params;
} CPS_NTP_Source; } CPS_NTP_Source;

183
conf.c
View file

@ -53,6 +53,7 @@
#include "acquire.h" #include "acquire.h"
#include "cmdparse.h" #include "cmdparse.h"
#include "broadcast.h" #include "broadcast.h"
#include "util.h"
/* ================================================== */ /* ================================================== */
@ -136,7 +137,7 @@ static int n_init_srcs;
than this, slew instead of stepping */ than this, slew instead of stepping */
static int init_slew_threshold = -1; static int init_slew_threshold = -1;
#define MAX_INIT_SRCS 8 #define MAX_INIT_SRCS 8
static unsigned long init_srcs_ip[MAX_INIT_SRCS]; static IPAddr init_srcs_ip[MAX_INIT_SRCS];
static int enable_manual=0; static int enable_manual=0;
@ -156,13 +157,13 @@ static double mail_change_threshold = 0.0;
memory */ memory */
static int no_client_log = 0; static int no_client_log = 0;
/* IP address (host order) for binding the NTP socket to. 0 means INADDR_ANY /* IP addresses for binding the NTP socket to. UNSPEC family means INADDR_ANY
will be used */ will be used */
static unsigned long bind_address = 0UL; static IPAddr bind_address4, bind_address6;
/* IP address (host order) for binding the command socket to. 0 means /* IP addresses for binding the command socket to. UNSPEC family means
use the value of bind_address */ use the value of bind_address */
static unsigned long bind_cmd_address = 0UL; static IPAddr bind_cmd_address4, bind_cmd_address6;
/* Filename to use for storing pid of running chronyd, to prevent multiple /* Filename to use for storing pid of running chronyd, to prevent multiple
* chronyds being started. */ * chronyds being started. */
@ -243,7 +244,7 @@ typedef enum {
typedef struct { typedef struct {
NTP_Source_Type type; NTP_Source_Type type;
unsigned long ip_addr; IPAddr ip_addr;
unsigned short port; unsigned short port;
SourceParameters params; SourceParameters params;
} NTP_Source; } NTP_Source;
@ -263,7 +264,7 @@ static int n_refclock_sources = 0;
typedef struct _AllowDeny { typedef struct _AllowDeny {
struct _AllowDeny *next; struct _AllowDeny *next;
struct _AllowDeny *prev; struct _AllowDeny *prev;
unsigned long ip; IPAddr ip;
int subnet_bits; int subnet_bits;
int all; /* 1 to override existing more specific defns */ int all; /* 1 to override existing more specific defns */
int allow; /* 0 for deny, 1 for allow */ int allow; /* 0 for deny, 1 for allow */
@ -697,7 +698,7 @@ parse_initstepslew(const char *line)
char hostname[HOSTNAME_LEN+1]; char hostname[HOSTNAME_LEN+1];
int n; int n;
int threshold; int threshold;
unsigned long ip_addr; IPAddr ip_addr;
n_init_srcs = 0; n_init_srcs = 0;
p = line; p = line;
@ -710,8 +711,7 @@ parse_initstepslew(const char *line)
} }
while (*p) { while (*p) {
if (sscanf(p, "%" SHOSTNAME_LEN "s%n", hostname, &n) == 1) { if (sscanf(p, "%" SHOSTNAME_LEN "s%n", hostname, &n) == 1) {
ip_addr = DNS_Name2IPAddressRetry(hostname); if (DNS_Name2IPAddress(hostname, &ip_addr, 1)) {
if (ip_addr != DNS_Failed_Address) {
init_srcs_ip[n_init_srcs] = ip_addr; init_srcs_ip[n_init_srcs] = ip_addr;
++n_init_srcs; ++n_init_srcs;
} }
@ -803,7 +803,7 @@ parse_allow_deny(const char *line, AllowDeny *list, int allow)
unsigned long a, b, c, d, n; unsigned long a, b, c, d, n;
int all = 0; int all = 0;
AllowDeny *new_node = NULL; AllowDeny *new_node = NULL;
unsigned long ip_addr; IPAddr ip_addr;
p = line; p = line;
@ -820,45 +820,54 @@ parse_allow_deny(const char *line, AllowDeny *list, int allow)
new_node = MallocNew(AllowDeny); new_node = MallocNew(AllowDeny);
new_node->allow = allow; new_node->allow = allow;
new_node->all = all; new_node->all = all;
new_node->ip = 0UL; new_node->ip.family = IPADDR_UNSPEC;
new_node->subnet_bits = 0; new_node->subnet_bits = 0;
} else { } else {
char *slashpos; char *slashpos;
slashpos = strchr(p, '/'); slashpos = strchr(p, '/');
if (slashpos) *slashpos = 0; if (slashpos) *slashpos = 0;
n = sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d); n = 0;
if (UTI_StringToIP(p, &ip_addr) ||
if (n >= 1) { (n = sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d)) >= 1) {
new_node = MallocNew(AllowDeny); new_node = MallocNew(AllowDeny);
new_node->allow = allow; new_node->allow = allow;
new_node->all = all; new_node->all = all;
a &= 0xff; if (n == 0) {
b &= 0xff; new_node->ip = ip_addr;
c &= 0xff; if (ip_addr.family == IPADDR_INET6)
d &= 0xff; new_node->subnet_bits = 128;
else
switch (n) {
case 1:
new_node->ip = (a<<24);
new_node->subnet_bits = 8;
break;
case 2:
new_node->ip = (a<<24) | (b<<16);
new_node->subnet_bits = 16;
break;
case 3:
new_node->ip = (a<<24) | (b<<16) | (c<<8);
new_node->subnet_bits = 24;
break;
case 4:
new_node->ip = (a<<24) | (b<<16) | (c<<8) | d;
new_node->subnet_bits = 32; new_node->subnet_bits = 32;
break; } else {
default: new_node->ip.family = IPADDR_INET4;
assert(0);
a &= 0xff;
b &= 0xff;
c &= 0xff;
d &= 0xff;
switch (n) {
case 1:
new_node->ip.addr.in4 = (a<<24);
new_node->subnet_bits = 8;
break;
case 2:
new_node->ip.addr.in4 = (a<<24) | (b<<16);
new_node->subnet_bits = 16;
break;
case 3:
new_node->ip.addr.in4 = (a<<24) | (b<<16) | (c<<8);
new_node->subnet_bits = 24;
break;
case 4:
new_node->ip.addr.in4 = (a<<24) | (b<<16) | (c<<8) | d;
new_node->subnet_bits = 32;
break;
default:
assert(0);
}
} }
if (slashpos) { if (slashpos) {
@ -872,13 +881,15 @@ parse_allow_deny(const char *line, AllowDeny *list, int allow)
} }
} else { } else {
ip_addr = DNS_Name2IPAddressRetry(p); if (DNS_Name2IPAddress(p, &ip_addr, 1)) {
if (ip_addr != DNS_Failed_Address) {
new_node = MallocNew(AllowDeny); new_node = MallocNew(AllowDeny);
new_node->allow = allow; new_node->allow = allow;
new_node->all = all; new_node->all = all;
new_node->ip = ip_addr; new_node->ip = ip_addr;
new_node->subnet_bits = 32; if (ip_addr.family == IPADDR_INET6)
new_node->subnet_bits = 128;
else
new_node->subnet_bits = 32;
} else { } else {
LOG(LOGS_WARN, LOGF_Configure, "Could not read address at line %d", line_number); LOG(LOGS_WARN, LOGF_Configure, "Could not read address at line %d", line_number);
} }
@ -931,27 +942,20 @@ parse_cmddeny(const char *line)
/* ================================================== */ /* ================================================== */
static unsigned long
parse_an_address(const char *line, const char *errmsg)
{
unsigned long a, b, c, d;
int n;
n = sscanf(line, "%lu.%lu.%lu.%lu", &a, &b, &c, &d);
if (n == 4) {
return (((a&0xff)<<24) | ((b&0xff)<<16) |
((c&0xff)<<8) | (d&0xff));
} else {
LOG(LOGS_WARN, LOGF_Configure, errmsg, line_number);
return 0UL;
}
}
/* ================================================== */
static void static void
parse_bindaddress(const char *line) parse_bindaddress(const char *line)
{ {
bind_address = parse_an_address(line, "Could not read bind address at line %d\n"); IPAddr ip;
char addr[51];
if (sscanf(line, "%50s", addr) == 1 && UTI_StringToIP(addr, &ip)) {
if (ip.family == IPADDR_INET4)
bind_address4 = ip;
else if (ip.family == IPADDR_INET6)
bind_address6 = ip;
} else {
LOG(LOGS_WARN, LOGF_Configure, "Could not read bind address at line %d\n", line_number);
}
} }
/* ================================================== */ /* ================================================== */
@ -959,7 +963,17 @@ parse_bindaddress(const char *line)
static void static void
parse_bindcmdaddress(const char *line) parse_bindcmdaddress(const char *line)
{ {
bind_cmd_address = parse_an_address(line, "Could not read bind command address at line %d\n"); IPAddr ip;
char addr[51];
if (sscanf(line, "%50s", addr) == 1 && UTI_StringToIP(addr, &ip)) {
if (ip.family == IPADDR_INET4)
bind_cmd_address4 = ip;
else if (ip.family == IPADDR_INET6)
bind_cmd_address6 = ip;
} else {
LOG(LOGS_WARN, LOGF_Configure, "Could not read bind command address at line %d\n", line_number);
}
} }
/* ================================================== */ /* ================================================== */
@ -976,7 +990,7 @@ parse_pidfile(const char *line)
typedef struct { typedef struct {
/* Both in host (not necessarily network) order */ /* Both in host (not necessarily network) order */
unsigned long addr; IPAddr addr;
unsigned short port; unsigned short port;
int interval; int interval;
} NTP_Broadcast_Destination; } NTP_Broadcast_Destination;
@ -992,27 +1006,22 @@ parse_broadcast(const char *line)
{ {
/* Syntax : broadcast <interval> <broadcast-IP-addr> [<port>] */ /* Syntax : broadcast <interval> <broadcast-IP-addr> [<port>] */
int port; int port;
unsigned int a, b, c, d;
int n; int n;
int interval; int interval;
unsigned long addr; char addr[51];
IPAddr ip;
n = sscanf(line, "%d %u.%u.%u.%u %d", &interval, &a, &b, &c, &d, &port); n = sscanf(line, "%d %50s %d", &interval, addr, &port);
if (n < 5) { if (n < 2 || !UTI_StringToIP(addr, &ip)) {
LOG(LOGS_WARN, LOGF_Configure, "Could not parse broadcast directive at line %d", line_number); LOG(LOGS_WARN, LOGF_Configure, "Could not parse broadcast directive at line %d", line_number);
return; return;
} else if (n == 5) { } else if (n == 2) {
/* default port */ /* default port */
port = 123; port = 123;
} else if (n > 6) { } else if (n > 3) {
LOG(LOGS_WARN, LOGF_Configure, "Too many fields in broadcast directive at line %d", line_number); LOG(LOGS_WARN, LOGF_Configure, "Too many fields in broadcast directive at line %d", line_number);
} }
addr = ((unsigned long) a << 24) |
((unsigned long) b << 16) |
((unsigned long) c << 8) |
((unsigned long) d );
if (max_broadcasts == n_broadcasts) { if (max_broadcasts == n_broadcasts) {
/* Expand array */ /* Expand array */
max_broadcasts += 8; max_broadcasts += 8;
@ -1023,7 +1032,7 @@ parse_broadcast(const char *line)
} }
} }
broadcasts[n_broadcasts].addr = addr; broadcasts[n_broadcasts].addr = ip;
broadcasts[n_broadcasts].port = port; broadcasts[n_broadcasts].port = port;
broadcasts[n_broadcasts].interval = interval; broadcasts[n_broadcasts].interval = interval;
++n_broadcasts; ++n_broadcasts;
@ -1074,7 +1083,7 @@ CNF_AddSources(void) {
for (i=0; i<n_ntp_sources; i++) { for (i=0; i<n_ntp_sources; i++) {
server.ip_addr = ntp_sources[i].ip_addr; server.ip_addr = ntp_sources[i].ip_addr;
server.local_ip_addr = 0; memset(&server.local_ip_addr, 0, sizeof (server.local_ip_addr));
server.port = ntp_sources[i].port; server.port = ntp_sources[i].port;
switch (ntp_sources[i].type) { switch (ntp_sources[i].type) {
@ -1111,7 +1120,7 @@ CNF_AddBroadcasts(void)
{ {
int i; int i;
for (i=0; i<n_broadcasts; i++) { for (i=0; i<n_broadcasts; i++) {
BRD_AddDestination(broadcasts[i].addr, BRD_AddDestination(&broadcasts[i].addr,
broadcasts[i].port, broadcasts[i].port,
broadcasts[i].interval); broadcasts[i].interval);
} }
@ -1307,14 +1316,14 @@ CNF_SetupAccessRestrictions(void)
int status; int status;
for (node = ntp_auth_list.next; node != &ntp_auth_list; node = node->next) { for (node = ntp_auth_list.next; node != &ntp_auth_list; node = node->next) {
status = NCR_AddAccessRestriction(node->ip, node->subnet_bits, node->allow, node->all); status = NCR_AddAccessRestriction(&node->ip, node->subnet_bits, node->allow, node->all);
if (!status) { if (!status) {
LOG(LOGS_WARN, LOGF_Configure, "Bad subnet for %08lx", node->ip); LOG(LOGS_WARN, LOGF_Configure, "Bad subnet for %08lx", node->ip);
} }
} }
for (node = cmd_auth_list.next; node != &cmd_auth_list; node = node->next) { for (node = cmd_auth_list.next; node != &cmd_auth_list; node = node->next) {
status = CAM_AddAccessRestriction(node->ip, node->subnet_bits, node->allow, node->all); status = CAM_AddAccessRestriction(&node->ip, node->subnet_bits, node->allow, node->all);
if (!status) { if (!status) {
LOG(LOGS_WARN, LOGF_Configure, "Bad subnet for %08lx", node->ip); LOG(LOGS_WARN, LOGF_Configure, "Bad subnet for %08lx", node->ip);
} }
@ -1334,17 +1343,27 @@ CNF_GetNoClientLog(void)
/* ================================================== */ /* ================================================== */
void void
CNF_GetBindAddress(unsigned long *addr) CNF_GetBindAddress(int family, IPAddr *addr)
{ {
*addr = bind_address; if (family == IPADDR_INET4)
*addr = bind_address4;
else if (family == IPADDR_INET6)
*addr = bind_address6;
else
addr->family = IPADDR_UNSPEC;
} }
/* ================================================== */ /* ================================================== */
void void
CNF_GetBindCommandAddress(unsigned long *addr) CNF_GetBindCommandAddress(int family, IPAddr *addr)
{ {
*addr = bind_cmd_address ? bind_cmd_address : bind_address; if (family == IPADDR_INET4)
*addr = bind_cmd_address4.family != IPADDR_UNSPEC ? bind_cmd_address4 : bind_address4;
else if (family == IPADDR_INET6)
*addr = bind_cmd_address6.family != IPADDR_UNSPEC ? bind_cmd_address6 : bind_address6;
else
addr->family = IPADDR_UNSPEC;
} }
/* ================================================== */ /* ================================================== */

6
conf.h
View file

@ -31,6 +31,8 @@
#ifndef GOT_CONF_H #ifndef GOT_CONF_H
#define GOT_CONF_H #define GOT_CONF_H
#include "addressing.h"
extern char *CNF_GetRtcDevice(void); extern char *CNF_GetRtcDevice(void);
extern void CNF_ReadFile(const char *filename); extern void CNF_ReadFile(const char *filename);
@ -60,8 +62,8 @@ extern int CNF_GetRTCOnUTC(void);
extern void CNF_GetLogChange(int *enabled, double *threshold); extern void CNF_GetLogChange(int *enabled, double *threshold);
extern void CNF_GetMailOnChange(int *enabled, double *threshold, char **user); extern void CNF_GetMailOnChange(int *enabled, double *threshold, char **user);
extern int CNF_GetNoClientLog(void); extern int CNF_GetNoClientLog(void);
extern void CNF_GetBindAddress(unsigned long *addr); extern void CNF_GetBindAddress(int family, IPAddr *addr);
extern void CNF_GetBindCommandAddress(unsigned long *addr); extern void CNF_GetBindCommandAddress(int family, IPAddr *addr);
extern char *CNF_GetPidFile(void); extern char *CNF_GetPidFile(void);
extern void CNF_GetLinuxHz(int *set, int *hz); extern void CNF_GetLinuxHz(int *set, int *hz);
extern void CNF_GetLinuxFreqScale(int *set, double *freq_scale); extern void CNF_GetLinuxFreqScale(int *set, double *freq_scale);

39
configure vendored
View file

@ -106,6 +106,32 @@ EOF
echo $result echo $result
} }
#}}} #}}}
#{{{ test_for_ipv6
test_for_ipv6 () {
cat >docheck.c <<EOF;
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main(int argc, char **argv) {
struct sockaddr_in6 n;
char p[100];
n.sin6_addr = in6addr_any;
return !inet_ntop(AF_INET6, &n.sin6_addr.s6_addr, p, sizeof(p));
}
EOF
${MYCC} ${MYCFLAGS} -c -o docheck.o docheck.c >/dev/null 2>&1
if [ $? -eq 0 ]
then
result=0
else
result=1
fi
rm -f docheck.c docheck.o
echo $result
}
#}}}
#{{{ usage #{{{ usage
usage () { usage () {
cat <<EOF; cat <<EOF;
@ -134,6 +160,7 @@ For better control, use the options below.
--readline-inc-dir=DIR Specify where readline include directory is --readline-inc-dir=DIR Specify where readline include directory is
--readline-lib-dir=DIR Specify where readline lib directory is --readline-lib-dir=DIR Specify where readline lib directory is
--with-ncurses-library=DIR Specify where ncurses lib directory is --with-ncurses-library=DIR Specify where ncurses lib directory is
--disable-ipv6 Disable IPv6 support
--disable-rtc Don't include RTC even on Linux --disable-rtc Don't include RTC even on Linux
--enable-linuxcaps Enable Linux capabilities support --enable-linuxcaps Enable Linux capabilities support
@ -181,6 +208,7 @@ feat_linuxcaps=0
readline_lib="" readline_lib=""
readline_inc="" readline_inc=""
ncurses_lib="" ncurses_lib=""
feat_ipv6=1
SETINFODIR="" SETINFODIR=""
SETMANDIR="" SETMANDIR=""
@ -218,6 +246,9 @@ do
--disable-rtc) --disable-rtc)
feat_rtc=0 feat_rtc=0
;; ;;
--disable-ipv6)
feat_ipv6=0
;;
--enable-linuxcaps) --enable-linuxcaps)
feat_linuxcaps=1 feat_linuxcaps=1
;; ;;
@ -339,6 +370,14 @@ else
printf "No\n" printf "No\n"
fi fi
printf "Checking for IPv6 support : "
if [ $feat_ipv6 -eq 1 -a `test_for_ipv6` -eq 0 ]; then
printf "Yes\n"
SYSDEFS="${SYSDEFS} -DHAVE_IPV6"
else
printf "No\n"
fi
if [ "x${MYCC}" = "xgcc" ]; then if [ "x${MYCC}" = "xgcc" ]; then
CCWARNFLAGS="-Wmissing-prototypes -Wall" CCWARNFLAGS="-Wmissing-prototypes -Wall"
else else

View file

@ -32,85 +32,134 @@
#include "sysincl.h" #include "sysincl.h"
#include "nameserv.h" #include "nameserv.h"
#include "util.h"
#include <resolv.h> #include <resolv.h>
/* ================================================== */ /* ================================================== */
#define MAXRETRIES 10
static unsigned int retries = 0; static unsigned int retries = 0;
static unsigned long int
Name2IPAddress(const char *name, int retry) DNS_Name2IPAddress(const char *name, IPAddr *addr, int retry)
{ {
struct hostent *host; #ifdef HAVE_IPV6
unsigned char *address0; struct addrinfo hints, *res, *ai;
unsigned long result; int result;
memset(&hints, 0, sizeof (hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_ADDRCONFIG;
try_again: try_again:
host = gethostbyname(name); result = getaddrinfo(name, NULL, &hints, &res);
if (host == NULL) {
if (retry && h_errno == TRY_AGAIN && retries < 10) { if (result) {
if (retry && result == EAI_AGAIN && retries < MAXRETRIES) {
sleep(2 << retries); sleep(2 << retries);
retries++; retries++;
res_init(); res_init();
goto try_again; goto try_again;
} }
result = DNS_Failed_Address; return 0;
} else {
address0 = host->h_addr_list[0];
result = ((((unsigned long)address0[0])<<24) |
(((unsigned long)address0[1])<<16) |
(((unsigned long)address0[2])<<8) |
(((unsigned long)address0[3])));
} }
return result; for (ai = res; !result && ai != NULL; ai = ai->ai_next) {
} switch (ai->ai_family) {
case AF_INET:
/* ================================================== */ addr->family = IPADDR_INET4;
addr->addr.in4 = ntohl(((struct sockaddr_in *)ai->ai_addr)->sin_addr.s_addr);
unsigned long result = 1;
DNS_Name2IPAddress(const char *name) break;
{ #ifdef HAVE_IPV6
return Name2IPAddress(name, 0); case AF_INET6:
} addr->family = IPADDR_INET6;
memcpy(&addr->addr.in6, &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr.s6_addr, sizeof (addr->addr.in6));
/* ================================================== */ result = 1;
break;
unsigned long #endif
DNS_Name2IPAddressRetry(const char *name)
{
return Name2IPAddress(name, 1);
}
/* ================================================== */
const char *
DNS_IPAddress2Name(unsigned long ip_addr)
{
struct hostent *host;
static char buffer[16];
unsigned int a, b, c, d;
uint32_t addr;
addr = htonl(ip_addr);
if (addr == 0UL) {
/* Catch this as a special case that will never resolve to
anything */
strcpy(buffer, "0.0.0.0");
return buffer;
} else {
host = gethostbyaddr((const char *) &addr, sizeof(ip_addr), AF_INET);
if (!host) {
a = (ip_addr >> 24) & 0xff;
b = (ip_addr >> 16) & 0xff;
c = (ip_addr >> 8) & 0xff;
d = (ip_addr) & 0xff;
snprintf(buffer, sizeof(buffer), "%u.%u.%u.%u", a, b, c, d);
return buffer;
} else {
return host->h_name;
} }
} }
freeaddrinfo(res);
return result;
#else
struct hostent *host;
char *address0;
try_again:
host = gethostbyname(name);
if (host == NULL) {
if (retry && h_errno == TRY_AGAIN && retries < MAXRETRIES) {
sleep(2 << retries);
retries++;
res_init();
goto try_again;
}
} else {
addr->family = IPADDR_INET4;
address0 = host->h_addr_list[0];
addr->addr.in4 = ((((unsigned long)address0[0])<<24) |
(((unsigned long)address0[1])<<16) |
(((unsigned long)address0[2])<<8) |
(((unsigned long)address0[3])));
return 1;
}
return 0;
#endif
}
/* ================================================== */
void
DNS_IPAddress2Name(IPAddr *ip_addr, char *name, int len)
{
#ifdef HAVE_IPV6
int result;
struct sockaddr_in in4;
struct sockaddr_in6 in6;
switch (ip_addr->family) {
case IPADDR_INET4:
memset(&in4, 0, sizeof (in4));
in4.sin_family = AF_INET;
in4.sin_addr.s_addr = htonl(ip_addr->addr.in4);
result = getnameinfo((const struct sockaddr *)&in4, sizeof (in4), name, len, NULL, 0, 0);
break;
case IPADDR_INET6:
memset(&in6, 0, sizeof (in6));
in6.sin6_family = AF_INET6;
memcpy(&in6.sin6_addr.s6_addr, ip_addr->addr.in6, sizeof (in6.sin6_addr.s6_addr));
result = getnameinfo((const struct sockaddr *)&in6, sizeof (in6), name, len, NULL, 0, 0);
break;
default:
result = 1;
}
if (result)
snprintf(name, len, "%s", UTI_IPToString(ip_addr));
#else
struct hostent *host;
uint32_t addr;
switch (ip_addr->family) {
case IPADDR_INET4:
addr = htonl(ip_addr->addr.in4);
host = gethostbyaddr((const char *) &addr, sizeof (ip_addr), AF_INET);
break;
#ifdef HAVE_IPV6
case IPADDR_INET6:
host = gethostbyaddr((const void *) ip_addr->addr.in6, sizeof (ip_addr->addr.in6), AF_INET6);
break;
#endif
default:
host = NULL;
}
snprintf(name, len, "%s", host ? host->h_name : UTI_IPToString(ip_addr));
#endif
} }
/* ================================================== */ /* ================================================== */

View file

@ -32,13 +32,11 @@
#ifndef GOT_NAMESERV_H #ifndef GOT_NAMESERV_H
#define GOT_NAMESERV_H #define GOT_NAMESERV_H
static const unsigned long DNS_Failed_Address = 0x0UL; #include "addressing.h"
extern unsigned long DNS_Name2IPAddress(const char *name); extern int DNS_Name2IPAddress(const char *name, IPAddr *addr, int retry);
extern unsigned long DNS_Name2IPAddressRetry(const char *name); extern void DNS_IPAddress2Name(IPAddr *ip_addr, char *name, int len);
const char *DNS_IPAddress2Name(unsigned long ip_addr);
#endif /* GOT_NAMESERV_H */ #endif /* GOT_NAMESERV_H */

View file

@ -319,7 +319,7 @@ create_instance(NTP_Remote_Address *remote_addr, NTP_Mode mode, SourceParameters
result->local_poll = params->minpoll; result->local_poll = params->minpoll;
/* Create a source instance for this NTP source */ /* Create a source instance for this NTP source */
result->source = SRC_CreateNewInstance(remote_addr->ip_addr, SRC_NTP); result->source = SRC_CreateNewInstance(UTI_IPToRefid(&remote_addr->ip_addr), SRC_NTP, &result->remote_addr.ip_addr);
result->local_rx.tv_sec = 0; result->local_rx.tv_sec = 0;
result->local_rx.tv_usec = 0; result->local_rx.tv_usec = 0;
@ -626,7 +626,7 @@ transmit_timeout(void *arg)
#ifdef TRACEON #ifdef TRACEON
LOG(LOGS_INFO, LOGF_NtpCore, "Transmit timeout for [%s:%d]", LOG(LOGS_INFO, LOGF_NtpCore, "Transmit timeout for [%s:%d]",
UTI_IPToDottedQuad(inst->remote_addr.ip_addr), inst->remote_addr.port); UTI_IPToString(&inst->remote_addr.ip_addr), inst->remote_addr.port);
#endif #endif
/* Check whether we need to 'warm up' the link to the other end by /* Check whether we need to 'warm up' the link to the other end by
@ -1043,8 +1043,8 @@ receive_packet(NTP_Packet *message, struct timeval *now, NCR_Instance inst, int
message->lvm, message->stratum, message->poll, message->precision); message->lvm, message->stratum, message->poll, message->precision);
LOG(LOGS_INFO, LOGF_NtpCore, "Root delay=%08lx (%f), dispersion=%08lx (%f)", LOG(LOGS_INFO, LOGF_NtpCore, "Root delay=%08lx (%f), dispersion=%08lx (%f)",
message->root_delay, pkt_root_delay, message->root_dispersion, pkt_root_dispersion); message->root_delay, pkt_root_delay, message->root_dispersion, pkt_root_dispersion);
LOG(LOGS_INFO, LOGF_NtpCore, "Ref id=[%s], ref_time=%08lx.%08lx [%s]", LOG(LOGS_INFO, LOGF_NtpCore, "Ref id=[%lx], ref_time=%08lx.%08lx [%s]",
UTI_IPToDottedQuad(ntohl(message->reference_id)), ntohl(message->reference_id),
message->reference_ts.hi, message->reference_ts.lo, message->reference_ts.hi, message->reference_ts.lo,
UTI_TimestampToString(&message->reference_ts)); UTI_TimestampToString(&message->reference_ts));
LOG(LOGS_INFO, LOGF_NtpCore, "Originate=%08lx.%08lx [%s]", LOG(LOGS_INFO, LOGF_NtpCore, "Originate=%08lx.%08lx [%s]",
@ -1243,7 +1243,7 @@ receive_packet(NTP_Packet *message, struct timeval *now, NCR_Instance inst, int
inst->maxpoll = inst->minpoll; inst->maxpoll = inst->minpoll;
if (inst->minpoll > inst->local_poll) if (inst->minpoll > inst->local_poll)
inst->local_poll = inst->minpoll; inst->local_poll = inst->minpoll;
LOG(LOGS_INFO, LOGF_NtpCore, "Received KoD RATE from %s, minpoll set to %d", UTI_IPToDottedQuad(inst->remote_addr.ip_addr), inst->minpoll); LOG(LOGS_INFO, LOGF_NtpCore, "Received KoD RATE from %s, minpoll set to %d", UTI_IPToString(&inst->remote_addr.ip_addr), inst->minpoll);
} }
/* Back off for a while */ /* Back off for a while */
delay_time += (double) (4 * (1UL << inst->minpoll)); delay_time += (double) (4 * (1UL << inst->minpoll));
@ -1268,7 +1268,7 @@ receive_packet(NTP_Packet *message, struct timeval *now, NCR_Instance inst, int
fprintf(logfile, "%s %-15s %1c %2d %1d%1d%1d%1d %1d%1d %1d%1d%1d%1d %2d %2d %2d %10.3e %10.3e %10.3e %10.3e %10.3e\n", fprintf(logfile, "%s %-15s %1c %2d %1d%1d%1d%1d %1d%1d %1d%1d%1d%1d %2d %2d %2d %10.3e %10.3e %10.3e %10.3e %10.3e\n",
UTI_TimeToLogForm(sample_time.tv_sec), UTI_TimeToLogForm(sample_time.tv_sec),
UTI_IPToDottedQuad(inst->remote_addr.ip_addr), UTI_IPToString(&inst->remote_addr.ip_addr),
sync_stats[pkt_leap], sync_stats[pkt_leap],
message->stratum, message->stratum,
test1, test2, test3, test4, test1, test2, test3, test4,
@ -1357,9 +1357,9 @@ process_known
one of the secondaries to flywheel it. The behaviour coded here one of the secondaries to flywheel it. The behaviour coded here
is required in the secondaries to make this possible. */ is required in the secondaries to make this possible. */
if (ADF_IsAllowed(access_auth_table, inst->remote_addr.ip_addr)) { if (ADF_IsAllowed(access_auth_table, &inst->remote_addr.ip_addr)) {
CLG_LogNTPClientAccess(inst->remote_addr.ip_addr, (time_t) now->tv_sec); CLG_LogNTPClientAccess(&inst->remote_addr.ip_addr, (time_t) now->tv_sec);
if (do_auth) { if (do_auth) {
auth_key_id = ntohl(message->auth_keyid); auth_key_id = ntohl(message->auth_keyid);
@ -1392,7 +1392,7 @@ process_known
} else { } else {
LOG(LOGS_WARN, LOGF_NtpCore, "NTP packet received from unauthorised host %s port %d", LOG(LOGS_WARN, LOGF_NtpCore, "NTP packet received from unauthorised host %s port %d",
UTI_IPToDottedQuad(inst->remote_addr.ip_addr), UTI_IPToString(&inst->remote_addr.ip_addr),
inst->remote_addr.port); inst->remote_addr.port);
} }
@ -1403,7 +1403,7 @@ process_known
switch(inst->mode) { switch(inst->mode) {
case MODE_ACTIVE: case MODE_ACTIVE:
/* Ordinary symmetric peering */ /* Ordinary symmetric peering */
CLG_LogNTPPeerAccess(inst->remote_addr.ip_addr, (time_t) now->tv_sec); CLG_LogNTPPeerAccess(&inst->remote_addr.ip_addr, (time_t) now->tv_sec);
receive_packet(message, now, inst, do_auth); receive_packet(message, now, inst, do_auth);
break; break;
case MODE_PASSIVE: case MODE_PASSIVE:
@ -1413,7 +1413,7 @@ process_known
case MODE_CLIENT: case MODE_CLIENT:
/* This is where we have the remote configured as a server and he has /* This is where we have the remote configured as a server and he has
us configured as a peer - fair enough. */ us configured as a peer - fair enough. */
CLG_LogNTPPeerAccess(inst->remote_addr.ip_addr, (time_t) now->tv_sec); CLG_LogNTPPeerAccess(&inst->remote_addr.ip_addr, (time_t) now->tv_sec);
receive_packet(message, now, inst, do_auth); receive_packet(message, now, inst, do_auth);
break; break;
case MODE_SERVER: case MODE_SERVER:
@ -1434,7 +1434,7 @@ process_known
switch(inst->mode) { switch(inst->mode) {
case MODE_ACTIVE: case MODE_ACTIVE:
/* Slightly bizarre combination, but we can still process it */ /* Slightly bizarre combination, but we can still process it */
CLG_LogNTPPeerAccess(inst->remote_addr.ip_addr, (time_t) now->tv_sec); CLG_LogNTPPeerAccess(&inst->remote_addr.ip_addr, (time_t) now->tv_sec);
receive_packet(message, now, inst, do_auth); receive_packet(message, now, inst, do_auth);
break; break;
case MODE_PASSIVE: case MODE_PASSIVE:
@ -1462,7 +1462,7 @@ process_known
case MODE_ACTIVE: case MODE_ACTIVE:
/* This would arise if we have the remote configured as a peer and /* This would arise if we have the remote configured as a peer and
he does not have us configured */ he does not have us configured */
CLG_LogNTPPeerAccess(inst->remote_addr.ip_addr, (time_t) now->tv_sec); CLG_LogNTPPeerAccess(&inst->remote_addr.ip_addr, (time_t) now->tv_sec);
receive_packet(message, now, inst, do_auth); receive_packet(message, now, inst, do_auth);
break; break;
case MODE_PASSIVE: case MODE_PASSIVE:
@ -1524,19 +1524,19 @@ NCR_ProcessNoauthUnknown(NTP_Packet *message, struct timeval *now, NTP_Remote_Ad
NTP_Mode my_mode; NTP_Mode my_mode;
int my_poll; int my_poll;
if (ADF_IsAllowed(access_auth_table, remote_addr->ip_addr)) { if (ADF_IsAllowed(access_auth_table, &remote_addr->ip_addr)) {
his_mode = message->lvm & 0x07; his_mode = message->lvm & 0x07;
if (his_mode == MODE_CLIENT) { if (his_mode == MODE_CLIENT) {
/* We are server */ /* We are server */
my_mode = MODE_SERVER; my_mode = MODE_SERVER;
CLG_LogNTPClientAccess(remote_addr->ip_addr, (time_t) now->tv_sec); CLG_LogNTPClientAccess(&remote_addr->ip_addr, (time_t) now->tv_sec);
} else if (his_mode == MODE_ACTIVE) { } else if (his_mode == MODE_ACTIVE) {
/* We are symmetric passive, even though we don't ever lock to him */ /* We are symmetric passive, even though we don't ever lock to him */
my_mode = MODE_PASSIVE; my_mode = MODE_PASSIVE;
CLG_LogNTPPeerAccess(remote_addr->ip_addr, (time_t) now->tv_sec); CLG_LogNTPPeerAccess(&remote_addr->ip_addr, (time_t) now->tv_sec);
} else { } else {
my_mode = MODE_UNDEFINED; my_mode = MODE_UNDEFINED;
@ -1560,7 +1560,7 @@ NCR_ProcessNoauthUnknown(NTP_Packet *message, struct timeval *now, NTP_Remote_Ad
} }
} else { } else {
LOG(LOGS_WARN, LOGF_NtpCore, "NTP packet received from unauthorised host %s port %d", LOG(LOGS_WARN, LOGF_NtpCore, "NTP packet received from unauthorised host %s port %d",
UTI_IPToDottedQuad(remote_addr->ip_addr), UTI_IPToString(&remote_addr->ip_addr),
remote_addr->port); remote_addr->port);
} }
@ -1594,19 +1594,19 @@ NCR_ProcessAuthUnknown(NTP_Packet *message, struct timeval *now, NTP_Remote_Addr
int valid_key, valid_auth; int valid_key, valid_auth;
unsigned long key_id; unsigned long key_id;
if (ADF_IsAllowed(access_auth_table, remote_addr->ip_addr)) { if (ADF_IsAllowed(access_auth_table, &remote_addr->ip_addr)) {
his_mode = message->lvm & 0x07; his_mode = message->lvm & 0x07;
if (his_mode == MODE_CLIENT) { if (his_mode == MODE_CLIENT) {
/* We are server */ /* We are server */
my_mode = MODE_SERVER; my_mode = MODE_SERVER;
CLG_LogNTPClientAccess(remote_addr->ip_addr, (time_t) now->tv_sec); CLG_LogNTPClientAccess(&remote_addr->ip_addr, (time_t) now->tv_sec);
} else if (his_mode == MODE_ACTIVE) { } else if (his_mode == MODE_ACTIVE) {
/* We are symmetric passive, even though we don't ever lock to him */ /* We are symmetric passive, even though we don't ever lock to him */
my_mode = MODE_PASSIVE; my_mode = MODE_PASSIVE;
CLG_LogNTPPeerAccess(remote_addr->ip_addr, (time_t) now->tv_sec); CLG_LogNTPPeerAccess(&remote_addr->ip_addr, (time_t) now->tv_sec);
} else { } else {
my_mode = MODE_UNDEFINED; my_mode = MODE_UNDEFINED;
@ -1678,7 +1678,7 @@ NCR_TakeSourceOnline(NCR_Instance inst)
case MD_OFFLINE: case MD_OFFLINE:
if (!inst->timer_running) { if (!inst->timer_running) {
/* We are not already actively polling it */ /* We are not already actively polling it */
LOG(LOGS_INFO, LOGF_NtpCore, "Source %s online", UTI_IPToDottedQuad(inst->remote_addr.ip_addr)); LOG(LOGS_INFO, LOGF_NtpCore, "Source %s online", UTI_IPToString(&inst->remote_addr.ip_addr));
inst->local_poll = inst->minpoll; inst->local_poll = inst->minpoll;
inst->score = (ZONE_WIDTH >> 1); inst->score = (ZONE_WIDTH >> 1);
inst->opmode = MD_ONLINE; inst->opmode = MD_ONLINE;
@ -1702,7 +1702,7 @@ NCR_TakeSourceOffline(NCR_Instance inst)
switch (inst->opmode) { switch (inst->opmode) {
case MD_ONLINE: case MD_ONLINE:
if (inst->timer_running) { if (inst->timer_running) {
LOG(LOGS_INFO, LOGF_NtpCore, "Source %s offline", UTI_IPToDottedQuad(inst->remote_addr.ip_addr)); LOG(LOGS_INFO, LOGF_NtpCore, "Source %s offline", UTI_IPToString(&inst->remote_addr.ip_addr));
SCH_RemoveTimeout(inst->timeout_id); SCH_RemoveTimeout(inst->timeout_id);
inst->timer_running = 0; inst->timer_running = 0;
inst->opmode = MD_OFFLINE; inst->opmode = MD_OFFLINE;
@ -1725,7 +1725,7 @@ void
NCR_ModifyMinpoll(NCR_Instance inst, int new_minpoll) NCR_ModifyMinpoll(NCR_Instance inst, int new_minpoll)
{ {
inst->minpoll = new_minpoll; inst->minpoll = new_minpoll;
LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new minpoll %d", UTI_IPToDottedQuad(inst->remote_addr.ip_addr), new_minpoll); LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new minpoll %d", UTI_IPToString(&inst->remote_addr.ip_addr), new_minpoll);
} }
/* ================================================== */ /* ================================================== */
@ -1734,7 +1734,7 @@ void
NCR_ModifyMaxpoll(NCR_Instance inst, int new_maxpoll) NCR_ModifyMaxpoll(NCR_Instance inst, int new_maxpoll)
{ {
inst->maxpoll = new_maxpoll; inst->maxpoll = new_maxpoll;
LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new maxpoll %d", UTI_IPToDottedQuad(inst->remote_addr.ip_addr), new_maxpoll); LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new maxpoll %d", UTI_IPToString(&inst->remote_addr.ip_addr), new_maxpoll);
} }
/* ================================================== */ /* ================================================== */
@ -1744,7 +1744,7 @@ NCR_ModifyMaxdelay(NCR_Instance inst, double new_max_delay)
{ {
inst->max_delay = new_max_delay; inst->max_delay = new_max_delay;
LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new max delay %f", LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new max delay %f",
UTI_IPToDottedQuad(inst->remote_addr.ip_addr), new_max_delay); UTI_IPToString(&inst->remote_addr.ip_addr), new_max_delay);
} }
/* ================================================== */ /* ================================================== */
@ -1754,7 +1754,7 @@ NCR_ModifyMaxdelayratio(NCR_Instance inst, double new_max_delay_ratio)
{ {
inst->max_delay_ratio = new_max_delay_ratio; inst->max_delay_ratio = new_max_delay_ratio;
LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new max delay ratio %f", LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new max delay ratio %f",
UTI_IPToDottedQuad(inst->remote_addr.ip_addr), new_max_delay_ratio); UTI_IPToString(&inst->remote_addr.ip_addr), new_max_delay_ratio);
} }
/* ================================================== */ /* ================================================== */
@ -1836,7 +1836,7 @@ NCR_ReportSource(NCR_Instance inst, RPT_SourceReport *report, struct timeval *no
/* ================================================== */ /* ================================================== */
int int
NCR_AddAccessRestriction(unsigned long ip_addr, int subnet_bits, int allow, int all) NCR_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all)
{ {
ADF_Status status; ADF_Status status;
@ -1866,7 +1866,7 @@ NCR_AddAccessRestriction(unsigned long ip_addr, int subnet_bits, int allow, int
/* ================================================== */ /* ================================================== */
int int
NCR_CheckAccessRestriction(unsigned long ip_addr) NCR_CheckAccessRestriction(IPAddr *ip_addr)
{ {
return ADF_IsAllowed(access_auth_table, ip_addr); return ADF_IsAllowed(access_auth_table, ip_addr);
} }

View file

@ -94,8 +94,8 @@ extern void NCR_InitiateSampleBurst(NCR_Instance inst, int n_good_samples, int n
extern void NCR_ReportSource(NCR_Instance inst, RPT_SourceReport *report, struct timeval *now); extern void NCR_ReportSource(NCR_Instance inst, RPT_SourceReport *report, struct timeval *now);
extern int NCR_AddAccessRestriction(unsigned long ip_addr, int subnet_bits, int allow, int all); extern int NCR_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all);
extern int NCR_CheckAccessRestriction(unsigned long ip_addr); extern int NCR_CheckAccessRestriction(IPAddr *ip_addr);
extern void NCR_CycleLogFile(void); extern void NCR_CycleLogFile(void);

204
ntp_io.c
View file

@ -41,8 +41,19 @@
#include <fcntl.h> #include <fcntl.h>
/* The file descriptor for the socket */ union sockaddr_in46 {
static int sock_fd; struct sockaddr_in in4;
#ifdef HAVE_IPV6
struct sockaddr_in6 in6;
#endif
struct sockaddr u;
};
/* The file descriptors for the IPv4 and IPv6 sockets */
static int sock_fd4;
#ifdef HAVE_IPV6
static int sock_fd6;
#endif
/* Flag indicating that we have been initialised */ /* Flag indicating that we have been initialised */
static int initialised=0; static int initialised=0;
@ -50,6 +61,7 @@ static int initialised=0;
/* ================================================== */ /* ================================================== */
/* Forward prototypes */ /* Forward prototypes */
static int prepare_socket(int family);
static void read_from_socket(void *anything); static void read_from_socket(void *anything);
/* ================================================== */ /* ================================================== */
@ -81,30 +93,28 @@ do_size_checks(void)
/* ================================================== */ /* ================================================== */
void static int
NIO_Initialise(void) prepare_socket(int family)
{ {
struct sockaddr_in my_addr; union sockaddr_in46 my_addr;
int sock_fd;
unsigned short port_number; unsigned short port_number;
unsigned long bind_address; IPAddr bind_address;
int on_off = 1; int on_off = 1;
assert(!initialised);
initialised = 1;
do_size_checks();
port_number = CNF_GetNTPPort(); port_number = CNF_GetNTPPort();
/* Open Internet domain UDP socket for NTP message transmissions */ /* Open Internet domain UDP socket for NTP message transmissions */
#if 0 #if 0
sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); sock_fd = socket(family, SOCK_DGRAM, IPPROTO_UDP);
#else #else
sock_fd = socket(AF_INET, SOCK_DGRAM, 0); sock_fd = socket(family, SOCK_DGRAM, 0);
#endif #endif
if (sock_fd < 0) { if (sock_fd < 0) {
LOG_FATAL(LOGF_NtpIO, "Could not open socket : %s", strerror(errno)); LOG(LOGS_ERR, LOGF_NtpIO, "Could not open socket : %s", strerror(errno));
return -1;
} }
/* Make the socket capable of re-using an old address */ /* Make the socket capable of re-using an old address */
@ -125,34 +135,67 @@ NIO_Initialise(void)
/* Don't quit - we might survive anyway */ /* Don't quit - we might survive anyway */
} }
/* We want the local IP info too */ if (family == AF_INET) {
if (setsockopt(sock_fd, IPPROTO_IP, IP_PKTINFO, (char *)&on_off, sizeof(on_off)) < 0) { /* We want the local IP info too */
LOG(LOGS_ERR, LOGF_NtpIO, "Could not request packet info using socket option"); if (setsockopt(sock_fd, IPPROTO_IP, IP_PKTINFO, (char *)&on_off, sizeof(on_off)) < 0) {
/* Don't quit - we might survive anyway */ LOG(LOGS_ERR, LOGF_NtpIO, "Could not request packet info using socket option");
/* Don't quit - we might survive anyway */
}
} }
#ifdef HAVE_IPV6
else if (family == AF_INET6) {
#ifdef IPV6_V6ONLY
/* Receive IPv6 packets only */
if (setsockopt(sock_fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on_off, sizeof(on_off)) < 0) {
LOG(LOGS_ERR, LOGF_NtpIO, "Could not request IPV6_V6ONLY socket option");
}
#endif
}
#endif
/* Bind the port */ /* Bind the port */
my_addr.sin_family = AF_INET; memset(&my_addr, 0, sizeof (my_addr));
my_addr.sin_port = htons(port_number);
CNF_GetBindAddress(&bind_address); switch (family) {
case AF_INET:
my_addr.in4.sin_family = family;
my_addr.in4.sin_port = htons(port_number);
if (bind_address != 0UL) { CNF_GetBindAddress(IPADDR_INET4, &bind_address);
my_addr.sin_addr.s_addr = htonl(bind_address);
} else { if (bind_address.family == IPADDR_INET4)
my_addr.sin_addr.s_addr = htonl(INADDR_ANY); my_addr.in4.sin_addr.s_addr = htonl(bind_address.addr.in4);
else
my_addr.in4.sin_addr.s_addr = htonl(INADDR_ANY);
break;
#ifdef HAVE_IPV6
case AF_INET6:
my_addr.in6.sin6_family = family;
my_addr.in6.sin6_port = htons(port_number);
CNF_GetBindAddress(IPADDR_INET6, &bind_address);
if (bind_address.family == IPADDR_INET6)
memcpy(my_addr.in6.sin6_addr.s6_addr, bind_address.addr.in6,
sizeof (my_addr.in6.sin6_addr.s6_addr));
else
my_addr.in6.sin6_addr = in6addr_any;
break;
#endif
default:
assert(0);
} }
#if 0 #if 0
LOG(LOGS_INFO, LOGF_NtpIO, "Initialising, socket fd=%d", sock_fd); LOG(LOGS_INFO, LOGF_NtpIO, "Initialising, socket fd=%d", sock_fd);
#endif #endif
if (bind(sock_fd, (struct sockaddr *) &my_addr, sizeof(my_addr)) < 0) { if (bind(sock_fd, &my_addr.u, sizeof(my_addr)) < 0) {
LOG_FATAL(LOGF_NtpIO, "Could not bind socket : %s", strerror(errno)); LOG_FATAL(LOGF_NtpIO, "Could not bind socket : %s", strerror(errno));
} }
/* Register handler for read events on the socket */ /* Register handler for read events on the socket */
SCH_AddInputFileHandler(sock_fd, read_from_socket, NULL); SCH_AddInputFileHandler(sock_fd, read_from_socket, (void *)(long)sock_fd);
#if 0 #if 0
if (fcntl(sock_fd, F_SETFL, O_NONBLOCK | O_NDELAY) < 0) { if (fcntl(sock_fd, F_SETFL, O_NONBLOCK | O_NDELAY) < 0) {
@ -163,6 +206,29 @@ NIO_Initialise(void)
LOG(LOGS_ERR, LOGF_NtpIO, "Could not enable signal"); LOG(LOGS_ERR, LOGF_NtpIO, "Could not enable signal");
} }
#endif #endif
return sock_fd;
}
void
NIO_Initialise(void)
{
assert(!initialised);
initialised = 1;
do_size_checks();
sock_fd4 = prepare_socket(AF_INET);
#ifdef HAVE_IPV6
sock_fd6 = prepare_socket(AF_INET6);
#endif
if (sock_fd4 < 0
#ifdef HAVE_IPV6
&& sock_fd6 < 0
#endif
) {
LOG_FATAL(LOGF_NtpIO, "Could not open any NTP socket");
}
return; return;
} }
@ -172,11 +238,18 @@ NIO_Initialise(void)
void void
NIO_Finalise(void) NIO_Finalise(void)
{ {
if (sock_fd >= 0) { if (sock_fd4 >= 0) {
SCH_RemoveInputFileHandler(sock_fd); SCH_RemoveInputFileHandler(sock_fd4);
close(sock_fd); close(sock_fd4);
} }
sock_fd = -1; sock_fd4 = -1;
#ifdef HAVE_IPV6
if (sock_fd6 >= 0) {
SCH_RemoveInputFileHandler(sock_fd6);
close(sock_fd6);
}
sock_fd6 = -1;
#endif
initialised = 0; initialised = 0;
return; return;
} }
@ -192,9 +265,9 @@ read_from_socket(void *anything)
/* This should only be called when there is something /* This should only be called when there is something
to read, otherwise it will block. */ to read, otherwise it will block. */
int status; int status, sock_fd;
ReceiveBuffer message; ReceiveBuffer message;
struct sockaddr_in where_from; union sockaddr_in46 where_from;
unsigned int flags = 0; unsigned int flags = 0;
struct timeval now; struct timeval now;
NTP_Remote_Address remote_addr; NTP_Remote_Address remote_addr;
@ -218,6 +291,7 @@ read_from_socket(void *anything)
msg.msg_controllen = sizeof(cmsgbuf); msg.msg_controllen = sizeof(cmsgbuf);
msg.msg_flags = 0; msg.msg_flags = 0;
sock_fd = (long)anything;
status = recvmsg(sock_fd, &msg, flags); status = recvmsg(sock_fd, &msg, flags);
/* Don't bother checking if read failed or why if it did. More /* Don't bother checking if read failed or why if it did. More
@ -228,16 +302,33 @@ read_from_socket(void *anything)
reponse on a subsequent recvfrom). */ reponse on a subsequent recvfrom). */
if (status > 0) { if (status > 0) {
remote_addr.ip_addr = ntohl(where_from.sin_addr.s_addr); memset(&remote_addr, 0, sizeof (remote_addr));
remote_addr.local_ip_addr = 0;
remote_addr.port = ntohs(where_from.sin_port); switch (where_from.u.sa_family) {
case AF_INET:
remote_addr.ip_addr.family = IPADDR_INET4;
remote_addr.ip_addr.addr.in4 = ntohl(where_from.in4.sin_addr.s_addr);
remote_addr.port = ntohs(where_from.in4.sin_port);
break;
#ifdef HAVE_IPV6
case AF_INET6:
remote_addr.ip_addr.family = IPADDR_INET6;
memcpy(&remote_addr.ip_addr.addr.in6, where_from.in6.sin6_addr.s6_addr,
sizeof (remote_addr.ip_addr.addr.in6));
remote_addr.port = ntohs(where_from.in6.sin6_port);
break;
#endif
default:
assert(0);
}
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) { if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) {
struct in_pktinfo ipi; struct in_pktinfo ipi;
memcpy(&ipi, CMSG_DATA(cmsg), sizeof(ipi)); memcpy(&ipi, CMSG_DATA(cmsg), sizeof(ipi));
remote_addr.local_ip_addr = ntohl(ipi.ipi_spec_dst.s_addr); remote_addr.local_ip_addr.addr.in4 = ntohl(ipi.ipi_spec_dst.s_addr);
remote_addr.local_ip_addr.family = IPADDR_INET4;
} }
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_TIMESTAMP) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_TIMESTAMP) {
@ -279,22 +370,43 @@ read_from_socket(void *anything)
static void static void
send_packet(void *packet, int packetlen, NTP_Remote_Address *remote_addr) send_packet(void *packet, int packetlen, NTP_Remote_Address *remote_addr)
{ {
struct sockaddr_in remote; union sockaddr_in46 remote;
struct msghdr msg; struct msghdr msg;
struct iovec iov; struct iovec iov;
struct cmsghdr *cmsg; struct cmsghdr *cmsg;
char cmsgbuf[256]; char cmsgbuf[256];
int cmsglen; int cmsglen;
int sock_fd;
assert(initialised); assert(initialised);
remote.sin_family = AF_INET; memset(&remote, 0, sizeof (remote));
remote.sin_port = htons(remote_addr->port); switch (remote_addr->ip_addr.family) {
remote.sin_addr.s_addr = htonl(remote_addr->ip_addr); case IPADDR_INET4:
remote.in4.sin_family = AF_INET;
remote.in4.sin_port = htons(remote_addr->port);
remote.in4.sin_addr.s_addr = htonl(remote_addr->ip_addr.addr.in4);
sock_fd = sock_fd4;
break;
#ifdef HAVE_IPV6
case IPADDR_INET6:
remote.in6.sin6_family = AF_INET6;
remote.in6.sin6_port = htons(remote_addr->port);
memcpy(&remote.in6.sin6_addr.s6_addr, &remote_addr->ip_addr.addr.in6,
sizeof (remote.in6.sin6_addr.s6_addr));
sock_fd = sock_fd6;
break;
#endif
default:
return;
}
if (sock_fd < 0)
return;
iov.iov_base = packet; iov.iov_base = packet;
iov.iov_len = packetlen; iov.iov_len = packetlen;
msg.msg_name = &remote; msg.msg_name = &remote.u;
msg.msg_namelen = sizeof(remote); msg.msg_namelen = sizeof(remote);
msg.msg_iov = &iov; msg.msg_iov = &iov;
msg.msg_iovlen = 1; msg.msg_iovlen = 1;
@ -303,7 +415,7 @@ send_packet(void *packet, int packetlen, NTP_Remote_Address *remote_addr)
msg.msg_flags = 0; msg.msg_flags = 0;
cmsglen = 0; cmsglen = 0;
if (remote_addr->local_ip_addr) { if (remote_addr->local_ip_addr.family == IPADDR_INET4) {
struct in_pktinfo *ipi; struct in_pktinfo *ipi;
cmsg = CMSG_FIRSTHDR(&msg); cmsg = CMSG_FIRSTHDR(&msg);
@ -315,10 +427,10 @@ send_packet(void *packet, int packetlen, NTP_Remote_Address *remote_addr)
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
ipi = (struct in_pktinfo *) CMSG_DATA(cmsg); ipi = (struct in_pktinfo *) CMSG_DATA(cmsg);
ipi->ipi_spec_dst.s_addr = htonl(remote_addr->local_ip_addr); ipi->ipi_spec_dst.s_addr = htonl(remote_addr->local_ip_addr.addr.in4);
#if 0 #if 0
LOG(LOGS_INFO, LOGF_NtpIO, "sending to %s:%d from %s", LOG(LOGS_INFO, LOGF_NtpIO, "sending to %s:%d from %s",
UTI_IPToDottedQuad(remote_addr->ip_addr), remote_addr->port, UTI_IPToDottedQuad(remote_addr->local_ip_addr)); UTI_IPToString(&remote_addr->ip_addr), remote_addr->port, UTI_IPToString(&remote_addr->local_ip_addr));
#endif #endif
} }
@ -326,7 +438,7 @@ send_packet(void *packet, int packetlen, NTP_Remote_Address *remote_addr)
if (sendmsg(sock_fd, &msg, 0) < 0) { if (sendmsg(sock_fd, &msg, 0) < 0) {
LOG(LOGS_WARN, LOGF_NtpIO, "Could not send to %s:%d : %s", LOG(LOGS_WARN, LOGF_NtpIO, "Could not send to %s:%d : %s",
UTI_IPToDottedQuad(remote_addr->ip_addr), remote_addr->port, strerror(errno)); UTI_IPToString(&remote_addr->ip_addr), remote_addr->port, strerror(errno));
} }
return; return;

View file

@ -120,17 +120,36 @@ static void
find_slot(NTP_Remote_Address *remote_addr, int *slot, int *found) find_slot(NTP_Remote_Address *remote_addr, int *slot, int *found)
{ {
unsigned long hash; unsigned long hash;
unsigned long ip = remote_addr->ip_addr; unsigned long ip;
unsigned short port = remote_addr->port; unsigned short port;
uint8_t *ip6;
assert(N_RECORDS == 256); assert(N_RECORDS == 256);
switch (remote_addr->ip_addr.family) {
case IPADDR_INET6:
ip6 = remote_addr->ip_addr.addr.in6;
ip = (ip6[0] ^ ip6[4] ^ ip6[8] ^ ip6[12]) |
(ip6[1] ^ ip6[5] ^ ip6[9] ^ ip6[13]) << 8 |
(ip6[2] ^ ip6[6] ^ ip6[10] ^ ip6[14]) << 16 |
(ip6[3] ^ ip6[7] ^ ip6[11] ^ ip6[15]) << 24;
break;
case IPADDR_INET4:
ip = remote_addr->ip_addr.addr.in4;
break;
default:
*found = *slot = 0;
return;
}
port = remote_addr->port;
/* Compute hash value just by xor'ing the 4 bytes of the address together */ /* Compute hash value just by xor'ing the 4 bytes of the address together */
hash = ip ^ (ip >> 16); hash = ip ^ (ip >> 16);
hash = (hash ^ (hash >> 8)) & 0xff; hash = (hash ^ (hash >> 8)) & 0xff;
while ((records[hash].in_use) && while ((records[hash].in_use) &&
(records[hash].remote_addr.ip_addr != ip)) { UTI_CompareIPs(&records[hash].remote_addr.ip_addr,
&remote_addr->ip_addr, NULL)) {
hash++; hash++;
if (hash == 256) hash = 0; if (hash == 256) hash = 0;
} }
@ -162,7 +181,7 @@ NSR_AddServer(NTP_Remote_Address *remote_addr, SourceParameters *params)
assert(initialised); assert(initialised);
#if 0 #if 0
LOG(LOGS_INFO, LOGF_NtpSources, "IP=%08lx port=%d", (unsigned long)remote_addr->ip_addr, remote_addr->port); LOG(LOGS_INFO, LOGF_NtpSources, "IP=%s port=%d", UTI_IPToString(&remote_addr->ip_addr), remote_addr->port);
#endif #endif
/* Find empty bin & check that we don't have the address already */ /* Find empty bin & check that we don't have the address already */
@ -172,6 +191,9 @@ NSR_AddServer(NTP_Remote_Address *remote_addr, SourceParameters *params)
} else { } else {
if (n_sources == MAX_SOURCES) { if (n_sources == MAX_SOURCES) {
return NSR_TooManySources; return NSR_TooManySources;
} else if (remote_addr->ip_addr.family != IPADDR_INET4 &&
remote_addr->ip_addr.family != IPADDR_INET6) {
return NSR_InvalidAF;
} else { } else {
n_sources++; n_sources++;
records[slot].remote_addr = *remote_addr; records[slot].remote_addr = *remote_addr;
@ -193,7 +215,7 @@ NSR_AddPeer(NTP_Remote_Address *remote_addr, SourceParameters *params)
assert(initialised); assert(initialised);
#if 0 #if 0
LOG(LOGS_INFO, LOGF_NtpSources, "IP=%08lx port=%d", (unsigned long) remote_addr->ip_addr, remote_addr->port); LOG(LOGS_INFO, LOGF_NtpSources, "IP=%s port=%d", UTI_IPToString(&remote_addr->ip_addr), remote_addr->port);
#endif #endif
/* Find empty bin & check that we don't have the address already */ /* Find empty bin & check that we don't have the address already */
@ -203,6 +225,9 @@ NSR_AddPeer(NTP_Remote_Address *remote_addr, SourceParameters *params)
} else { } else {
if (n_sources == MAX_SOURCES) { if (n_sources == MAX_SOURCES) {
return NSR_TooManySources; return NSR_TooManySources;
} else if (remote_addr->ip_addr.family != IPADDR_INET4 &&
remote_addr->ip_addr.family != IPADDR_INET6) {
return NSR_InvalidAF;
} else { } else {
n_sources++; n_sources++;
records[slot].remote_addr = *remote_addr; records[slot].remote_addr = *remote_addr;
@ -249,7 +274,7 @@ NSR_ProcessReceive(NTP_Packet *message, struct timeval *now, NTP_Remote_Address
#if 0 #if 0
LOG(LOGS_INFO, LOGF_NtpSources, "from (%s,%d) at %s", LOG(LOGS_INFO, LOGF_NtpSources, "from (%s,%d) at %s",
UTI_IPToDottedQuad(remote_addr->ip_addr), UTI_IPToString(&remote_addr->ip_addr),
remote_addr->port, UTI_TimevalToString(now)); remote_addr->port, UTI_TimevalToString(now));
#endif #endif
@ -296,7 +321,7 @@ slew_sources(struct timeval *raw,
if (records[i].in_use) { if (records[i].in_use) {
#if 0 #if 0
LOG(LOGS_INFO, LOGF_Sources, "IP=%s dfreq=%f doff=%f", LOG(LOGS_INFO, LOGF_Sources, "IP=%s dfreq=%f doff=%f",
UTI_IPToDottedQuad(records[i].remote_addr.ip_addr), dfreq, doffset); UTI_IPToString(&records[i].remote_addr.ip_addr), dfreq, doffset);
#endif #endif
NCR_SlewTimes(records[i].data, cooked, dfreq, doffset); NCR_SlewTimes(records[i].data, cooked, dfreq, doffset);
@ -308,17 +333,16 @@ slew_sources(struct timeval *raw,
/* ================================================== */ /* ================================================== */
int int
NSR_TakeSourcesOnline(unsigned long mask, unsigned long address) NSR_TakeSourcesOnline(IPAddr *mask, IPAddr *address)
{ {
int i; int i;
int any; int any;
unsigned long ip;
any = 0; any = 0;
for (i=0; i<N_RECORDS; i++) { for (i=0; i<N_RECORDS; i++) {
if (records[i].in_use) { if (records[i].in_use) {
ip = records[i].remote_addr.ip_addr; if (address->family == IPADDR_UNSPEC ||
if ((ip & mask) == address) { !UTI_CompareIPs(&records[i].remote_addr.ip_addr, address, mask)) {
any = 1; any = 1;
NCR_TakeSourceOnline(records[i].data); NCR_TakeSourceOnline(records[i].data);
} }
@ -331,17 +355,16 @@ NSR_TakeSourcesOnline(unsigned long mask, unsigned long address)
/* ================================================== */ /* ================================================== */
int int
NSR_TakeSourcesOffline(unsigned long mask, unsigned long address) NSR_TakeSourcesOffline(IPAddr *mask, IPAddr *address)
{ {
int i; int i;
int any; int any;
unsigned long ip;
any = 0; any = 0;
for (i=0; i<N_RECORDS; i++) { for (i=0; i<N_RECORDS; i++) {
if (records[i].in_use) { if (records[i].in_use) {
ip = records[i].remote_addr.ip_addr; if (address->family == IPADDR_UNSPEC ||
if ((ip & mask) == address) { !UTI_CompareIPs(&records[i].remote_addr.ip_addr, address, mask)) {
any = 1; any = 1;
NCR_TakeSourceOffline(records[i].data); NCR_TakeSourceOffline(records[i].data);
} }
@ -354,11 +377,11 @@ NSR_TakeSourcesOffline(unsigned long mask, unsigned long address)
/* ================================================== */ /* ================================================== */
int int
NSR_ModifyMinpoll(unsigned long address, int new_minpoll) NSR_ModifyMinpoll(IPAddr *address, int new_minpoll)
{ {
int slot, found; int slot, found;
NTP_Remote_Address addr; NTP_Remote_Address addr;
addr.ip_addr = address; addr.ip_addr = *address;
addr.port = 0; addr.port = 0;
find_slot(&addr, &slot, &found); find_slot(&addr, &slot, &found);
@ -373,11 +396,11 @@ NSR_ModifyMinpoll(unsigned long address, int new_minpoll)
/* ================================================== */ /* ================================================== */
int int
NSR_ModifyMaxpoll(unsigned long address, int new_maxpoll) NSR_ModifyMaxpoll(IPAddr *address, int new_maxpoll)
{ {
int slot, found; int slot, found;
NTP_Remote_Address addr; NTP_Remote_Address addr;
addr.ip_addr = address; addr.ip_addr = *address;
addr.port = 0; addr.port = 0;
find_slot(&addr, &slot, &found); find_slot(&addr, &slot, &found);
@ -392,11 +415,11 @@ NSR_ModifyMaxpoll(unsigned long address, int new_maxpoll)
/* ================================================== */ /* ================================================== */
int int
NSR_ModifyMaxdelay(unsigned long address, double new_max_delay) NSR_ModifyMaxdelay(IPAddr *address, double new_max_delay)
{ {
int slot, found; int slot, found;
NTP_Remote_Address addr; NTP_Remote_Address addr;
addr.ip_addr = address; addr.ip_addr = *address;
addr.port = 0; addr.port = 0;
find_slot(&addr, &slot, &found); find_slot(&addr, &slot, &found);
@ -411,11 +434,11 @@ NSR_ModifyMaxdelay(unsigned long address, double new_max_delay)
/* ================================================== */ /* ================================================== */
int int
NSR_ModifyMaxdelayratio(unsigned long address, double new_max_delay_ratio) NSR_ModifyMaxdelayratio(IPAddr *address, double new_max_delay_ratio)
{ {
int slot, found; int slot, found;
NTP_Remote_Address addr; NTP_Remote_Address addr;
addr.ip_addr = address; addr.ip_addr = *address;
addr.port = 0; addr.port = 0;
find_slot(&addr, &slot, &found); find_slot(&addr, &slot, &found);
@ -431,17 +454,16 @@ NSR_ModifyMaxdelayratio(unsigned long address, double new_max_delay_ratio)
int int
NSR_InitiateSampleBurst(int n_good_samples, int n_total_samples, NSR_InitiateSampleBurst(int n_good_samples, int n_total_samples,
unsigned long mask, unsigned long address) IPAddr *mask, IPAddr *address)
{ {
int i; int i;
int any; int any;
unsigned long ip;
any = 0; any = 0;
for (i=0; i<N_RECORDS; i++) { for (i=0; i<N_RECORDS; i++) {
if (records[i].in_use) { if (records[i].in_use) {
ip = records[i].remote_addr.ip_addr; if (address->family == IPADDR_UNSPEC ||
if ((ip & mask) == address) { !UTI_CompareIPs(&records[i].remote_addr.ip_addr, address, mask)) {
any = 1; any = 1;
NCR_InitiateSampleBurst(records[i].data, n_good_samples, n_total_samples); NCR_InitiateSampleBurst(records[i].data, n_good_samples, n_total_samples);
} }

View file

@ -46,7 +46,8 @@ typedef enum {
NSR_Success, /* Operation successful */ NSR_Success, /* Operation successful */
NSR_NoSuchSource, /* Remove - attempt to remove a source that is not known */ NSR_NoSuchSource, /* Remove - attempt to remove a source that is not known */
NSR_AlreadyInUse, /* AddServer, AddPeer - attempt to add a source that is already known */ NSR_AlreadyInUse, /* AddServer, AddPeer - attempt to add a source that is already known */
NSR_TooManySources /* AddServer, AddPeer - too many sources already present */ NSR_TooManySources, /* AddServer, AddPeer - too many sources already present */
NSR_InvalidAF /* AddServer, AddPeer - attempt to add a source with invalid address family */
} NSR_Status; } NSR_Status;
/* Procedure to add a new server source (to which this machine will be /* Procedure to add a new server source (to which this machine will be
@ -75,22 +76,22 @@ extern void NSR_Finalise(void);
/* This routine is used to indicate that sources whose IP addresses /* This routine is used to indicate that sources whose IP addresses
match a particular subnet should be set online again. Returns a match a particular subnet should be set online again. Returns a
flag indicating whether any hosts matched the address */ flag indicating whether any hosts matched the address */
extern int NSR_TakeSourcesOnline(unsigned long mask, unsigned long address); extern int NSR_TakeSourcesOnline(IPAddr *mask, IPAddr *address);
/* This routine is used to indicate that sources whose IP addresses /* This routine is used to indicate that sources whose IP addresses
match a particular subnet should be set offline. Returns a flag match a particular subnet should be set offline. Returns a flag
indicating whether any hosts matched the address */ indicating whether any hosts matched the address */
extern int NSR_TakeSourcesOffline(unsigned long mask, unsigned long address); extern int NSR_TakeSourcesOffline(IPAddr *mask, IPAddr *address);
extern int NSR_ModifyMinpoll(unsigned long address, int new_minpoll); extern int NSR_ModifyMinpoll(IPAddr *address, int new_minpoll);
extern int NSR_ModifyMaxpoll(unsigned long address, int new_maxpoll); extern int NSR_ModifyMaxpoll(IPAddr *address, int new_maxpoll);
extern int NSR_ModifyMaxdelay(unsigned long address, double new_max_delay); extern int NSR_ModifyMaxdelay(IPAddr *address, double new_max_delay);
extern int NSR_ModifyMaxdelayratio(unsigned long address, double new_max_delay_ratio); extern int NSR_ModifyMaxdelayratio(IPAddr *address, double new_max_delay_ratio);
extern int NSR_InitiateSampleBurst(int n_good_samples, int n_total_samples, unsigned long mask, unsigned long address); extern int NSR_InitiateSampleBurst(int n_good_samples, int n_total_samples, IPAddr *mask, IPAddr *address);
extern void NSR_ReportSource(RPT_SourceReport *report, struct timeval *now); extern void NSR_ReportSource(RPT_SourceReport *report, struct timeval *now);

View file

@ -172,7 +172,7 @@ RCL_StartRefclocks(void)
for (i = 0; i < n_sources; i++) { for (i = 0; i < n_sources; i++) {
RCL_Instance inst = &refclocks[i]; RCL_Instance inst = &refclocks[i];
inst->source = SRC_CreateNewInstance(inst->ref_id, SRC_REFCLOCK); inst->source = SRC_CreateNewInstance(inst->ref_id, SRC_REFCLOCK, NULL);
inst->timeout_id = SCH_AddTimeoutByDelay(0.0, poll_timeout, (void *)inst); inst->timeout_id = SCH_AddTimeoutByDelay(0.0, poll_timeout, (void *)inst);
} }
@ -186,7 +186,8 @@ RCL_ReportSource(RPT_SourceReport *report, struct timeval *now)
int i; int i;
unsigned long ref_id; unsigned long ref_id;
ref_id = report->ip_addr; assert(report->ip_addr.family == IPADDR_INET4);
ref_id = report->ip_addr.addr.in4;
for (i = 0; i < n_sources; i++) { for (i = 0; i < n_sources; i++) {
RCL_Instance inst = &refclocks[i]; RCL_Instance inst = &refclocks[i];

View file

@ -32,11 +32,12 @@
#define GOT_REPORTS_H #define GOT_REPORTS_H
#include "sysincl.h" #include "sysincl.h"
#include "addressing.h"
#define REPORT_INVALID_OFFSET 0x80000000 #define REPORT_INVALID_OFFSET 0x80000000
typedef struct { typedef struct {
unsigned long ip_addr; IPAddr ip_addr;
int stratum; int stratum;
int poll; int poll;
enum {RPT_NTP_CLIENT, RPT_NTP_PEER, RPT_LOCAL_REFERENCE} mode; enum {RPT_NTP_CLIENT, RPT_NTP_PEER, RPT_LOCAL_REFERENCE} mode;
@ -65,7 +66,7 @@ typedef struct {
} RPT_TrackingReport; } RPT_TrackingReport;
typedef struct { typedef struct {
unsigned long ip_addr; IPAddr ip_addr;
unsigned long n_samples; unsigned long n_samples;
unsigned long n_runs; unsigned long n_runs;
unsigned long span_seconds; unsigned long span_seconds;
@ -94,7 +95,7 @@ typedef struct {
} RPT_ClientAccess_Report; } RPT_ClientAccess_Report;
typedef struct { typedef struct {
unsigned long ip_addr; IPAddr ip_addr;
unsigned long client_hits; unsigned long client_hits;
unsigned long peer_hits; unsigned long peer_hits;
unsigned long cmd_hits_auth; unsigned long cmd_hits_auth;

View file

@ -88,6 +88,7 @@ struct SRC_Instance_Record {
unsigned long ref_id; /* The reference ID of this source unsigned long ref_id; /* The reference ID of this source
(i.e. its IP address, NOT the (i.e. its IP address, NOT the
reference _it_ is sync'd to) */ reference _it_ is sync'd to) */
IPAddr *ip_addr; /* Its IP address if NTP source */
/* Flag indicating that we are receiving packets with valid headers /* Flag indicating that we are receiving packets with valid headers
from this source and can use it as a reference */ from this source and can use it as a reference */
@ -160,7 +161,7 @@ void SRC_Finalise(void)
/* Function to create a new instance. This would be called by one of /* Function to create a new instance. This would be called by one of
the individual source-type instance creation routines. */ the individual source-type instance creation routines. */
SRC_Instance SRC_CreateNewInstance(unsigned long ref_id, SRC_Type type) SRC_Instance SRC_CreateNewInstance(unsigned long ref_id, SRC_Type type, IPAddr *addr)
{ {
SRC_Instance result; SRC_Instance result;
@ -189,6 +190,7 @@ SRC_Instance SRC_CreateNewInstance(unsigned long ref_id, SRC_Type type)
result->index = n_sources; result->index = n_sources;
result->leap_status = LEAP_Normal; result->leap_status = LEAP_Normal;
result->ref_id = ref_id; result->ref_id = ref_id;
result->ip_addr = addr;
result->reachable = 0; result->reachable = 0;
result->status = SRC_BAD_STATS; result->status = SRC_BAD_STATS;
result->type = type; result->type = type;
@ -362,7 +364,7 @@ source_to_string(SRC_Instance inst)
{ {
switch (inst->type) { switch (inst->type) {
case SRC_NTP: case SRC_NTP:
return UTI_IPToDottedQuad(inst->ref_id); return UTI_IPToString(inst->ip_addr);
case SRC_REFCLOCK: case SRC_REFCLOCK:
return UTI_RefidToString(inst->ref_id); return UTI_RefidToString(inst->ref_id);
default: default:
@ -912,7 +914,16 @@ SRC_ReportSource(int index, RPT_SourceReport *report, struct timeval *now)
return 0; return 0;
} else { } else {
src = sources[index]; src = sources[index];
report->ip_addr = src->ref_id;
memset(&report->ip_addr, 0, sizeof (report->ip_addr));
if (src->ip_addr)
report->ip_addr = *src->ip_addr;
else {
/* Use refid as an address */
report->ip_addr.addr.in4 = src->ref_id;
report->ip_addr.family = IPADDR_INET4;
}
switch (src->status) { switch (src->status) {
case SRC_SYNC: case SRC_SYNC:
report->state = RPT_SYNC; report->state = RPT_SYNC;
@ -949,7 +960,10 @@ SRC_ReportSourcestats(int index, RPT_SourcestatsReport *report)
return 0; return 0;
} else { } else {
src = sources[index]; src = sources[index];
report->ip_addr = src->ref_id; if (src->ip_addr)
report->ip_addr = *src->ip_addr;
else
report->ip_addr.family = IPADDR_UNSPEC;
SST_DoSourcestatsReport(src->stats, report); SST_DoSourcestatsReport(src->stats, report);
return 1; return 1;
} }

View file

@ -58,7 +58,7 @@ typedef enum {
/* Function to create a new instance. This would be called by one of /* Function to create a new instance. This would be called by one of
the individual source-type instance creation routines. */ the individual source-type instance creation routines. */
extern SRC_Instance SRC_CreateNewInstance(unsigned long ref_id, SRC_Type type); extern SRC_Instance SRC_CreateNewInstance(unsigned long ref_id, SRC_Type type, IPAddr *addr);
/* Function to get rid of a source when it is being unconfigured. /* Function to get rid of a source when it is being unconfigured.
This may cause the current reference source to be reselected, if this This may cause the current reference source to be reselected, if this

View file

@ -79,6 +79,11 @@
#endif #endif
#ifdef HAVE_IPV6
/* For inet_ntop() */
#include <arpa/inet.h>
#endif
#if defined (SOLARIS) || defined(SUNOS) #if defined (SOLARIS) || defined(SUNOS)
/* Only needed on these platforms, and doesn't exist on some Linux /* Only needed on these platforms, and doesn't exist on some Linux
versions. */ versions. */

164
util.c
View file

@ -31,6 +31,7 @@
#include "sysincl.h" #include "sysincl.h"
#include "util.h" #include "util.h"
#include "md5.h"
/* ================================================== */ /* ================================================== */
@ -271,6 +272,169 @@ UTI_IPToDottedQuad(unsigned long ip)
/* ================================================== */ /* ================================================== */
char *
UTI_IPToString(IPAddr *addr)
{
unsigned long a, b, c, d, ip;
uint8_t *ip6;
char *result;
result = NEXT_BUFFER;
switch (addr->family) {
case IPADDR_UNSPEC:
snprintf(result, BUFFER_LENGTH, "[UNSPEC]");
break;
case IPADDR_INET4:
ip = addr->addr.in4;
a = (ip>>24) & 0xff;
b = (ip>>16) & 0xff;
c = (ip>> 8) & 0xff;
d = (ip>> 0) & 0xff;
snprintf(result, BUFFER_LENGTH, "%ld.%ld.%ld.%ld", a, b, c, d);
break;
case IPADDR_INET6:
ip6 = addr->addr.in6;
#ifdef HAVE_IPV6
inet_ntop(AF_INET6, ip6, result, BUFFER_LENGTH);
#else
snprintf(result, BUFFER_LENGTH, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
ip6[0], ip6[1], ip6[2], ip6[3], ip6[4], ip6[5], ip6[6], ip6[7],
ip6[8], ip6[9], ip6[10], ip6[11], ip6[12], ip6[13], ip6[14], ip6[15]);
#endif
break;
default:
snprintf(result, BUFFER_LENGTH, "[UNKNOWN]");
}
return result;
}
/* ================================================== */
int
UTI_StringToIP(const char *addr, IPAddr *ip)
{
#ifdef HAVE_IPV6
struct in_addr in4;
struct in6_addr in6;
if (inet_pton(AF_INET, addr, &in4) > 0) {
ip->family = IPADDR_INET4;
ip->addr.in4 = ntohl(in4.s_addr);
return 1;
}
if (inet_pton(AF_INET6, addr, &in6) > 0) {
ip->family = IPADDR_INET6;
memcpy(ip->addr.in6, in6.s6_addr, sizeof (ip->addr.in6));
return 1;
}
#else
unsigned long a, b, c, d, n;
n = sscanf(addr, "%lu.%lu.%lu.%lu", &a, &b, &c, &d);
if (n == 4) {
ip->family = IPADDR_INET4;
ip->addr.in4 = ((a & 0xff) << 24) | ((b & 0xff) << 16) |
((c & 0xff) << 8) | (d & 0xff);
return 1;
}
#endif
return 0;
}
/* ================================================== */
unsigned long
UTI_IPToRefid(IPAddr *ip)
{
MD5_CTX ctx;
switch (ip->family) {
case IPADDR_INET4:
return ip->addr.in4;
case IPADDR_INET6:
MD5Init(&ctx);
MD5Update(&ctx, (unsigned const char *) ip->addr.in6, sizeof (ip->addr.in6));
MD5Final(&ctx);
return ctx.digest[0] << 24 | ctx.digest[1] << 16 | ctx.digest[2] << 8 | ctx.digest[3];
}
return 0;
}
/* ================================================== */
void
UTI_IPHostToNetwork(IPAddr *src, IPAddr *dest)
{
/* Don't send uninitialized bytes over network */
memset(dest, 0, sizeof (IPAddr));
dest->family = htons(src->family);
switch (src->family) {
case IPADDR_INET4:
dest->addr.in4 = htonl(src->addr.in4);
break;
case IPADDR_INET6:
memcpy(dest->addr.in6, src->addr.in6, sizeof (dest->addr.in6));
break;
}
}
/* ================================================== */
void
UTI_IPNetworkToHost(IPAddr *src, IPAddr *dest)
{
dest->family = ntohs(src->family);
switch (dest->family) {
case IPADDR_INET4:
dest->addr.in4 = ntohl(src->addr.in4);
break;
case IPADDR_INET6:
memcpy(dest->addr.in6, src->addr.in6, sizeof (dest->addr.in6));
break;
}
}
/* ================================================== */
int
UTI_CompareIPs(IPAddr *a, IPAddr *b, IPAddr *mask)
{
int i, d;
if (a->family != b->family)
return a->family - b->family;
if (mask && mask->family != b->family)
mask = NULL;
switch (a->family) {
case IPADDR_UNSPEC:
return 0;
case IPADDR_INET4:
if (mask)
return (a->addr.in4 & mask->addr.in4) - (b->addr.in4 & mask->addr.in4);
else
return a->addr.in4 - b->addr.in4;
case IPADDR_INET6:
for (i = 0, d = 0; !d && i < 16; i++) {
if (mask)
d = (a->addr.in6[i] & mask->addr.in6[i]) -
(b->addr.in6[i] & mask->addr.in6[i]);
else
d = a->addr.in6[i] - b->addr.in6[i];
}
return d;
}
return 0;
}
/* ================================================== */
char * char *
UTI_TimeToLogForm(time_t t) UTI_TimeToLogForm(time_t t)
{ {

10
util.h
View file

@ -33,6 +33,7 @@
#include "sysincl.h" #include "sysincl.h"
#include "addressing.h"
#include "ntp.h" #include "ntp.h"
/* Convert a timeval into a floating point number of seconds */ /* Convert a timeval into a floating point number of seconds */
@ -75,8 +76,15 @@ extern char *UTI_TimestampToString(NTP_int64 *ts);
/* Convert ref_id into a temporary string, for diagnostics */ /* Convert ref_id into a temporary string, for diagnostics */
extern char *UTI_RefidToString(unsigned long ref_id); extern char *UTI_RefidToString(unsigned long ref_id);
/* Convert an IP address to dotted quad notation, for diagnostics */ /* Convert an IP address to string, for diagnostics */
extern char *UTI_IPToDottedQuad(unsigned long ip); extern char *UTI_IPToDottedQuad(unsigned long ip);
extern char *UTI_IPToString(IPAddr *ip);
extern int UTI_StringToIP(const char *addr, IPAddr *ip);
extern unsigned long UTI_IPToRefid(IPAddr *ip);
extern void UTI_IPHostToNetwork(IPAddr *src, IPAddr *dest);
extern void UTI_IPNetworkToHost(IPAddr *src, IPAddr *dest);
extern int UTI_CompareIPs(IPAddr *a, IPAddr *b, IPAddr *mask);
extern char *UTI_TimeToLogForm(time_t t); extern char *UTI_TimeToLogForm(time_t t);