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)
typedef struct { unsigned long ip_addr;
typedef struct {
IPAddr ip_addr; /* Address of the server */
int sanity; /* Flag indicating whether source
looks sane or not */
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 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
initialise_io(void)
static int
prepare_socket(int family)
{
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) {
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
number it gets */
} else {
struct sockaddr_in my_addr;
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(port_number);
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sock_fd, (struct sockaddr *) &my_addr, sizeof(my_addr)) < 0) {
union sockaddr_in46 my_addr;
memset(&my_addr, 0, sizeof (my_addr));
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));
/* 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
finalise_io(void)
{
if (sock_fd >= 0) {
SCH_RemoveInputFileHandler(sock_fd);
close(sock_fd);
if (sock_fd4 >= 0) {
SCH_RemoveInputFileHandler(sock_fd4);
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;
}
@ -195,10 +246,11 @@ probe_source(SourceRecord *src)
NTP_Mode my_mode = MODE_CLIENT;
struct timeval cooked;
double local_time_err;
struct sockaddr_in his_addr;
union sockaddr_in46 his_addr;
int sock_fd;
#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
pkt.lvm = (((LEAP_Unsynchronised << 6) & 0xc0) |
@ -219,18 +271,37 @@ probe_source(SourceRecord *src)
pkt.receive_ts.lo = 0; /* Set to 0 */
/* And do transmission */
his_addr.sin_addr.s_addr = htonl(src->ip_addr);
his_addr.sin_port = htons(123); /* Fixed for now */
his_addr.sin_family = AF_INET;
memset(&his_addr, 0, sizeof (his_addr));
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);
UTI_TimevalToInt64(&cooked, &pkt.transmit_ts);
if (sendto(sock_fd, (void *) &pkt, NTP_NORMAL_PACKET_SIZE,
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",
UTI_IPToDottedQuad(src->ip_addr),
UTI_IPToString(&src->ip_addr),
strerror(errno));
}
@ -253,7 +324,7 @@ transmit_timeout(void *x)
src->timer_running = 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
if (src->n_dead_probes < MAX_DEAD_PROBES) {
@ -357,11 +428,12 @@ read_from_socket(void *anything)
{
int status;
ReceiveBuffer msg;
struct sockaddr_in his_addr;
union sockaddr_in46 his_addr;
int sock_fd;
socklen_t his_addr_len;
int flags;
int message_length;
unsigned long remote_ip;
IPAddr remote_ip;
int i, ok;
struct timeval now;
double local_time_err;
@ -374,24 +446,39 @@ read_from_socket(void *anything)
/* Get timestamp */
LCL_ReadCookedTime(&now, &local_time_err);
sock_fd = (long)anything;
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) {
LOG(LOGS_WARN, LOGF_Acquire, "Error reading from socket, %s", strerror(errno));
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
printf("Got message from %08lx\n", remote_ip);
printf("Got message from %s\n", UTI_IPToString(&remote_ip));
#endif
/* Find matching host */
ok = 0;
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;
break;
}
@ -418,7 +505,7 @@ read_from_socket(void *anything)
(src->n_total_samples >= MAX_SAMPLES)) {
++n_completed_sources;
#if 0
printf("Source %08lx completed\n", src->ip_addr);
printf("Source %s completed\n", UTI_IPToString(&src->ip_addr));
#endif
if (n_completed_sources == n_sources) {
wind_up_acquisition();
@ -440,7 +527,7 @@ start_next_source(void)
{
probe_source(sources + n_started_sources);
#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
n_started_sources++;
@ -552,10 +639,10 @@ process_measurements(void)
for (i=0; i<2*n_sane_sources; i++) {
#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].index,
sources[eps[i].index].ip_addr,
UTI_IPToString(&sources[eps[i].index].ip_addr),
eps[i].offset);
#endif
@ -655,10 +742,10 @@ start_source_timeout_handler(void *not_used)
/* ================================================== */
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_anything = anything;
@ -670,14 +757,18 @@ ACQ_StartAcquisition(int n, unsigned long *ip_addrs, int threshold, void (*after
n_sources = 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].n_samples = 0;
sources[i].n_total_samples = 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_next_source();

View file

@ -31,13 +31,15 @@
#ifndef GOT_ACQUIRE_H
#define GOT_ACQUIRE_H
#include "addressing.h"
typedef struct ACQ_SourceRecord *ACQ_Source;
extern void ACQ_Initialise(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);
extern void ACQ_AccumulateSample(ACQ_Source acq_source, double offset, double root_distance);

View file

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

View file

@ -51,23 +51,35 @@ typedef struct _TableNode {
} TableNode;
struct ADF_AuthTableInst {
TableNode base;
TableNode base4; /* IPv4 node */
TableNode base6; /* IPv6 node */
};
/* ================================================== */
inline static unsigned long
get_subnet(unsigned long addr)
static void
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
get_residual(unsigned long addr)
inline static uint32_t
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);
/* Default is that nothing is allowed */
result->base.state = DENY;
result->base.extended = NULL;
result->base4.state = DENY;
result->base4.extended = NULL;
result->base6.state = DENY;
result->base6.extended = NULL;
return result;
}
@ -135,22 +149,22 @@ open_node(TableNode *node)
static ADF_Status
set_subnet(TableNode *start_node,
unsigned long ip,
uint32_t *ip,
int ip_len,
int subnet_bits,
State new_state,
int delete_children)
{
int bits_to_go;
unsigned long residual;
unsigned long subnet;
int bits_to_go, bits_consumed;
uint32_t subnet;
TableNode *node;
bits_consumed = 0;
bits_to_go = subnet_bits;
residual = ip;
node = start_node;
if ((subnet_bits < 0) ||
(subnet_bits > 32)) {
(subnet_bits > 32 * ip_len)) {
return ADF_BADSUBNET;
@ -159,13 +173,13 @@ set_subnet(TableNode *start_node,
if ((bits_to_go & (NBITS-1)) == 0) {
while (bits_to_go > 0) {
subnet = get_subnet(residual);
residual = get_residual(residual);
subnet = get_subnet(ip, bits_consumed);
if (!(node->extended)) {
open_node(node);
}
node = &(node->extended[subnet]);
bits_to_go -= NBITS;
bits_consumed += NBITS;
}
if (delete_children) {
@ -178,18 +192,18 @@ set_subnet(TableNode *start_node,
TableNode *this_node;
while (bits_to_go >= NBITS) {
subnet = get_subnet(residual);
residual = get_residual(residual);
subnet = get_subnet(ip, bits_consumed);
if (!(node->extended)) {
open_node(node);
}
node = &(node->extended[subnet]);
bits_to_go -= NBITS;
bits_consumed += NBITS;
}
/* How many subnet entries to set : 1->8, 2->4, 3->2 */
N = 1 << (NBITS-bits_to_go);
subnet = get_subnet(residual);
subnet = get_subnet(ip, bits_consumed);
if (!(node->extended)) {
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_Allow(ADF_AuthTable table,
unsigned long ip,
IPAddr *ip,
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_AllowAll(ADF_AuthTable table,
unsigned long ip,
IPAddr *ip,
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_Deny(ADF_AuthTable table,
unsigned long ip,
IPAddr *ip,
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_DenyAll(ADF_AuthTable table,
unsigned long ip,
IPAddr *ip,
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
ADF_DestroyTable(ADF_AuthTable table)
{
close_node(&(table->base));
close_node(&table->base4);
close_node(&table->base6);
Free(table);
}
/* ================================================== */
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 finished = 0;
TableNode *node;
State state=DENY;
node = start_node;
residual = ip;
do {
if (node->state != AS_PARENT) {
state = node->state;
}
if (node->extended) {
subnet = get_subnet(residual);
residual = get_residual(residual);
subnet = get_subnet(ip, bits_consumed);
node = &(node->extended[subnet]);
bits_consumed += NBITS;
} else {
/* Make decision on this node */
finished = 1;
@ -306,38 +350,63 @@ check_ip_in_node(TableNode *start_node, unsigned long ip)
int
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
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;
TableNode *sub_node;
for (i=0; i<subnet_bits; i++) putchar(' ');
printf("%d.%d.%d.%d/%d : %s\n",
((addr >> 24) & 255),
((addr >> 16) & 255),
((addr >> 8) & 255),
((addr ) & 255),
if (ip_len == 1)
printf("%d.%d.%d.%d",
((addr[0] >> 24) & 255),
((addr[0] >> 16) & 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,
(node->state == ALLOW) ? "allow" :
(node->state == DENY) ? "deny" : "as parent");
if (node->extended) {
for (i=0; i<16; i++) {
sub_node = &((*(node->extended))[i]);
new_addr = addr | ((unsigned long) i << shift);
print_node(sub_node, new_addr, shift - 4, subnet_bits + 4);
sub_node = &(node->extended[i]);
new_addr[0] = addr[0];
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;
@ -346,11 +415,15 @@ static void print_node(TableNode *node, unsigned long addr, int shift, int subne
static void print_table(ADF_AuthTable table)
{
unsigned long addr = 0;
int shift = 28;
int subnet_bits = 0;
uint32_t addr[4];
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;
}
@ -358,13 +431,41 @@ static void print_table(ADF_AuthTable table)
int main (int argc, char **argv)
{
IPAddr ip;
ADF_AuthTable table;
table = ADF_CreateTable();
ADF_Allow(table, 0x7e800000, 9);
ADF_Deny(table, 0x7ecc0000, 14);
/* ADF_Deny(table, 0x7f000001, 32); */
/* ADF_Allow(table, 0x7f000000, 8); */
ip.family = IPADDR_INET4;
ip.addr.in4 = 0x7e800000;
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);

View file

@ -31,6 +31,8 @@
#ifndef GOT_ADDRFILT_H
#define GOT_ADDRFILT_H
#include "addressing.h"
typedef struct ADF_AuthTableInst *ADF_AuthTable;
typedef enum {
@ -45,25 +47,25 @@ extern ADF_AuthTable ADF_CreateTable(void);
/* Allow anything in the supplied subnet, EXCEPT for any more specific
subnets that are already defined */
extern ADF_Status ADF_Allow(ADF_AuthTable table,
unsigned long ip,
IPAddr *ip,
int subnet_bits);
/* Allow anything in the supplied subnet, overwriting existing
definitions for any more specific subnets */
extern ADF_Status ADF_AllowAll(ADF_AuthTable table,
unsigned long ip,
IPAddr *ip,
int subnet_bits);
/* Deny anything in the supplied subnet, EXCEPT for any more specific
subnets that are already defined */
extern ADF_Status ADF_Deny(ADF_AuthTable table,
unsigned long ip,
IPAddr *ip,
int subnet_bits);
/* Deny anything in the supplied subnet, overwriting existing
definitions for any more specific subnets */
extern ADF_Status ADF_DenyAll(ADF_AuthTable table,
unsigned long ip,
IPAddr *ip,
int subnet_bits);
/* 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
the table */
extern int ADF_IsAllowed(ADF_AuthTable table,
unsigned long ip);
IPAddr *ip);
#endif /* GOT_ADDRFILT_H */

View file

@ -132,7 +132,7 @@ timeout_handler(void *arbitrary)
/* ================================================== */
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) {
/* 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.local_ip_addr = 0;
destinations[n_destinations].addr.ip_addr = *addr;
destinations[n_destinations].addr.local_ip_addr.family = IPADDR_UNSPEC;
destinations[n_destinations].addr.port = port;
destinations[n_destinations].interval = interval;

View file

@ -31,9 +31,11 @@
#ifndef GOT_BROADCAST_H
#define GOT_BROADCAST_H
#include "addressing.h"
extern void BRD_Initialise(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 */

48
candm.h
View file

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

414
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;
struct sockaddr_in his_addr;
union sockaddr_in46 his_addr;
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 */
static void
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) {
perror("Can't create socket");
exit(1);
}
my_addr.sin_family = AF_INET;
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) {
if(bind(sock_fd, &my_addr.u, sizeof(my_addr)) < 0) {
perror("Can't bind socket");
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;
}
@ -208,34 +218,78 @@ close_io(void)
/* ================================================== */
static int
read_mask_address(char *line, unsigned long *mask, unsigned long *address)
static void
bits_to_mask(int bits, int family, IPAddr *mask)
{
unsigned int ma, mb, mc, md, aa, ab, ac, ad;
int ok = 0;
char *p;
int i;
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;
while (*p && isspace((unsigned char)*p)) p++;
if (!*p) {
*mask = *address = 0;
ok = 1;
mask->family = address->family = IPADDR_UNSPEC;
return 1;
} else {
if (sscanf(line, "%u.%u.%u.%u/%u.%u.%u.%u",
&ma, &mb, &mc, &md,
&aa, &ab, &ac, &ad) != 8) {
fprintf(stderr, "Invalid syntax for mask/address\n");
ok = 0;
q = strchr(p, '/');
if (q) {
*q++ = 0;
if (UTI_StringToIP(p, mask)) {
p = q;
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 {
*mask = (ma << 24) | (mb << 16) | (mc << 8) | md;
*address = (aa << 24) | (ab << 16) | (ac << 8) | ad;
ok = 1;
if (UTI_StringToIP(p, address)) {
bits_to_mask(-1, address->family, mask);
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
process_cmd_offline(CMD_Request *msg, char *line)
{
unsigned long mask, address;
IPAddr mask, address;
int ok;
if (read_mask_address(line, &mask, &address)) {
msg->data.offline.mask = htonl(mask);
msg->data.offline.address = htonl(address);
UTI_IPHostToNetwork(&mask, &msg->data.offline.mask);
UTI_IPHostToNetwork(&address, &msg->data.offline.address);
msg->command = htons(REQ_OFFLINE);
ok = 1;
} else {
@ -265,12 +319,12 @@ process_cmd_offline(CMD_Request *msg, char *line)
static int
process_cmd_online(CMD_Request *msg, char *line)
{
unsigned long mask, address;
IPAddr mask, address;
int ok;
if (read_mask_address(line, &mask, &address)) {
msg->data.online.mask = htonl(mask);
msg->data.online.address = htonl(address);
UTI_IPHostToNetwork(&mask, &msg->data.online.mask);
UTI_IPHostToNetwork(&address, &msg->data.online.address);
msg->command = htons(REQ_ONLINE);
ok = 1;
} else {
@ -284,7 +338,7 @@ process_cmd_online(CMD_Request *msg, char *line)
/* ================================================== */
static int
read_address_integer(char *line, unsigned long *address, int *value)
read_address_integer(char *line, IPAddr *address, int *value)
{
char hostname[2048];
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");
ok = 0;
} else {
*address = DNS_Name2IPAddress(hostname);
if (*address == DNS_Failed_Address) {
if (!DNS_Name2IPAddress(hostname, address, 0)) {
fprintf(stderr, "Could not get address for hostname\n");
ok = 0;
} else {
@ -310,7 +363,7 @@ read_address_integer(char *line, unsigned long *address, int *value)
/* ================================================== */
static int
read_address_double(char *line, unsigned long *address, double *value)
read_address_double(char *line, IPAddr *address, double *value)
{
char hostname[2048];
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");
ok = 0;
} else {
*address = DNS_Name2IPAddress(hostname);
if (*address == DNS_Failed_Address) {
if (!DNS_Name2IPAddress(hostname, address, 0)) {
fprintf(stderr, "Could not get address for hostname\n");
ok = 0;
} else {
@ -338,12 +390,12 @@ read_address_double(char *line, unsigned long *address, double *value)
static int
process_cmd_minpoll(CMD_Request *msg, char *line)
{
unsigned long address;
IPAddr address;
int minpoll;
int ok;
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->command = htons(REQ_MODIFY_MINPOLL);
ok = 1;
@ -360,12 +412,12 @@ process_cmd_minpoll(CMD_Request *msg, char *line)
static int
process_cmd_maxpoll(CMD_Request *msg, char *line)
{
unsigned long address;
IPAddr address;
int maxpoll;
int ok;
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->command = htons(REQ_MODIFY_MAXPOLL);
ok = 1;
@ -382,12 +434,12 @@ process_cmd_maxpoll(CMD_Request *msg, char *line)
static int
process_cmd_maxdelay(CMD_Request *msg, char *line)
{
unsigned long address;
IPAddr address;
double max_delay;
int ok;
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->command = htons(REQ_MODIFY_MAXDELAY);
ok = 1;
@ -404,12 +456,12 @@ process_cmd_maxdelay(CMD_Request *msg, char *line)
static int
process_cmd_maxdelayratio(CMD_Request *msg, char *line)
{
unsigned long address;
IPAddr address;
double max_delay_ratio;
int ok;
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->command = htons(REQ_MODIFY_MAXDELAYRATIO);
ok = 1;
@ -478,36 +530,28 @@ process_cmd_cyclelogs(CMD_Request *msg, char *line)
static int
process_cmd_burst(CMD_Request *msg, char *line)
{
int ok;
int n_good_samples, n_total_samples;
unsigned int ma, mb, mc, md, aa, ab, ac, ad;
int n_parsed;
char s[101];
IPAddr address, mask;
n_parsed = sscanf(line, "%d/%d %u.%u.%u.%u/%u.%u.%u.%u",
&n_good_samples,
&n_total_samples,
&ma, &mb, &mc, &md,
&aa, &ab, &ac, &ad);
n_parsed = sscanf(line, "%d/%d %100s", &n_good_samples, &n_total_samples, s);
msg->command = htons(REQ_BURST);
msg->data.burst.n_good_samples = ntohl(n_good_samples);
msg->data.burst.n_total_samples = ntohl(n_total_samples);
if (n_parsed == 10) {
msg->data.burst.mask = htonl((ma << 24) | (mb << 16) | (mc << 8) | md);
msg->data.burst.address = htonl((aa << 24) | (ab << 16) | (ac << 8) | ad);
ok = 1;
} else if (n_parsed == 2) {
msg->data.burst.mask = 0;
msg->data.burst.address = 0;
ok = 1;
} else {
ok = 0;
mask.family = address.family = IPADDR_UNSPEC;
if (n_parsed < 2 || (n_parsed == 3 && !read_mask_address(s, &mask, &address))) {
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
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;
p = line;
while (*p && isspace((unsigned char)*p)) p++;
if (!*p) {
/* 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);
} else {
char *slashpos;
slashpos = strchr(p, '/');
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 */
q = p;
while (*q) {
if (*q == '\n') *q = 0;
q++;
}
ip = DNS_Name2IPAddress(p);
if (ip == DNS_Failed_Address) {
if (!DNS_Name2IPAddress(p, &ip, 0)) {
fprintf(stderr, "Could not read address\n");
return 0;
} else {
msg->data.allow_deny.ip = htonl(ip);
msg->data.allow_deny.subnet_bits = htonl(32);
UTI_IPHostToNetwork(&ip, &msg->data.allow_deny.ip);
if (ip.family == IPADDR_INET6)
msg->data.allow_deny.subnet_bits = htonl(128);
else
msg->data.allow_deny.subnet_bits = htonl(32);
}
} else {
a &= 0xff;
b &= 0xff;
c &= 0xff;
d &= 0xff;
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);
if (n == 0) {
if (ip.family == IPADDR_INET6)
msg->data.allow_deny.subnet_bits = htonl(128);
else
msg->data.allow_deny.subnet_bits = htonl(32);
break;
default:
assert(0);
} else {
ip.family = IPADDR_INET4;
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) {
int specified_subnet_bits, n;
n = sscanf(slashpos+1, "%d", &specified_subnet_bits);
@ -739,9 +798,10 @@ process_cmd_cmddenyall(CMD_Request *msg, char *line)
/* ================================================== */
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;
p = line;
while (*p && isspace(*p)) p++;
@ -749,7 +809,8 @@ accheck_getaddr(char *line, unsigned long *addr)
return 0;
} else {
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;
} else {
q = p;
@ -757,8 +818,7 @@ accheck_getaddr(char *line, unsigned long *addr)
if (*q == '\n') *q = 0;
q++;
}
ip = DNS_Name2IPAddress(p);
if (ip == DNS_Failed_Address) {
if (!DNS_Name2IPAddress(p, &ip, 0)) {
return 0;
} else {
*addr = ip;
@ -773,10 +833,10 @@ accheck_getaddr(char *line, unsigned long *addr)
static int
process_cmd_accheck(CMD_Request *msg, char *line)
{
unsigned long ip;
IPAddr ip;
msg->command = htons(REQ_ACCHECK);
if (accheck_getaddr(line, &ip)) {
msg->data.ac_check.ip = htonl(ip);
UTI_IPHostToNetwork(&ip, &msg->data.ac_check.ip);
return 1;
} else {
fprintf(stderr, "Could not read address\n");
@ -789,10 +849,10 @@ process_cmd_accheck(CMD_Request *msg, char *line)
static int
process_cmd_cmdaccheck(CMD_Request *msg, char *line)
{
unsigned long ip;
IPAddr ip;
msg->command = htons(REQ_CMDACCHECK);
if (accheck_getaddr(line, &ip)) {
msg->data.ac_check.ip = htonl(ip);
UTI_IPHostToNetwork(&ip, &msg->data.ac_check.ip);
return 1;
} else {
fprintf(stderr, "Could not read address\n");
@ -866,7 +926,7 @@ process_cmd_add_server_or_peer(CMD_Request *msg, char *line)
switch (status) {
case CPS_Success:
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.maxpoll = htonl(data.params.maxpoll);
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];
int ok = 0;
unsigned long address = 0UL;
IPAddr address;
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");
ok = 0;
} else {
address = DNS_Name2IPAddress(hostname);
if (address == DNS_Failed_Address) {
if (!DNS_Name2IPAddress(hostname, &address, 0)) {
fprintf(stderr, "Could not get address for hostname\n");
ok = 0;
} 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;
@ -1121,7 +1180,7 @@ submit_request(CMD_Request *request, CMD_Reply *reply, int *reply_auth_ok)
{
unsigned long tx_sequence;
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 select_status;
int recvfrom_status;
@ -1168,7 +1227,7 @@ submit_request(CMD_Request *request, CMD_Reply *reply, int *reply_auth_ok)
#endif
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
@ -1210,7 +1269,7 @@ submit_request(CMD_Request *request, CMD_Reply *reply, int *reply_auth_ok)
where_from_len = sizeof(where_from);
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
@ -1231,8 +1290,17 @@ submit_request(CMD_Request *request, CMD_Reply *reply, int *reply_auth_ok)
expected_length = PKL_ReplyLength(reply);
bad_length = (read_length != expected_length);
bad_sender = ((where_from.sin_addr.s_addr != his_addr.sin_addr.s_addr) ||
(where_from.sin_port != his_addr.sin_port));
bad_sender = (where_from.u.sa_family != his_addr.u.sa_family ||
(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) {
bad_sequence = (ntohl(reply->sequence) != tx_sequence);
@ -1382,13 +1450,12 @@ process_cmd_sources(char *line)
int verbose = 0;
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_ago;
uint16_t poll, stratum;
uint16_t state, mode;
double resid_freq, resid_skew;
const char *dns_lookup;
char hostname_buf[32];
uint16_t status;
@ -1439,7 +1506,7 @@ process_cmd_sources(char *line)
if (submit_ok) {
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);
stratum = ntohs(reply.data.source_data.stratum);
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_skew = (double) (ntohl(reply.data.source_data.resid_skew)) * 1.0e-3;
hostname_buf[25] = 0;
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) {
snprintf(hostname_buf, sizeof(hostname_buf), "%s", UTI_IPToDottedQuad(ip_addr));
snprintf(hostname_buf, sizeof(hostname_buf), "%s", UTI_IPToString(&ip_addr));
} else {
dns_lookup = DNS_IPAddress2Name(ip_addr);
strncpy(hostname_buf, dns_lookup, 25);
DNS_IPAddress2Name(&ip_addr, hostname_buf, sizeof(hostname_buf));
hostname_buf[25] = 0;
}
switch (mode) {
@ -1515,12 +1581,11 @@ process_cmd_sourcestats(char *line)
int n_sources, i;
int verbose = 0;
const char *dns_lookup;
char hostname_buf[32];
unsigned long n_samples, n_runs, span_seconds;
double resid_freq_ppm, skew_ppm;
unsigned long sd_us;
unsigned long ip_addr;
IPAddr ip_addr;
unsigned short status;
verbose = check_for_verbose_flag(line);
@ -1569,7 +1634,7 @@ process_cmd_sourcestats(char *line)
if (submit_ok) {
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_runs = ntohl(reply.data.sourcestats.n_runs);
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);
sd_us = ntohl(reply.data.sourcestats.sd_us);
hostname_buf[25] = 0;
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 {
dns_lookup = DNS_IPAddress2Name(ip_addr);
strncpy(hostname_buf, dns_lookup, 25);
DNS_IPAddress2Name(&ip_addr, hostname_buf, sizeof(hostname_buf));
hostname_buf[25] = 0;
}
printf("%-25s %2lu %2lu ", hostname_buf, n_samples, n_runs);
@ -1644,9 +1708,10 @@ process_cmd_tracking(char *line)
b = (ref_id >> 16) & 0xff;
c = (ref_id >> 8) & 0xff;
d = (ref_id) & 0xff;
printf("Reference ID : %lu.%lu.%lu.%lu (%s)\n",
a, b, c, d,
(no_dns) ? UTI_IPToDottedQuad(ref_id) : DNS_IPAddress2Name(ref_id));
a, b, c, d, "");
//* TODO (no_dns) ? UTI_IPToDottedQuad(ref_id) : DNS_IPAddress2Name(ref_id)); */
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_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_cmd_hit_ago;
char hostname_buf[32];
const char *dns_lookup;
int n_replies;
@ -1922,9 +1986,8 @@ process_cmd_clients(char *line)
snprintf(hostname_buf, sizeof(hostname_buf),
"%s", UTI_IPToDottedQuad(ip));
} else {
dns_lookup = DNS_IPAddress2Name(ip);
DNS_IPAddress2Name(ip, hostname_buf, sizeof(hostname_buf));
hostname_buf[25] = 0;
strncpy(hostname_buf, dns_lookup, 25);
}
printf("%-25s %6d %6d %6d %6d %6d ",
hostname_buf,
@ -1988,7 +2051,7 @@ process_cmd_clients(char *line)
int status;
unsigned long next_index;
int j;
unsigned long ip;
IPAddr ip;
unsigned long client_hits;
unsigned long peer_hits;
unsigned long cmd_hits_auth;
@ -1997,7 +2060,6 @@ process_cmd_clients(char *line)
unsigned long last_ntp_hit_ago;
unsigned long last_cmd_hit_ago;
char hostname_buf[32];
const char *dns_lookup;
int n_replies;
int n_indices_in_table;
@ -2025,9 +2087,9 @@ process_cmd_clients(char *line)
goto finished;
}
for (j=0; j<n_replies; j++) {
ip = ntohl(reply.data.client_accesses_by_index.clients[j].ip);
if (ip != 0UL) {
/* ip == 0 implies that the node could not be found in
UTI_IPNetworkToHost(&reply.data.client_accesses_by_index.clients[j].ip, &ip);
if (ip.family != IPADDR_UNSPEC) {
/* UNSPEC implies that the node could not be found in
the daemon's tables; we shouldn't ever generate this
case, but ignore it if we do. (In future there might
be a protocol to reset the client logging; if another
@ -2045,11 +2107,10 @@ process_cmd_clients(char *line)
if (no_dns) {
snprintf(hostname_buf, sizeof(hostname_buf),
"%s", UTI_IPToDottedQuad(ip));
"%s", UTI_IPToString(&ip));
} else {
dns_lookup = DNS_IPAddress2Name(ip);
DNS_IPAddress2Name(&ip, hostname_buf, sizeof(hostname_buf));
hostname_buf[25] = 0;
strncpy(hostname_buf, dns_lookup, 25);
}
printf("%-25s %6ld %6ld %6ld %6ld %6ld ",
hostname_buf,
@ -2475,6 +2536,9 @@ process_line(char *line)
case STT_BADRTCFILE:
printf("514 Can't write RTC parameters");
break;
case STT_INVALIDAF:
printf("515 Invalid address family");
break;
}
if (reply_auth_ok) {

View file

@ -53,7 +53,7 @@
#define TABLE_SIZE (1UL<<NBITS)
typedef struct _Node {
unsigned long ip_addr;
IPAddr ip_addr;
unsigned long client_hits;
unsigned long peer_hits;
unsigned long cmd_hits_bad;
@ -69,8 +69,10 @@ typedef struct _Subnet {
/* ================================================== */
/* Table for the class A subnet */
static Subnet top_subnet;
/* Table for the IPv4 class A subnet */
static Subnet top_subnet4;
/* Table for IPv6 */
static Subnet top_subnet6;
/* Table containing pointers directly to all nodes that have been
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
clear_subnet(Subnet *subnet)
{
@ -118,7 +148,8 @@ clear_node(Node *node)
void
CLG_Initialise(void)
{
clear_subnet(&top_subnet);
clear_subnet(&top_subnet4);
clear_subnet(&top_subnet6);
if (CNF_GetNoClientLog()) {
active = 0;
} else {
@ -178,27 +209,18 @@ create_node(Subnet *parent_subnet, int the_entry)
expanding subnet tables and node entries as we go if necessary. */
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;
unsigned long new_bits_left;
uint32_t this_subnet;
shift = 32 - NBITS;
mask = (1UL<<shift) - 1;
this_subnet = addr >> shift;
new_subnet = (addr & mask) << NBITS;
new_bits_left = bits_left - NBITS;
this_subnet = get_subnet(addr, bits_consumed);
bits_consumed += NBITS;
#if 0
fprintf(stderr, "fs addr=%08lx bl=%d ma=%08lx this=%08lx newsn=%08lx nbl=%d\n",
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]) {
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 {
if (!subnet->entry[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 */
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;
unsigned long new_bits_left;
uint32_t this_subnet;
if (bits_left == 0) {
if (bits_consumed >= 32 * addr_len) {
return subnet;
} else {
shift = 32 - NBITS;
mask = (1UL<<shift) - 1;
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
this_subnet = get_subnet(addr, bits_consumed);
bits_consumed += NBITS;
if (!subnet->entry[this_subnet]) {
return NULL;
} 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
CLG_LogNTPClientAccess (CLG_IP_Addr client, time_t now)
CLG_LogNTPClientAccess (IPAddr *client, time_t now)
{
uint32_t ip6[4];
Node *node;
if (active) {
node = (Node *) find_subnet(&top_subnet, client, 32);
node->ip_addr = client;
switch (client->family) {
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->last_ntp_hit = now;
}
@ -258,12 +284,25 @@ CLG_LogNTPClientAccess (CLG_IP_Addr client, time_t now)
/* ================================================== */
void
CLG_LogNTPPeerAccess(CLG_IP_Addr client, time_t now)
CLG_LogNTPPeerAccess(IPAddr *client, time_t now)
{
uint32_t ip6[4];
Node *node;
if (active) {
node = (Node *) find_subnet(&top_subnet, client, 32);
node->ip_addr = client;
switch (client->family) {
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->last_ntp_hit = now;
}
@ -272,12 +311,25 @@ CLG_LogNTPPeerAccess(CLG_IP_Addr client, time_t now)
/* ================================================== */
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;
if (active) {
node = (Node *) find_subnet(&top_subnet, client, 32);
node->ip_addr = client;
switch (client->family) {
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;
switch (type) {
case CLG_CMD_AUTH:
@ -299,16 +351,32 @@ CLG_LogCommandAccess(CLG_IP_Addr client, CLG_Command_Type type, time_t now)
/* ================================================== */
CLG_Status
CLG_GetSubnetBitmap(CLG_IP_Addr subnet, int bits, CLG_Bitmap result)
CLG_GetSubnetBitmap(IPAddr *subnet, int bits, CLG_Bitmap result)
{
Subnet *s;
uint32_t ip6[4];
unsigned long i;
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);
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) {
for (i=0; i<256; i++) {
if (s->entry[i]) {
@ -333,14 +401,25 @@ CLG_GetSubnetBitmap(CLG_IP_Addr subnet, int bits, CLG_Bitmap result)
/* ================================================== */
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;
if (!active) {
return CLG_INACTIVE;
} 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) {
return CLG_EMPTYSUBNET;

View file

@ -35,15 +35,13 @@
#include "sysincl.h"
#include "reports.h"
typedef unsigned long CLG_IP_Addr;
/* Enough to hold flags for 256 hosts in a class C */
typedef uint32_t CLG_Bitmap[8];
extern void CLG_Initialise(void);
extern void CLG_Finalise(void);
extern void CLG_LogNTPClientAccess(CLG_IP_Addr client, time_t now);
extern void CLG_LogNTPPeerAccess(CLG_IP_Addr client, time_t now);
extern void CLG_LogNTPClientAccess(IPAddr *client, time_t now);
extern void CLG_LogNTPPeerAccess(IPAddr *client, time_t now);
/* When logging command packets, there are several subtypes */
@ -53,7 +51,7 @@ typedef enum {
CLG_CMD_BAD_PKT /* bad version or packet length */
} 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. */
/* TBD */
@ -70,10 +68,10 @@ typedef enum {
known. For bits=24, flag which hosts in that subnet are known.
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
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_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'. */
extern void CLG_IterateNTPClients
(void (*fn)(CLG_IP_Addr client, void *arb),
(void (*fn)(IPAddr *client, void *arb),
void *arb,
time_t since);

408
cmdmon.c
View file

@ -54,8 +54,19 @@
/* ================================================== */
/* File descriptor for command and monitoring socket */
static int sock_fd;
union sockaddr_in46 {
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 */
static int initialised = 0;
@ -157,17 +168,93 @@ static ADF_AuthTable access_auth_table;
/* ================================================== */
/* Forward prototypes */
static int prepare_socket(int family);
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
CAM_Initialise(void)
{
int port_number;
struct sockaddr_in my_addr;
unsigned long bind_address;
int on_off = 1;
if (initialised) {
CROAK("Shouldn't be initialised");
@ -188,40 +275,19 @@ CAM_Initialise(void)
free_replies = NULL;
kept_replies.next = NULL;
port_number = CNF_GetCommandPort();
if (port_number < 0) {
port_number = DEFAULT_CANDM_PORT;
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_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();
}
@ -231,9 +297,18 @@ CAM_Initialise(void)
void
CAM_Finalise(void)
{
SCH_RemoveInputFileHandler(sock_fd);
close(sock_fd);
sock_fd = -1;
if (sock_fd4 >= 0) {
SCH_RemoveInputFileHandler(sock_fd4);
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);
@ -644,21 +719,51 @@ print_reply_packet(CMD_Reply *pkt)
/* ================================================== */
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 tx_message_length;
unsigned long remote_ip;
unsigned short remote_port;
int sock_fd;
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);
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) {
remote_ip = ntohl(where_to->sin_addr.s_addr);
remote_port = ntohs(where_to->sin_port);
LOG(LOGS_WARN, LOGF_CmdMon, "Could not send response to %s:%hu", UTI_IPToDottedQuad(remote_ip), remote_port);
unsigned short port;
IPAddr ip;
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;
@ -679,7 +784,10 @@ static void
handle_online(CMD_Request *rx_message, CMD_Reply *tx_message)
{
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) {
tx_message->status = htons(STT_SUCCESS);
} else {
@ -693,7 +801,10 @@ static void
handle_offline(CMD_Request *rx_message, CMD_Reply *tx_message)
{
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) {
tx_message->status = htons(STT_SUCCESS);
} else {
@ -707,10 +818,12 @@ static void
handle_burst(CMD_Request *rx_message, CMD_Reply *tx_message)
{
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),
ntohl(rx_message->data.burst.n_total_samples),
ntohl(rx_message->data.burst.mask),
ntohl(rx_message->data.burst.address));
&mask, &address);
if (status) {
tx_message->status = htons(STT_SUCCESS);
@ -725,7 +838,9 @@ static void
handle_modify_minpoll(CMD_Request *rx_message, CMD_Reply *tx_message)
{
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));
if (status) {
@ -741,7 +856,9 @@ static void
handle_modify_maxpoll(CMD_Request *rx_message, CMD_Reply *tx_message)
{
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));
if (status) {
@ -757,7 +874,9 @@ static void
handle_modify_maxdelay(CMD_Request *rx_message, CMD_Reply *tx_message)
{
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));
if (status) {
tx_message->status = htons(STT_SUCCESS);
@ -772,7 +891,9 @@ static void
handle_modify_maxdelayratio(CMD_Request *rx_message, CMD_Reply *tx_message)
{
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));
if (status) {
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->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.poll = htons(report.poll);
switch (report.state) {
@ -943,11 +1064,11 @@ handle_rekey(CMD_Request *rx_message, CMD_Reply *tx_message)
static void
handle_allow(CMD_Request *rx_message, CMD_Reply *tx_message)
{
unsigned long ip;
IPAddr ip;
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);
if (NCR_AddAccessRestriction(ip, subnet_bits, 1, 0)) {
if (NCR_AddAccessRestriction(&ip, subnet_bits, 1, 0)) {
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_BADSUBNET);
@ -959,11 +1080,11 @@ handle_allow(CMD_Request *rx_message, CMD_Reply *tx_message)
static void
handle_allowall(CMD_Request *rx_message, CMD_Reply *tx_message)
{
unsigned long ip;
IPAddr ip;
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);
if (NCR_AddAccessRestriction(ip, subnet_bits, 1, 1)) {
if (NCR_AddAccessRestriction(&ip, subnet_bits, 1, 1)) {
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_BADSUBNET);
@ -975,11 +1096,11 @@ handle_allowall(CMD_Request *rx_message, CMD_Reply *tx_message)
static void
handle_deny(CMD_Request *rx_message, CMD_Reply *tx_message)
{
unsigned long ip;
IPAddr ip;
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);
if (NCR_AddAccessRestriction(ip, subnet_bits, 0, 0)) {
if (NCR_AddAccessRestriction(&ip, subnet_bits, 0, 0)) {
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_BADSUBNET);
@ -991,11 +1112,11 @@ handle_deny(CMD_Request *rx_message, CMD_Reply *tx_message)
static void
handle_denyall(CMD_Request *rx_message, CMD_Reply *tx_message)
{
unsigned long ip;
IPAddr ip;
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);
if (NCR_AddAccessRestriction(ip, subnet_bits, 0, 1)) {
if (NCR_AddAccessRestriction(&ip, subnet_bits, 0, 1)) {
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_BADSUBNET);
@ -1007,11 +1128,11 @@ handle_denyall(CMD_Request *rx_message, CMD_Reply *tx_message)
static void
handle_cmdallow(CMD_Request *rx_message, CMD_Reply *tx_message)
{
unsigned long ip;
IPAddr ip;
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);
if (CAM_AddAccessRestriction(ip, subnet_bits, 1, 0)) {
if (CAM_AddAccessRestriction(&ip, subnet_bits, 1, 0)) {
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_BADSUBNET);
@ -1023,11 +1144,11 @@ handle_cmdallow(CMD_Request *rx_message, CMD_Reply *tx_message)
static void
handle_cmdallowall(CMD_Request *rx_message, CMD_Reply *tx_message)
{
unsigned long ip;
IPAddr ip;
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);
if (CAM_AddAccessRestriction(ip, subnet_bits, 1, 1)) {
if (CAM_AddAccessRestriction(&ip, subnet_bits, 1, 1)) {
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_BADSUBNET);
@ -1039,11 +1160,11 @@ handle_cmdallowall(CMD_Request *rx_message, CMD_Reply *tx_message)
static void
handle_cmddeny(CMD_Request *rx_message, CMD_Reply *tx_message)
{
unsigned long ip;
IPAddr ip;
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);
if (CAM_AddAccessRestriction(ip, subnet_bits, 0, 0)) {
if (CAM_AddAccessRestriction(&ip, subnet_bits, 0, 0)) {
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_BADSUBNET);
@ -1055,11 +1176,11 @@ handle_cmddeny(CMD_Request *rx_message, CMD_Reply *tx_message)
static void
handle_cmddenyall(CMD_Request *rx_message, CMD_Reply *tx_message)
{
unsigned long ip;
IPAddr ip;
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);
if (CAM_AddAccessRestriction(ip, subnet_bits, 0, 1)) {
if (CAM_AddAccessRestriction(&ip, subnet_bits, 0, 1)) {
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_BADSUBNET);
@ -1071,9 +1192,9 @@ handle_cmddenyall(CMD_Request *rx_message, CMD_Reply *tx_message)
static void
handle_accheck(CMD_Request *rx_message, CMD_Reply *tx_message)
{
unsigned long ip;
ip = ntohl(rx_message->data.ac_check.ip);
if (NCR_CheckAccessRestriction(ip)) {
IPAddr ip;
UTI_IPNetworkToHost(&rx_message->data.ac_check.ip, &ip);
if (NCR_CheckAccessRestriction(&ip)) {
tx_message->status = htons(STT_ACCESSALLOWED);
} else {
tx_message->status = htons(STT_ACCESSDENIED);
@ -1085,9 +1206,9 @@ handle_accheck(CMD_Request *rx_message, CMD_Reply *tx_message)
static void
handle_cmdaccheck(CMD_Request *rx_message, CMD_Reply *tx_message)
{
unsigned long ip;
ip = ntohl(rx_message->data.ac_check.ip);
if (CAM_CheckAccessRestriction(ip)) {
IPAddr ip;
UTI_IPNetworkToHost(&rx_message->data.ac_check.ip, &ip);
if (CAM_CheckAccessRestriction(&ip)) {
tx_message->status = htons(STT_ACCESSALLOWED);
} else {
tx_message->status = htons(STT_ACCESSDENIED);
@ -1103,8 +1224,8 @@ handle_add_server(CMD_Request *rx_message, CMD_Reply *tx_message)
SourceParameters params;
NSR_Status status;
rem_addr.ip_addr = ntohl(rx_message->data.ntp_source.ip_addr);
rem_addr.local_ip_addr = 0;
UTI_IPNetworkToHost(&rx_message->data.ntp_source.ip_addr, &rem_addr.ip_addr);
rem_addr.local_ip_addr.family = IPADDR_UNSPEC;
rem_addr.port = (unsigned short)(ntohl(rx_message->data.ntp_source.port));
params.minpoll = ntohl(rx_message->data.ntp_source.minpoll);
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:
tx_message->status = htons(STT_TOOMANYSOURCES);
break;
case NSR_InvalidAF:
tx_message->status = htons(STT_INVALIDAF);
break;
case NSR_NoSuchSource:
CROAK("Impossible");
break;
@ -1140,8 +1264,8 @@ handle_add_peer(CMD_Request *rx_message, CMD_Reply *tx_message)
SourceParameters params;
NSR_Status status;
rem_addr.ip_addr = ntohl(rx_message->data.ntp_source.ip_addr);
rem_addr.local_ip_addr = 0;
UTI_IPNetworkToHost(&rx_message->data.ntp_source.ip_addr, &rem_addr.ip_addr);
rem_addr.local_ip_addr.family = IPADDR_UNSPEC;
rem_addr.port = (unsigned short)(ntohl(rx_message->data.ntp_source.port));
params.minpoll = ntohl(rx_message->data.ntp_source.minpoll);
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:
tx_message->status = htons(STT_TOOMANYSOURCES);
break;
case NSR_InvalidAF:
tx_message->status = htons(STT_INVALIDAF);
break;
case NSR_NoSuchSource:
CROAK("Impossible");
break;
@ -1175,8 +1302,8 @@ handle_del_source(CMD_Request *rx_message, CMD_Reply *tx_message)
NTP_Remote_Address rem_addr;
NSR_Status status;
rem_addr.ip_addr = ntohl(rx_message->data.del_source.ip_addr);
rem_addr.local_ip_addr = 0;
UTI_IPNetworkToHost(&rx_message->data.del_source.ip_addr, &rem_addr.ip_addr);
rem_addr.local_ip_addr.family = IPADDR_UNSPEC;
rem_addr.port = 0;
status = NSR_RemoveSource(&rem_addr);
@ -1189,6 +1316,7 @@ handle_del_source(CMD_Request *rx_message, CMD_Reply *tx_message)
break;
case NSR_TooManySources:
case NSR_AlreadyInUse:
case NSR_InvalidAF:
CROAK("Impossible");
break;
}
@ -1273,7 +1401,7 @@ handle_sourcestats(CMD_Request *rx_message, CMD_Reply *tx_message)
if (status) {
tx_message->status = htons(STT_SUCCESS);
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_runs = htonl(report.n_runs);
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)
{
int i, j;
unsigned long ns;
unsigned long ip, bits_specd;
unsigned long ns, bits_specd;
IPAddr ip;
CLG_Status result;
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);
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);
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);
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) {
case CLG_SUCCESS:
case CLG_EMPTYSUBNET:
@ -1394,7 +1522,7 @@ handle_client_accesses(CMD_Request *rx_message, CMD_Reply *tx_message)
CLG_Status result;
RPT_ClientAccess_Report report;
unsigned long nc;
unsigned long ip;
IPAddr ip;
int i;
struct timeval now;
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));
for (i=0; i<nc; i++) {
ip = ntohl(rx_message->data.client_accesses.client_ips[i]);
tx_message->data.client_accesses.clients[i].ip = htonl(ip);
UTI_IPNetworkToHost(&rx_message->data.client_accesses.client_ips[i], &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) {
case CLG_SUCCESS:
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].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);
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;
case CLG_EMPTYSUBNET:
/* Signal back to the client that this single client address
was unknown, by specifying the zero ip address, which will
always be invalid (hopefully) */
tx_message->data.client_accesses.clients[i].ip = htonl(0);
was unknown */
ip.family = IPADDR_UNSPEC;
UTI_IPHostToNetwork(&ip, &tx_message->data.client_accesses.clients[i].ip);
break;
case CLG_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) {
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].peer_hits = htonl(report.peer_hits);
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_Reply tx_message, *prev_tx_message;
int rx_message_length, tx_message_length;
struct sockaddr_in where_from;
int sock_fd;
union sockaddr_in46 where_from;
socklen_t from_length;
unsigned long remote_ip;
IPAddr remote_ip;
unsigned short remote_port;
int md5_ok;
int utoken_ok, token_ok;
@ -1617,14 +1746,14 @@ read_from_cmd_socket(void *anything)
rx_message_length = sizeof(rx_message);
from_length = sizeof(where_from);
sock_fd = (long)anything;
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) {
LOG(LOGS_WARN, LOGF_CmdMon, "Error [%s] reading from control socket (IP=%s port=%d)",
strerror(errno),
UTI_IPToDottedQuad(ntohl(where_from.sin_addr.s_addr)),
ntohs(where_from.sin_port));
LOG(LOGS_WARN, LOGF_CmdMon, "Error [%s] reading from control socket %d",
strerror(errno), sock_fd);
return;
}
read_length = status;
@ -1650,12 +1779,31 @@ read_from_cmd_socket(void *anything)
tx_message.token = htonl(0xffffffffUL);
memset(&tx_message.auth, 0, sizeof(tx_message.auth));
remote_ip = ntohl(where_from.sin_addr.s_addr);
remote_port = ntohs(where_from.sin_port);
switch (where_from.u.sa_family) {
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)) {
/* The client is not allowed access, so don't waste any more time
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. */
LOG(LOGS_WARN, LOGF_CmdMon, "Command packet received from unauthorised host %s port %d",
UTI_IPToDottedQuad(remote_ip),
UTI_IPToString(&remote_ip),
remote_port);
tx_message.status = htons(STT_NOHOSTACCESS);
@ -1678,8 +1826,8 @@ read_from_cmd_socket(void *anything)
if (read_length != expected_length) {
LOG(LOGS_WARN, LOGF_CmdMon, "Read incorrectly sized packet from %s:%hu", UTI_IPToDottedQuad(remote_ip), remote_port);
CLG_LogCommandAccess(remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec);
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);
/* For now, just ignore the packet. We may want to send a reply
back eventually */
return;
@ -1691,7 +1839,7 @@ read_from_cmd_socket(void *anything)
(rx_message.res2 != 0)) {
/* 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;
}
@ -1773,7 +1921,7 @@ read_from_cmd_socket(void *anything)
status = sendto(sock_fd, (void *) prev_tx_message, tx_message_length, 0,
(struct sockaddr *) &where_from, sizeof(where_from));
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;
}
@ -1800,9 +1948,9 @@ read_from_cmd_socket(void *anything)
authenticated = md5_ok & utoken_ok & token_ok;
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 {
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) {
@ -1895,7 +2043,7 @@ read_from_cmd_socket(void *anything)
if (!issue_token) {
LOG(LOGS_WARN, LOGF_CmdMon,
"Bad command logon from %s port %d (md5_ok=%d valid_ts=%d)\n",
UTI_IPToDottedQuad(remote_ip),
UTI_IPToString(&remote_ip),
remote_port,
md5_ok, valid_ts);
}
@ -2092,7 +2240,7 @@ read_from_cmd_socket(void *anything)
/* ================================================== */
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;
@ -2122,7 +2270,7 @@ CAM_AddAccessRestriction(unsigned long ip_addr, int subnet_bits, int allow, int
/* ================================================== */
int
CAM_CheckAccessRestriction(unsigned long ip_addr)
CAM_CheckAccessRestriction(IPAddr *ip_addr)
{
return ADF_IsAllowed(access_auth_table, ip_addr);
}

View file

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

View file

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

View file

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

181
conf.c
View file

@ -53,6 +53,7 @@
#include "acquire.h"
#include "cmdparse.h"
#include "broadcast.h"
#include "util.h"
/* ================================================== */
@ -136,7 +137,7 @@ static int n_init_srcs;
than this, slew instead of stepping */
static int init_slew_threshold = -1;
#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;
@ -156,13 +157,13 @@ static double mail_change_threshold = 0.0;
memory */
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 */
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 */
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
* chronyds being started. */
@ -243,7 +244,7 @@ typedef enum {
typedef struct {
NTP_Source_Type type;
unsigned long ip_addr;
IPAddr ip_addr;
unsigned short port;
SourceParameters params;
} NTP_Source;
@ -263,7 +264,7 @@ static int n_refclock_sources = 0;
typedef struct _AllowDeny {
struct _AllowDeny *next;
struct _AllowDeny *prev;
unsigned long ip;
IPAddr ip;
int subnet_bits;
int all; /* 1 to override existing more specific defns */
int allow; /* 0 for deny, 1 for allow */
@ -697,7 +698,7 @@ parse_initstepslew(const char *line)
char hostname[HOSTNAME_LEN+1];
int n;
int threshold;
unsigned long ip_addr;
IPAddr ip_addr;
n_init_srcs = 0;
p = line;
@ -710,8 +711,7 @@ parse_initstepslew(const char *line)
}
while (*p) {
if (sscanf(p, "%" SHOSTNAME_LEN "s%n", hostname, &n) == 1) {
ip_addr = DNS_Name2IPAddressRetry(hostname);
if (ip_addr != DNS_Failed_Address) {
if (DNS_Name2IPAddress(hostname, &ip_addr, 1)) {
init_srcs_ip[n_init_srcs] = ip_addr;
++n_init_srcs;
}
@ -803,7 +803,7 @@ parse_allow_deny(const char *line, AllowDeny *list, int allow)
unsigned long a, b, c, d, n;
int all = 0;
AllowDeny *new_node = NULL;
unsigned long ip_addr;
IPAddr ip_addr;
p = line;
@ -820,45 +820,54 @@ parse_allow_deny(const char *line, AllowDeny *list, int allow)
new_node = MallocNew(AllowDeny);
new_node->allow = allow;
new_node->all = all;
new_node->ip = 0UL;
new_node->ip.family = IPADDR_UNSPEC;
new_node->subnet_bits = 0;
} else {
char *slashpos;
slashpos = strchr(p, '/');
if (slashpos) *slashpos = 0;
n = sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d);
if (n >= 1) {
n = 0;
if (UTI_StringToIP(p, &ip_addr) ||
(n = sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d)) >= 1) {
new_node = MallocNew(AllowDeny);
new_node->allow = allow;
new_node->all = all;
a &= 0xff;
b &= 0xff;
c &= 0xff;
d &= 0xff;
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;
if (n == 0) {
new_node->ip = ip_addr;
if (ip_addr.family == IPADDR_INET6)
new_node->subnet_bits = 128;
else
new_node->subnet_bits = 32;
break;
default:
assert(0);
} else {
new_node->ip.family = IPADDR_INET4;
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) {
@ -872,13 +881,15 @@ parse_allow_deny(const char *line, AllowDeny *list, int allow)
}
} else {
ip_addr = DNS_Name2IPAddressRetry(p);
if (ip_addr != DNS_Failed_Address) {
if (DNS_Name2IPAddress(p, &ip_addr, 1)) {
new_node = MallocNew(AllowDeny);
new_node->allow = allow;
new_node->all = all;
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 {
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
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
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 {
/* Both in host (not necessarily network) order */
unsigned long addr;
IPAddr addr;
unsigned short port;
int interval;
} NTP_Broadcast_Destination;
@ -992,27 +1006,22 @@ parse_broadcast(const char *line)
{
/* Syntax : broadcast <interval> <broadcast-IP-addr> [<port>] */
int port;
unsigned int a, b, c, d;
int n;
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);
if (n < 5) {
n = sscanf(line, "%d %50s %d", &interval, addr, &port);
if (n < 2 || !UTI_StringToIP(addr, &ip)) {
LOG(LOGS_WARN, LOGF_Configure, "Could not parse broadcast directive at line %d", line_number);
return;
} else if (n == 5) {
} else if (n == 2) {
/* default port */
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);
}
addr = ((unsigned long) a << 24) |
((unsigned long) b << 16) |
((unsigned long) c << 8) |
((unsigned long) d );
if (max_broadcasts == n_broadcasts) {
/* Expand array */
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].interval = interval;
++n_broadcasts;
@ -1074,7 +1083,7 @@ CNF_AddSources(void) {
for (i=0; i<n_ntp_sources; i++) {
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;
switch (ntp_sources[i].type) {
@ -1111,7 +1120,7 @@ CNF_AddBroadcasts(void)
{
int i;
for (i=0; i<n_broadcasts; i++) {
BRD_AddDestination(broadcasts[i].addr,
BRD_AddDestination(&broadcasts[i].addr,
broadcasts[i].port,
broadcasts[i].interval);
}
@ -1307,14 +1316,14 @@ CNF_SetupAccessRestrictions(void)
int status;
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) {
LOG(LOGS_WARN, LOGF_Configure, "Bad subnet for %08lx", node->ip);
}
}
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) {
LOG(LOGS_WARN, LOGF_Configure, "Bad subnet for %08lx", node->ip);
}
@ -1334,17 +1343,27 @@ CNF_GetNoClientLog(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
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
#define GOT_CONF_H
#include "addressing.h"
extern char *CNF_GetRtcDevice(void);
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_GetMailOnChange(int *enabled, double *threshold, char **user);
extern int CNF_GetNoClientLog(void);
extern void CNF_GetBindAddress(unsigned long *addr);
extern void CNF_GetBindCommandAddress(unsigned long *addr);
extern void CNF_GetBindAddress(int family, IPAddr *addr);
extern void CNF_GetBindCommandAddress(int family, IPAddr *addr);
extern char *CNF_GetPidFile(void);
extern void CNF_GetLinuxHz(int *set, int *hz);
extern void CNF_GetLinuxFreqScale(int *set, double *freq_scale);

39
configure vendored
View file

@ -106,6 +106,32 @@ EOF
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 () {
cat <<EOF;
@ -134,6 +160,7 @@ For better control, use the options below.
--readline-inc-dir=DIR Specify where readline include directory is
--readline-lib-dir=DIR Specify where readline 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
--enable-linuxcaps Enable Linux capabilities support
@ -181,6 +208,7 @@ feat_linuxcaps=0
readline_lib=""
readline_inc=""
ncurses_lib=""
feat_ipv6=1
SETINFODIR=""
SETMANDIR=""
@ -218,6 +246,9 @@ do
--disable-rtc)
feat_rtc=0
;;
--disable-ipv6)
feat_ipv6=0
;;
--enable-linuxcaps)
feat_linuxcaps=1
;;
@ -339,6 +370,14 @@ else
printf "No\n"
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
CCWARNFLAGS="-Wmissing-prototypes -Wall"
else

View file

@ -32,85 +32,134 @@
#include "sysincl.h"
#include "nameserv.h"
#include "util.h"
#include <resolv.h>
/* ================================================== */
#define MAXRETRIES 10
static unsigned int retries = 0;
static unsigned long
Name2IPAddress(const char *name, int retry)
int
DNS_Name2IPAddress(const char *name, IPAddr *addr, int retry)
{
struct hostent *host;
unsigned char *address0;
unsigned long result;
#ifdef HAVE_IPV6
struct addrinfo hints, *res, *ai;
int result;
memset(&hints, 0, sizeof (hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_ADDRCONFIG;
try_again:
host = gethostbyname(name);
if (host == NULL) {
if (retry && h_errno == TRY_AGAIN && retries < 10) {
result = getaddrinfo(name, NULL, &hints, &res);
if (result) {
if (retry && result == EAI_AGAIN && retries < MAXRETRIES) {
sleep(2 << retries);
retries++;
res_init();
goto try_again;
}
result = DNS_Failed_Address;
} 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 0;
}
return result;
}
/* ================================================== */
unsigned long
DNS_Name2IPAddress(const char *name)
{
return Name2IPAddress(name, 0);
}
/* ================================================== */
unsigned long
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;
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);
result = 1;
break;
#ifdef HAVE_IPV6
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;
#endif
}
}
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
#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);
const char *DNS_IPAddress2Name(unsigned long ip_addr);
extern void DNS_IPAddress2Name(IPAddr *ip_addr, char *name, int len);
#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;
/* 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_usec = 0;
@ -626,7 +626,7 @@ transmit_timeout(void *arg)
#ifdef TRACEON
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
/* 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);
LOG(LOGS_INFO, LOGF_NtpCore, "Root delay=%08lx (%f), dispersion=%08lx (%f)",
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]",
UTI_IPToDottedQuad(ntohl(message->reference_id)),
LOG(LOGS_INFO, LOGF_NtpCore, "Ref id=[%lx], ref_time=%08lx.%08lx [%s]",
ntohl(message->reference_id),
message->reference_ts.hi, message->reference_ts.lo,
UTI_TimestampToString(&message->reference_ts));
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;
if (inst->minpoll > inst->local_poll)
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 */
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",
UTI_TimeToLogForm(sample_time.tv_sec),
UTI_IPToDottedQuad(inst->remote_addr.ip_addr),
UTI_IPToString(&inst->remote_addr.ip_addr),
sync_stats[pkt_leap],
message->stratum,
test1, test2, test3, test4,
@ -1357,9 +1357,9 @@ process_known
one of the secondaries to flywheel it. The behaviour coded here
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) {
auth_key_id = ntohl(message->auth_keyid);
@ -1392,7 +1392,7 @@ process_known
} else {
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);
}
@ -1403,7 +1403,7 @@ process_known
switch(inst->mode) {
case MODE_ACTIVE:
/* 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);
break;
case MODE_PASSIVE:
@ -1413,7 +1413,7 @@ process_known
case MODE_CLIENT:
/* This is where we have the remote configured as a server and he has
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);
break;
case MODE_SERVER:
@ -1434,7 +1434,7 @@ process_known
switch(inst->mode) {
case MODE_ACTIVE:
/* 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);
break;
case MODE_PASSIVE:
@ -1462,7 +1462,7 @@ process_known
case MODE_ACTIVE:
/* This would arise if we have the remote configured as a peer and
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);
break;
case MODE_PASSIVE:
@ -1524,19 +1524,19 @@ NCR_ProcessNoauthUnknown(NTP_Packet *message, struct timeval *now, NTP_Remote_Ad
NTP_Mode my_mode;
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;
if (his_mode == MODE_CLIENT) {
/* We are 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) {
/* We are symmetric passive, even though we don't ever lock to him */
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 {
my_mode = MODE_UNDEFINED;
@ -1560,7 +1560,7 @@ NCR_ProcessNoauthUnknown(NTP_Packet *message, struct timeval *now, NTP_Remote_Ad
}
} else {
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);
}
@ -1594,19 +1594,19 @@ NCR_ProcessAuthUnknown(NTP_Packet *message, struct timeval *now, NTP_Remote_Addr
int valid_key, valid_auth;
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;
if (his_mode == MODE_CLIENT) {
/* We are 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) {
/* We are symmetric passive, even though we don't ever lock to him */
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 {
my_mode = MODE_UNDEFINED;
@ -1678,7 +1678,7 @@ NCR_TakeSourceOnline(NCR_Instance inst)
case MD_OFFLINE:
if (!inst->timer_running) {
/* 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->score = (ZONE_WIDTH >> 1);
inst->opmode = MD_ONLINE;
@ -1702,7 +1702,7 @@ NCR_TakeSourceOffline(NCR_Instance inst)
switch (inst->opmode) {
case MD_ONLINE:
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);
inst->timer_running = 0;
inst->opmode = MD_OFFLINE;
@ -1725,7 +1725,7 @@ void
NCR_ModifyMinpoll(NCR_Instance inst, int 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)
{
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;
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;
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
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;
@ -1866,7 +1866,7 @@ NCR_AddAccessRestriction(unsigned long ip_addr, int subnet_bits, int allow, int
/* ================================================== */
int
NCR_CheckAccessRestriction(unsigned long ip_addr)
NCR_CheckAccessRestriction(IPAddr *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 int NCR_AddAccessRestriction(unsigned long ip_addr, int subnet_bits, int allow, int all);
extern int NCR_CheckAccessRestriction(unsigned long ip_addr);
extern int NCR_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all);
extern int NCR_CheckAccessRestriction(IPAddr *ip_addr);
extern void NCR_CycleLogFile(void);

204
ntp_io.c
View file

@ -41,8 +41,19 @@
#include <fcntl.h>
/* The file descriptor for the socket */
static int sock_fd;
union sockaddr_in46 {
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 */
static int initialised=0;
@ -50,6 +61,7 @@ static int initialised=0;
/* ================================================== */
/* Forward prototypes */
static int prepare_socket(int family);
static void read_from_socket(void *anything);
/* ================================================== */
@ -81,30 +93,28 @@ do_size_checks(void)
/* ================================================== */
void
NIO_Initialise(void)
static int
prepare_socket(int family)
{
struct sockaddr_in my_addr;
union sockaddr_in46 my_addr;
int sock_fd;
unsigned short port_number;
unsigned long bind_address;
IPAddr bind_address;
int on_off = 1;
assert(!initialised);
initialised = 1;
do_size_checks();
port_number = CNF_GetNTPPort();
/* Open Internet domain UDP socket for NTP message transmissions */
#if 0
sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
sock_fd = socket(family, SOCK_DGRAM, IPPROTO_UDP);
#else
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
sock_fd = socket(family, SOCK_DGRAM, 0);
#endif
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 */
@ -125,34 +135,67 @@ NIO_Initialise(void)
/* Don't quit - we might survive anyway */
}
/* We want the local IP info too */
if (setsockopt(sock_fd, IPPROTO_IP, IP_PKTINFO, (char *)&on_off, sizeof(on_off)) < 0) {
LOG(LOGS_ERR, LOGF_NtpIO, "Could not request packet info using socket option");
/* Don't quit - we might survive anyway */
if (family == AF_INET) {
/* We want the local IP info too */
if (setsockopt(sock_fd, IPPROTO_IP, IP_PKTINFO, (char *)&on_off, sizeof(on_off)) < 0) {
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 */
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(port_number);
memset(&my_addr, 0, sizeof (my_addr));
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) {
my_addr.sin_addr.s_addr = htonl(bind_address);
} else {
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
CNF_GetBindAddress(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(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
LOG(LOGS_INFO, LOGF_NtpIO, "Initialising, socket fd=%d", sock_fd);
#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));
}
/* 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 (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");
}
#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;
}
@ -172,11 +238,18 @@ NIO_Initialise(void)
void
NIO_Finalise(void)
{
if (sock_fd >= 0) {
SCH_RemoveInputFileHandler(sock_fd);
close(sock_fd);
if (sock_fd4 >= 0) {
SCH_RemoveInputFileHandler(sock_fd4);
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;
return;
}
@ -192,9 +265,9 @@ read_from_socket(void *anything)
/* This should only be called when there is something
to read, otherwise it will block. */
int status;
int status, sock_fd;
ReceiveBuffer message;
struct sockaddr_in where_from;
union sockaddr_in46 where_from;
unsigned int flags = 0;
struct timeval now;
NTP_Remote_Address remote_addr;
@ -218,6 +291,7 @@ read_from_socket(void *anything)
msg.msg_controllen = sizeof(cmsgbuf);
msg.msg_flags = 0;
sock_fd = (long)anything;
status = recvmsg(sock_fd, &msg, flags);
/* 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). */
if (status > 0) {
remote_addr.ip_addr = ntohl(where_from.sin_addr.s_addr);
remote_addr.local_ip_addr = 0;
remote_addr.port = ntohs(where_from.sin_port);
memset(&remote_addr, 0, sizeof (remote_addr));
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)) {
if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) {
struct in_pktinfo 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) {
@ -279,22 +370,43 @@ read_from_socket(void *anything)
static void
send_packet(void *packet, int packetlen, NTP_Remote_Address *remote_addr)
{
struct sockaddr_in remote;
union sockaddr_in46 remote;
struct msghdr msg;
struct iovec iov;
struct cmsghdr *cmsg;
char cmsgbuf[256];
int cmsglen;
int sock_fd;
assert(initialised);
remote.sin_family = AF_INET;
remote.sin_port = htons(remote_addr->port);
remote.sin_addr.s_addr = htonl(remote_addr->ip_addr);
memset(&remote, 0, sizeof (remote));
switch (remote_addr->ip_addr.family) {
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_len = packetlen;
msg.msg_name = &remote;
msg.msg_name = &remote.u;
msg.msg_namelen = sizeof(remote);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
@ -303,7 +415,7 @@ send_packet(void *packet, int packetlen, NTP_Remote_Address *remote_addr)
msg.msg_flags = 0;
cmsglen = 0;
if (remote_addr->local_ip_addr) {
if (remote_addr->local_ip_addr.family == IPADDR_INET4) {
struct in_pktinfo *ipi;
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));
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
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
}
@ -326,7 +438,7 @@ send_packet(void *packet, int packetlen, NTP_Remote_Address *remote_addr)
if (sendmsg(sock_fd, &msg, 0) < 0) {
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;

View file

@ -120,17 +120,36 @@ static void
find_slot(NTP_Remote_Address *remote_addr, int *slot, int *found)
{
unsigned long hash;
unsigned long ip = remote_addr->ip_addr;
unsigned short port = remote_addr->port;
unsigned long ip;
unsigned short port;
uint8_t *ip6;
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 */
hash = ip ^ (ip >> 16);
hash = (hash ^ (hash >> 8)) & 0xff;
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++;
if (hash == 256) hash = 0;
}
@ -162,7 +181,7 @@ NSR_AddServer(NTP_Remote_Address *remote_addr, SourceParameters *params)
assert(initialised);
#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
/* 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 {
if (n_sources == MAX_SOURCES) {
return NSR_TooManySources;
} else if (remote_addr->ip_addr.family != IPADDR_INET4 &&
remote_addr->ip_addr.family != IPADDR_INET6) {
return NSR_InvalidAF;
} else {
n_sources++;
records[slot].remote_addr = *remote_addr;
@ -193,7 +215,7 @@ NSR_AddPeer(NTP_Remote_Address *remote_addr, SourceParameters *params)
assert(initialised);
#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
/* 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 {
if (n_sources == MAX_SOURCES) {
return NSR_TooManySources;
} else if (remote_addr->ip_addr.family != IPADDR_INET4 &&
remote_addr->ip_addr.family != IPADDR_INET6) {
return NSR_InvalidAF;
} else {
n_sources++;
records[slot].remote_addr = *remote_addr;
@ -249,7 +274,7 @@ NSR_ProcessReceive(NTP_Packet *message, struct timeval *now, NTP_Remote_Address
#if 0
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));
#endif
@ -296,7 +321,7 @@ slew_sources(struct timeval *raw,
if (records[i].in_use) {
#if 0
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
NCR_SlewTimes(records[i].data, cooked, dfreq, doffset);
@ -308,17 +333,16 @@ slew_sources(struct timeval *raw,
/* ================================================== */
int
NSR_TakeSourcesOnline(unsigned long mask, unsigned long address)
NSR_TakeSourcesOnline(IPAddr *mask, IPAddr *address)
{
int i;
int any;
unsigned long ip;
any = 0;
for (i=0; i<N_RECORDS; i++) {
if (records[i].in_use) {
ip = records[i].remote_addr.ip_addr;
if ((ip & mask) == address) {
if (address->family == IPADDR_UNSPEC ||
!UTI_CompareIPs(&records[i].remote_addr.ip_addr, address, mask)) {
any = 1;
NCR_TakeSourceOnline(records[i].data);
}
@ -331,17 +355,16 @@ NSR_TakeSourcesOnline(unsigned long mask, unsigned long address)
/* ================================================== */
int
NSR_TakeSourcesOffline(unsigned long mask, unsigned long address)
NSR_TakeSourcesOffline(IPAddr *mask, IPAddr *address)
{
int i;
int any;
unsigned long ip;
any = 0;
for (i=0; i<N_RECORDS; i++) {
if (records[i].in_use) {
ip = records[i].remote_addr.ip_addr;
if ((ip & mask) == address) {
if (address->family == IPADDR_UNSPEC ||
!UTI_CompareIPs(&records[i].remote_addr.ip_addr, address, mask)) {
any = 1;
NCR_TakeSourceOffline(records[i].data);
}
@ -354,11 +377,11 @@ NSR_TakeSourcesOffline(unsigned long mask, unsigned long address)
/* ================================================== */
int
NSR_ModifyMinpoll(unsigned long address, int new_minpoll)
NSR_ModifyMinpoll(IPAddr *address, int new_minpoll)
{
int slot, found;
NTP_Remote_Address addr;
addr.ip_addr = address;
addr.ip_addr = *address;
addr.port = 0;
find_slot(&addr, &slot, &found);
@ -373,11 +396,11 @@ NSR_ModifyMinpoll(unsigned long address, int new_minpoll)
/* ================================================== */
int
NSR_ModifyMaxpoll(unsigned long address, int new_maxpoll)
NSR_ModifyMaxpoll(IPAddr *address, int new_maxpoll)
{
int slot, found;
NTP_Remote_Address addr;
addr.ip_addr = address;
addr.ip_addr = *address;
addr.port = 0;
find_slot(&addr, &slot, &found);
@ -392,11 +415,11 @@ NSR_ModifyMaxpoll(unsigned long address, int new_maxpoll)
/* ================================================== */
int
NSR_ModifyMaxdelay(unsigned long address, double new_max_delay)
NSR_ModifyMaxdelay(IPAddr *address, double new_max_delay)
{
int slot, found;
NTP_Remote_Address addr;
addr.ip_addr = address;
addr.ip_addr = *address;
addr.port = 0;
find_slot(&addr, &slot, &found);
@ -411,11 +434,11 @@ NSR_ModifyMaxdelay(unsigned long address, double new_max_delay)
/* ================================================== */
int
NSR_ModifyMaxdelayratio(unsigned long address, double new_max_delay_ratio)
NSR_ModifyMaxdelayratio(IPAddr *address, double new_max_delay_ratio)
{
int slot, found;
NTP_Remote_Address addr;
addr.ip_addr = address;
addr.ip_addr = *address;
addr.port = 0;
find_slot(&addr, &slot, &found);
@ -431,17 +454,16 @@ NSR_ModifyMaxdelayratio(unsigned long address, double new_max_delay_ratio)
int
NSR_InitiateSampleBurst(int n_good_samples, int n_total_samples,
unsigned long mask, unsigned long address)
IPAddr *mask, IPAddr *address)
{
int i;
int any;
unsigned long ip;
any = 0;
for (i=0; i<N_RECORDS; i++) {
if (records[i].in_use) {
ip = records[i].remote_addr.ip_addr;
if ((ip & mask) == address) {
if (address->family == IPADDR_UNSPEC ||
!UTI_CompareIPs(&records[i].remote_addr.ip_addr, address, mask)) {
any = 1;
NCR_InitiateSampleBurst(records[i].data, n_good_samples, n_total_samples);
}

View file

@ -46,7 +46,8 @@ typedef enum {
NSR_Success, /* Operation successful */
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_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;
/* 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
match a particular subnet should be set online again. Returns a
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
match a particular subnet should be set offline. Returns a flag
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);

View file

@ -172,7 +172,7 @@ RCL_StartRefclocks(void)
for (i = 0; i < n_sources; 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);
}
@ -186,7 +186,8 @@ RCL_ReportSource(RPT_SourceReport *report, struct timeval *now)
int i;
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++) {
RCL_Instance inst = &refclocks[i];

View file

@ -32,11 +32,12 @@
#define GOT_REPORTS_H
#include "sysincl.h"
#include "addressing.h"
#define REPORT_INVALID_OFFSET 0x80000000
typedef struct {
unsigned long ip_addr;
IPAddr ip_addr;
int stratum;
int poll;
enum {RPT_NTP_CLIENT, RPT_NTP_PEER, RPT_LOCAL_REFERENCE} mode;
@ -65,7 +66,7 @@ typedef struct {
} RPT_TrackingReport;
typedef struct {
unsigned long ip_addr;
IPAddr ip_addr;
unsigned long n_samples;
unsigned long n_runs;
unsigned long span_seconds;
@ -94,7 +95,7 @@ typedef struct {
} RPT_ClientAccess_Report;
typedef struct {
unsigned long ip_addr;
IPAddr ip_addr;
unsigned long client_hits;
unsigned long peer_hits;
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
(i.e. its IP address, NOT the
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
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
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;
@ -189,6 +190,7 @@ SRC_Instance SRC_CreateNewInstance(unsigned long ref_id, SRC_Type type)
result->index = n_sources;
result->leap_status = LEAP_Normal;
result->ref_id = ref_id;
result->ip_addr = addr;
result->reachable = 0;
result->status = SRC_BAD_STATS;
result->type = type;
@ -362,7 +364,7 @@ source_to_string(SRC_Instance inst)
{
switch (inst->type) {
case SRC_NTP:
return UTI_IPToDottedQuad(inst->ref_id);
return UTI_IPToString(inst->ip_addr);
case SRC_REFCLOCK:
return UTI_RefidToString(inst->ref_id);
default:
@ -912,7 +914,16 @@ SRC_ReportSource(int index, RPT_SourceReport *report, struct timeval *now)
return 0;
} else {
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) {
case SRC_SYNC:
report->state = RPT_SYNC;
@ -949,7 +960,10 @@ SRC_ReportSourcestats(int index, RPT_SourcestatsReport *report)
return 0;
} else {
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);
return 1;
}

View file

@ -58,7 +58,7 @@ typedef enum {
/* Function to create a new instance. This would be called by one of
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.
This may cause the current reference source to be reselected, if this

View file

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

164
util.c
View file

@ -31,6 +31,7 @@
#include "sysincl.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 *
UTI_TimeToLogForm(time_t t)
{

10
util.h
View file

@ -33,6 +33,7 @@
#include "sysincl.h"
#include "addressing.h"
#include "ntp.h"
/* 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 */
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_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);